Hi,
I am currently working on programming a custom board that uses a STM32L4A6 microcontroller through the STM2Cube IDE and I seem to consistently get a hardfault error ( xPortStartScheduler() ) after the device runs for around 2 hours.
I’ve previously implemented a queue that used malloc and free and assumed that this may have caused a memory leak. After I omitted those functions and changed it to a circular buffer the device ran for around 4 hours but still goes into a hardfault error in the same location.
I haven’t used the malloc or free functions anywhere else in the code but I do route the printf to a UART peripheral.
I followed solution 2 from one of the other forum posts to help set up the FreeRTOS in the project: Undefined library functions - Libraries - FreeRTOS Community Forums
Hard to tell… this might have various reasons including broken HAL driver code if you’re using it.
Did you define configASSERT , enable stack overflow checking ?
Data corruptions can cause subtle error symptoms.
Maybe this hints also help a bit:
Hi,
Thank you for the reply. In the FreeRTOSConfig.h file the configAssert is defined as shown below:
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
/* USER CODE BEGIN 1 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
/* USER CODE END 1 */```
And from the .ioc file the Hook function related definition for CHECK_FOR_STACK_OVERFLOW is disabled.
There are a handful of C run-time library functions provided by newlib that are not thread safe unless you define configUSE_NEWLIB_REENTRANT to 1. Printf is one of them, but only with certain format specifiers. Additionally those functions use malloc internally, and newlib has not provided thread safety to malloc either, though they have made provision for you as the developer to provide the required locks. These issues can lead to memory corruption and hard faults. Just an idea if you haven’t already considered it.
As Hartmut says, the HAL can be tricky too. It is also not written to be thread safe. In general though you are pretty safe if you use any given HAL driver only from one task.
Hi,
Thank you for the reply.
The #define configUSE_NEWLIB_REENTRANT is set to 1 in the project and I will also look more into checking for stack overflows but since I’m fairly new to using FreeRTOS and STM32 could you please give emphasis on what you mean by locks that could help with the memory corruption and hard faults?
I don’t know what the .ioc file is, but if you have a problem then the first things to do are set configCHECK_FOR_STACK_OVERFLOW to 2 and define configASSERT() - it sounds like you only did one of those. Together they will catch most problems. Take a look here: https://freertos.org/FAQHelp.html - for example, are you calling NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); before the RTOS is started?
Thank you for the reply. I’ve set the CHECK_FOR_STACK_OVERFLOW TO 2 and configASSERT is already defined.
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
The NVIC_PriorityGroupConfig() is also called during the HAL initialisation which runs before the osKernelInitialise() is called.
I will make sure to go through the FAQ to see if I have missed anything else.
The malloc locks make malloc thread safe and are required if using malloc (used by newlib) in a multi threaded environment (FreeRTOS). You’ll want to implement __malloc_lock() and __malloc_unlock(). A common implementation is to call vTaskSuspendAll() for the lock function and to call vTaskResumeAll() for the unlock.
However, if you are using printf() from multiple tasks, and if printf() is directed to a UART that uses a driver that isn’t thread safe, that might be causing the corruption / hard faults. Can you test by removing all the printf() statements?
Hi,
Thank you for the reply. I will also try running the code without any printf’s just to see if that is the issue.
I use vTaskSuspendAll() and xTaskResumeAll() when I get readings from the sensors and sprintf the wifi json string but only at that part of the code since I’ve tried implementing it at other locations and they get stuck so I’ve refrained using it.