FreeRTOS kernel 11.0.1 and Picolibc with TLS

Hi!

I want to use FreeRTOS 11 (11.0.1) kernel with stm32f439zi microcontroller in a simple CubeIDE project.
I don’t use CMSIS-RTOS wrapper, only the native FreeRTOS API. I’m using the LL version of the STM32Cube drivers, as always.
The project has two versions:

  • the version compiled with STM32’s newlib-nano c library, linked with STM32’s linker script
  • and the version using the Picolibc library, using the Picolibc linker script

The newlib-nano version runs perfectly.
The Picolibc version crashes with HardFault in the “LL_RCC_HSE_IsReady()” function when running “SystemCoreClock_config()”.

The relevant options in FreeRTOSConfig.h:

#define PICOLIBC_TLS
#define configUSE_PICOLIBC_TLS 1

Configuration of picolibc.ld:

__flash = 0x08000000;
__flash_size = 2M;
__ram = 0x20000000;
__ram_size = 192k;
__ccmram = 0x10000000;
__ccmram_size = 64k;
__stack_size = 1k;

To make it work for FreeRTOS, I recompiled Picolibc 1.8.6 with the “-Dthread-local-storage=true” option.
The toolchain used are “gnu tools for stm32 12.3.rel1” and “arm gnu toolchain 13.2.Rel1”.
Of course I used Picolibc compiled with the given toolchain. For both toolchains the same result.
The project builds without error, but the MCU stops with the HardFault error mentioned above.

My specific question would be: how to correctly configure FreeRTOS 11 to work with Picolibc?

Many thanks!

Are you using HSE in your application? Can you step through the LL function that is crashing to see where it crashes specifically?

From your description, it sounds like you’re application is crashing before FreeRTOS even starts. Can you see if that is true?

Yes, I use an 8MHz external oscillator in the application, that’s why the HSE is used. I suspected that I was breaking something TLS specific in the linker script and that’s why the MCU crashes before the kernel starts.
This whole thread-local storage on microcontroller field is new to me. In desktop development I have no problem with it because there I don’t need to edit linker scripts :slight_smile: ,but in MCU it’s not trivial for me.

In the meantime, it turned out that the problem was caused by the STM32 “SystemInit()” function not running when using Picolibc.
This function is called by STM32’s Reset_Handler at the beginning of startup, but with Picolibc it runs its own crt0, not the STM32’s startup_stm32f439zitx.s.
This wouldn’t be a problem yet, but in my small test projects I don’t load programs into Flash but into RAM. I use an appropriately modified picolibc.ld for this purpose. So I also move the interrupt vector table to the front of RAM, but the SCB->VTOR is set in SystemInit. This was not done for Picolibc.
As a temporary solution, I set VTOR at the beginning of “main()” and now everything works!

If I use TLS-enabled Picolibc with FreeRTOS 11, do I need to pay attention to anything compared to the old newlib-nano version? Is there any example or documentation about this?

1 Like

Great catch. This is a good fix. Ideally picolib cstartup would have done this for you, but your fix is a clean fix.

No, it will work seamlessly. The best documentation is probably section 4.11 of the recently released v1.0 official FreeRTOS kernel book. https://freertos.org/Documentation/Mastering-the-FreeRTOS-Real-Time-Kernel.v1.0.pdf

2 Likes

Thank you very much for your help!

1 Like