FreeRTOS FAQ ¶
FreeRTOS configuration ¶
Which configuration files are essential for FreeRTOS on STM32?
FreeRTOSConfig.h: Configuration of the kernel: priorities, stack size, timers, etc.Main FreeRTOS source files:
tasks.c,queue.c,list.c,timers.c,event_groups.cCortex-M port files:
port.candportmacro.h
STM32Cube-level files:
Startup file:
startup_stm32xxxx.s(handlesPendSV,SysTick,SVC)system_stm32xxxx.c(system clock configuration)
How to initialize FreeRTOS with STM32CubeMX?
In STM32CubeMX:
Go to Middleware > FreeRTOS and activate FreeRTOS.
Configure:
Heap implementation (e.g.
heap_4.corheap_5.c).Minimum stack size for tasks.
Number of priorities:
configMAX_PRIORITIES.
Generate the code:
STM32CubeMX typically generates: -
mx_freertos_app.c,mx_freertos_app.handFreeRTOSConfig.h- FreeRTOS sources inmisc/STMicroelectronics.freertos.X.Y.Z
In
main.c:
Call
app_synctasks_init();to create tasks and objects.Start the kernel with
vTaskStartScheduler();
Which FreeRTOS heap implementation should I use on STM32?
Commonly used on STM32:
heap_1.c: - Only static allocation (novPortFree). - Very simple but not flexible.heap_2.c: - Dynamic allocation + free. - More prone to fragmentation.heap_4.c: - Most common choice. - Dynamic allocation + free with coalescing of free blocks. - More robust and widely recommended for STM32 projects.heap_5.c: - Similar behavior toheap_4but supports multiple memory regions : useful if you want to use different SRAM banks, TCM, SRAM2, etc.
In practice, STM32 community examples very often use
heap_4.c.
How to size ``configTOTAL_HEAP_SIZE`` for FreeRTOS on STM32?
Basic approach:
Estimate the total memory required for:
Sum of all task stacks.
Queues, semaphores, mutexes, timers.
Plus a safety margin (30–50% at the beginning).
Example values (rough guidelines):
STM32F4 with 128 KB RAM: between
20*1024and50*1024bytes, depending on number of tasks and features.Low-RAM devices (STM32G0/L0): start around
4*1024or8*1024bytes and adjust.
Monitor usage:
Use functions like
uxTaskGetStackHighWaterMark()for each task.Use
uxTaskGetSystemState()and/or RTOS-aware debug tools to refine heap and stack sizes.
Interrupts and priorities ¶
How should NVIC interrupt priorities be set with FreeRTOS on STM32?
Key macros in
FreeRTOSConfig.h:
configLIBRARY_LOWEST_INTERRUPT_PRIORITYconfigLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITYconfigKERNEL_INTERRUPT_PRIORITY
Cortex-M rules:
Any interrupt that calls a FreeRTOS FromISR API (e.g.
xQueueSendFromISR,xSemaphoreGiveFromISR) must have a numerical priority greater or equal (i.e. less urgent) thanconfigLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY.Interrupts that are more urgent than
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITYmust not call any FreeRTOS API.
Also ensure:
configPRIO_BITSmatches the MCU (from CMSIS define__NVIC_PRIO_BITS).Priority grouping is consistent if used (e.g. no conflicting
NVIC_PriorityGroupConfigon older devices).
Why does my system freeze after calling ``vTaskStartScheduler()``?
Typical root causes:
Incorrect NVIC configuration :
Wrong priorities for
PendSV,SysTickorSVCall.They must match the configuration expected by the FreeRTOS port.
Main stack (MSP) too small :
The scheduler startup initially uses the main stack pointer.
Increase stack size in the linker script or startup file.
Insufficient heap :
Task creation may fail before the scheduler starts.
Check task handles for
NULLand verify the malloc failed hook.
Malloc or stack overflow hooks triggered :
vApplicationMallocFailedHookorvApplicationStackOverflowHookmay be called and loop indefinitely.Ensure
configASSERTis enabled and check for assertion failures.
When should I use the *FromISR* versions of FreeRTOS functions?
In any ISR (hardware interrupt):
Use the FromISR variants:
xQueueSendFromISR,xQueueReceiveFromISR,xSemaphoreGiveFromISR,xTaskNotifyFromISR, etc.
Never call the “normal” API functions (e.g.
xQueueSend,xSemaphoreTake) from an ISR.Always consider the
pxHigherPriorityTaskWokenargument and callportYIELD_FROM_ISR()(or equivalent macro) if it indicates that a context switch should occur.
Tasks, stack and performance ¶
How do I choose the task stack size?
Guidelines:
Start with a “large” stack value, e.g.
256or512words (depending on port, usually 4-byte words).During testing, use:
uxTaskGetStackHighWaterMark()to check remaining stack for each task.Increase or decrease stack sizes based on the minimum observed headroom.
Beware of heavy stack users:
printf/sprintfand floating-point operations can consume a lot of stack.Large local arrays should be made
staticor allocated from the heap instead of the stack.
Is there a significant CPU cost to using FreeRTOS on STM32?
For most STM32 families:
Context switch overhead is typically small (a few microseconds) at common clock speeds.
The impact depends on:
Interrupt rate.
Frequency of task wake-ups.
Number of ready tasks at any time.
For many real-time applications, the scheduling overhead is negligible compared to I/O operations or complex computations.
How can I avoid priority inversion and starvation?
Best practices:
Do not assign too many tasks to the maximum priority.
Use FreeRTOS mutexes (with priority inheritance) to protect shared resources.
Avoid high-priority tasks that loop without blocking:
They should call
vTaskDelay(),xQueueReceive(), etc., so that lower-priority tasks can run.
Prefer a small number of well-designed tasks with internal state machines over many micro-tasks that complicate scheduling.
Inter-task communication ¶
Queue vs Semaphore for notifying a task?
Queue:
Use to transfer data (structures, messages, values).
Allows buffering and decoupling producers and consumers.
Semaphore:
Binary semaphore: signal that an event occurred (often from an ISR).
Counting semaphore: count occurrences of an event, such as repeated interrupts or jobs.
Task Notification:
Very lightweight and efficient mechanism for one-to-one signaling.
Often recommended instead of a simple semaphore when only one task is involved.
When should I use Event Groups?
Event groups are useful when:
A task must wait on multiple conditions simultaneously.
Example: waiting for both
ETH_READYandLINK_UPbits.
Advantages:
More readable than managing multiple semaphores and combining them manually.
Limitations:
Not meant for data transfer, only for signaling status bits/events.
SysTick and HAL_Delay ¶
Why does ``HAL_Delay()`` behave incorrectly after starting FreeRTOS?
On STM32:
HAL_Delay()uses SysTick by default.FreeRTOS also uses SysTick for the OS tick.
After
vTaskStartScheduler():
HAL_Delay()is often re-implemented to rely onosDelay()orvTaskDelay().If this is not done,
HAL_Delay()can become inaccurate or block the system.
Recommendations:
In FreeRTOS-based projects, replace application calls to
HAL_Delay()withosDelay()/vTaskDelay()as soon as possible.Before the scheduler starts (initialization phase), short calls to
HAL_Delay()are acceptable but should be minimized.
How to configure the FreeRTOS tick rate (``configTICK_RATE_HZ``)?
Typical values:
1000Hz (1 ms tick) is common for many applications.
For low-power applications (STM32L0/L4/U5, etc.):
You may reduce it to
100Hz or even lower to save energy.
Trade-offs:
Higher tick frequencies mean more SysTick interrupts and more context switches.
Lower tick frequencies reduce timing resolution for
vTaskDelay,vTaskDelayUntil, and timeouts.
Debugging and common issues ¶
How do I detect a task stack overflow with FreeRTOS?
In
FreeRTOSConfig.h:
#define configCHECK_FOR_STACK_OVERFLOW 2
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
{
/* Breakpoint, logging, reset, etc. */
for (;;);
}
Notes:
Mode
2enables a more comprehensive check.Place a breakpoint inside the hook to identify the offending task.
My program ends up in HardFault after some time: how do I debug this?
Common causes on STM32 + FreeRTOS:
Task or main stack overflow.
Null pointer dereference in callbacks or ISRs.
Incorrect NVIC/FreeRTOS configuration (wrong priority setup).
Suggested actions:
Enable
configASSERTand the stack overflow hook.Implement a detailed HardFault handler that dumps registers and stack frame.
Verify that all tasks have adequate stack size.
Double-check
configPRIO_BITSand interrupt priority configuration.
Integration with HAL/LL ¶
How to use FreeRTOS with HAL callbacks (DMA, UART, SPI, etc.)?
Typical pattern:
In the HAL callback (executed in interrupt context):
Notify a task using
xSemaphoreGiveFromISR(),xQueueSendFromISR(), orvTaskNotifyGiveFromISR().
In the task:
Wait for the event using
xSemaphoreTake(),xQueueReceive(),ulTaskNotifyTake(), etc.
Best practice:
Keep ISR code small and fast.
Perform heavy processing in tasks, not in ISRs.
Should access to HAL drivers be limited per task?
Often recommended architecture:
One peripheral = one “owner” task, responsible for:
Initializing the peripheral.
Handling all I/O.
Managing errors.
Other tasks communicate with this owner task using queues or messages.
For shared peripherals accessed by multiple tasks:
Use FreeRTOS mutexes around HAL calls (if a single owner task is not possible).
Ensure that blocking calls in HAL are understood and compatible with the RTOS scheduling model.
Low-Power and FreeRTOS ¶
How to use STM32 low-power modes with FreeRTOS?
Typical approach:
Enable tickless idle:
Set
configUSE_TICKLESS_IDLEinFreeRTOSConfig.h.Provide or use the MCU-specific implementation of
vPortSuppressTicksAndSleep().
Use a low-power timer (RTC, LPTIM) to wake up after several OS ticks.
Enter a low-power mode (e.g. STOPx or SLEEP) when no tasks are ready.
Key points:
Ensure that interrupt sources that should wake the MCU are configured properly.
Take care with clock configuration:
Some clocks need to be maintained or restored on wake-up.
Check STM32 ANs for RTOS + low-power examples specific to your family.
What about ``HAL_Delay()`` and low-power with FreeRTOS?
Problems:
HAL_Delay()based on SysTick or busy-waiting can prevent entry into deep sleep and introduce unnecessary active time.
Recommendations:
In FreeRTOS low-power designs, prefer:
vTaskDelay()orxTaskDelayUntil().FreeRTOS timers.
RTC-based wake-ups when long delays are needed.
Avoid long blocking delays in ISRs or before the kernel starts, if low power is critical.
Links ¶
What is FreeRTOS? : What is FreeRTOS ?
FreeRTOS Best practices: FreeRTOS Best Practices