vTaskDelay causes hard_fault unless I step trough it the first time on STM32

I’m trying to write some very basic code with freertos and libopencm3 to run on a STM32F7 Discovery Board.
To keep it simple I’m starting with a simple Blinky.
With that I was able to create a Task, that just runs gpio_toggle and this works, the LED gets dim.
Now adding vTaskDelay(1000) to the task results in some strange behaviour:
If I just run the code, it gets a hard_fault with IACCVIOL=1.
If I put a breakpoint at vTaskDelay(1000) and continue from there, it also gets a hard_fault.

But if I step into vTaskDelay(1000), step over all the Instructions inside vTaskDelay(1000), return to my Task function, remove the Breakpoint and let it continue, it just works.

Which STM32 are you using and which FreeRTOS port are you using (Cortex-M3 or 4). Does it have caches, or external memory?

Do you have configCHECK_FOR_STACK_OVERFLOW set to 2 and configASSERT defined?

Which version of the kernel are you using? Asking as different versions have different amount of assert points. Version number is at the top of the source files.

I am using the NUCLEO-F767ZI Board with first the ARM_CM7 and now the ARM_CM4F port.
Regarding caches or external memory I’m not sure, but I don’t see anything in my linker file besides RAM(384KB), ROM(2MB) and CCM(128KB) as per the STM32F767ZI Datasheet. There seems to be no external RAM on this board.

As for configCHECK_FOR_STACK_OVERFLOW, it is set to 2. configASSERT is just added to my FreeRTOSConfig.h as this (from here):

/* Define configASSERT() to disable interrupts and sit in a loop. */
#define configASSERT(x) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

I’m currently using the V10.4.1-kernel-only branch.

Are the FreeRTOS vectors installed correctly using #define? See #1 here:

According to https://www.st.com/en/microcontrollers-microprocessors/stm32f767zi.html the part does have a cache. Just to try and help track down the issue - try running the code with the cache disabled. If you step through the start up code you should see where the cache gets enabled, so the easiest thing to do would be just comment out those lines temporarily.

Also as this is a Cortex-M7, check the revision of the core. If it is an r0p1 core then you will have to use the FreeRTOS port from this directory as it contains some workarounds for some silicon errata: https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/5fb26de0194b4ebfd09b37128bf9f3ff6d34c1b7/portable/GCC/ARM_CM7/r0p1 - otherwise you should be able to use the port from this directory https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/5fb26de0194b4ebfd09b37128bf9f3ff6d34c1b7/portable/GCC/ARM_CM4F

Yes, I have that block in my FreeRTOSConfig.h file.

As it seems from here the STM32F76xx Series seems to use the r1P0 core, therefor I’m compiling it with the ARM_CM4F port.
Regarding the startup sequence I was unable to find much. The reset_vector is implemented in vectors.c of libopencm3 and I don’t see anything related to caches.

Which file is pre_main() implemented in - its not easy to find in github - is it specific to your CM7 device or a generic implementation from this git repo?

If you can share the complete project, that will helpful too.


Yeah, Intellisense be blessed: It’s defined in vector_chipset.c, which itself is included trough lib/dispatch/vector_chipset.c.

If it helps, sure: https://github.com/engelant/stm32-cmake

Those 3 #define statements assume the C library uses CMSIS names, but it seems libopencm3 does not. I suggest you remove opencm3.c from your project.

Then you can update the three #define statements in FreeRTOSConfig.h to use the libopencm3 names in the vector table, like this:

// Map FreeRTOS handlers to their libopencm3 names (not CMSIS names)
#define xPortPendSVHandler pend_sv_handler
#define vPortSVCHandler sv_call_handler
#define xPortSysTickHandler sys_tick_handler

The really important one is PendSV. xPortPendSVHandler() must be the actual ISR not just called by the ISR. Otherwise you can get context corruption.

Thank you very much, as you expected, it does work now.

1 Like