2023-07-12 06:12 AM
Hello everyone,
I'm currently working with the STM32CubeIDE and I'm encountering an error after the new Update 1.13.1.
After using the printf function the following function in the newlib_lock_glue.c throws me into the Error_Handler in the main.c, after checking the lock for a NULL value.
__retarget_lock_acquire_recursive(_LOCK_T lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock); //This line results in the Error_Handler
stm32_lock_acquire(STM32_LOCK_PARAMETER(lock));
}
This behaviour just started after the version upgrade from 1.12.1 to 1.13.1 of the IDE.
I tried to change the MCU Toolchain settings to the older GNU Tools version (10.3.-2021.10)
now printf works just fine, but if I use the new GNU Tools version (11.3.rel1), which is
the new default setting of the IDE im encountering said Error.
How can this be avoided in the new version of the GNU Tools?
Maybe someone can help me with this issue.
Please inform me if you need further information.
Thanks in advance
2023-07-21 11:05 PM - edited 2023-07-21 11:22 PM
This is a bug in newlib that has since been fixed. Initialization of the lock in each standard stream was unintentionally removed during refactoring. It looks like ST noticed it a few weeks after the upstream 11.3.Rel1 release came out and submitted a patch to the newlib project. Unfortunately they did not include the fix in their newlib build nor add it to their list of known issues. You can verify by checking the disassembly of the std function. It doesn't call anything besides memset.
Here's a workaround:
#include <stdio.h>
#include <sys/lock.h>
// Insert this somewhere before first use of standard streams. One of the the
// user code sections near the top of main is a good place.
#if __NEWLIB__ == 4 && __NEWLIB_MINOR__ == 2 && __NEWLIB_PATCHLEVEL__ == 0 && !defined(__SINGLE_THREAD__)
// The version of newlib bundled with GNU Tools for STM32 11.3.rel1 fails to
// initialize the locks in the standard streams.
if (!stdin->_lock)
__lock_init_recursive(stdin->_lock);
if (!stdout->_lock)
__lock_init_recursive(stdout->_lock);
if (!stderr->_lock)
__lock_init_recursive(stderr->_lock);
#endif
Also, if you're using STM32_THREAD_SAFE_STRATEGY == 4, see the link that Piranha posted. It's not the problem here, but it is a problem. If you aren't using anything that requires a lock from an ISR, which you shouldn't be, switching to #5 is the easiest way to resolve it.
2023-07-24 02:41 AM
Wrong. The release note for CubeIDE 1.13 clearly states the exact version of the ARM GNU Toolchain version which is being shipped with CubeIDE.
" It doesn't contain the same error or we wouldn't be stuck in the __retarget_lock_acquire_recursive function defined in the project.I".
The default implementation obviously contains empty stubs because the default is non-thread aware. These weak stubs are overridden by the RTOS-aware implementation.
The same firmware package 1.18 for STM32L4 worked fine with CubeIDE 1.12.x. Thus the regression must come from the newer ARM GNU Toolchain.
Don't know if ST re-compiles it from the sources, and just forgot to configure it correctly, or the embedded Newlib has actually developed this regression.
2023-07-24 11:43 AM - edited 2023-08-04 08:55 PM
@KHors.1 wrote:Wrong. The release note for CubeIDE 1.13 clearly states the exact version of the ARM GNU Toolchain version wich is being shipped with CubeIDE.
...
Don't know if ST re-compiles it from the sources, and just forgot to configure it correctly, or the embedded Newlib has actually developed this regression.
The release notes say "based on". ST doesn't ship the unmodified ARM GNU Toolchain. Their distribution includes changes to GCC, newlib, the build scripts, and other things. A PDF containing a list of changes (but not the patches themselves) can be found within the IDE at Help > Information Center > STM32CubeIDE manuals > TOOLCHAIN MANUALS ([version]) > Patch List.
" It doesn't contain the same error or we wouldn't be stuck in the __retarget_lock_acquire_recursive function defined in the project.I".
The default implementation obviously contains empty stubs because the default is non-thread aware. These weak stubs are overridden by the RTOS-aware implementation.
The error that I was referring to was the one at the link—that newlib was built without --enable-newlib-retargetable-locking in the version 11 toolchain—not the overall issue discussed in this thread. That resulted in newlib neither providing weak stubs nor calling user provided locking functions. That problem is indeed not present in ST's 11.3 and was actually fixed upstream in 11.3 (see the newlib_configure line here).
Edit: Interestingly, the stubs are intentionally not weak in order to ensure that either all or none of the stubs are replaced. The reason you don't get a double definition error is because the linker only pulls in an object from an archive (library) if the object is needed to satisfy an undefined reference. A project that defines all the locking functions required by the functions it uses will not pull in the object with the stubs. A project that defines none of them will get the stubs. A project that defines some but not all of them will get both the stubs and its own definitions, triggering a double definition error at link time.
2023-08-08 04:46 AM
Is it possible get --wrap=std working as a workaround?
Tried it out but nothing happened - guessing because it's in an archive file (libc.a or libc_nano.a) and gets linked all at once.
2023-08-08 06:23 AM
Can also just install the previous toolchain easily enough...
2023-08-16 03:21 PM
Installing GNU Tools for STM32 version 10.3 worked perfectly for me. Printf stopped calling the error handler. Thanks!
2023-08-17 02:17 AM
Does anyone have a test that demonstrates correct working (or failing) of __retarget_lock_acquire_recursive and all this newlib locking, with FreeRTOS?
2023-08-21 04:38 PM
Still broken in 1.13.1, reverting my development environment again. (Thank you Apple, Time Machine is a good thing).
2023-09-25 07:01 AM
In the recent version of Cube IDE 1.13.2 the issue seems to be resolved for good.