FreeRTOS RTOS Engineering & Integration

Task architecture, priority assignment, inter-task communication, and power management — FreeRTOS engineered for determinism, safety, and production reliability.

Platform engineering
Platform Capabilities

What We Build on This Platform

Task Architecture Design

Task decomposition from functional requirements, priority assignment from response time analysis, and stack sizing from call depth measurement.

Inter-Task Communication

Queue, binary semaphore, counting semaphore, mutex with priority inheritance, event group, and stream buffer for concurrent firmware design.

ISR and Deferred Interrupt Handling

ISR-safe API selection, deferred interrupt handler task, and interrupt priority configuration below configMAX_SYSCALL_INTERRUPT_PRIORITY.

Tickless Idle and Low Power

Tickless idle mode, sleep hook, peripheral clock gating from idle task, and tick count correction for sub-10µA average current.

Memory Management

heap_4 and heap_5 memory pools, static allocation for TCB and stack, and runtime heap watermark monitoring.

Stack Overflow Detection

Watermark checking, MPU stack guard configuration, and runtime stack high-water mark analysis.

FreeRTOS+TCP

Embedded TCP/IP stack integration on FreeRTOS for Ethernet and Wi-Fi IoT applications.

Trace and Debug

Tracealyzer, SEGGER SystemView, vTaskGetRunTimeStats, and task state monitoring for production firmware.

Platform Integration

How Ankh Uses This Platform

01

Task Architecture from Requirements

Task identification from the functional decomposition: every concurrent activity becomes a task; every response time requirement becomes a priority constraint. Priority assignment from Rate Monotonic Scheduling theory for periodic tasks: the task with the shortest period gets the highest priority. Response time analysis verifies that every task meets its deadline under worst-case preemption by higher-priority tasks.

02

Stack Sizing and Memory Planning

Stack size calculated from function call depth including all called functions' local variable usage, ISR stack overhead for tasks receiving deferred work, and floating-point register save for FPU tasks. FreeRTOS stack watermark monitoring configured and enabled in development builds. Total RAM allocation across all task stacks, queue buffers, and kernel objects verified against the MCU's RAM budget.

03

Inter-Task Communication Design

Queue designed for data producer-consumer decoupling: item size, queue length, and blocking behaviour. Mutex configured for shared resource protection with priority inheritance enabled. Binary semaphore used for ISR-to-task signalling. Event groups for multi-condition wait without polling. Stream buffer for high-throughput byte stream transfer between tasks.

04

ISR Architecture

All ISRs kept minimal: pend a deferred interrupt task or send to a queue from ISR context; no blocking API calls in ISR context; xHigherPriorityTaskWoken checked and portYIELD_FROM_ISR called where required. NVIC priority for all ISR sources set below configMAX_SYSCALL_INTERRUPT_PRIORITY to allow FreeRTOS critical section protection.

05

Tickless Idle and Production Power Management

Tickless idle mode configured for battery-powered products: tick suppression during idle, SysTick stop during low-power sleep, peripheral clock gating from pre-sleep hook, and tick count correction on wake. Idle task hook for additional low-power configuration. Power budget measured at each operating state from the specific duty cycle requirement.

Engineering Depth

Deep Technical Capability

01

Priority Inversion and the Mutex Protocol

A FreeRTOS mutex created with xSemaphoreCreateMutex() implements priority inheritance — the mechanism that temporarily raises the priority of a low-priority task holding a mutex when a high-priority task blocks waiting for the same mutex, preventing the high-priority task from being indefinitely delayed by medium-priority tasks that preempt the lock-holder. Priority inheritance is the correct protocol for preventing priority inversion in most embedded applications — but it does not prevent all scenarios. A system with two mutexes where Task A acquires Mutex 1 then Mutex 2, and Task B acquires Mutex 2 then Mutex 1, can deadlock if the acquisition sequence is interleaved — a deadlock that priority inheritance cannot resolve. Ankh designs mutex usage with a global resource acquisition order policy: every task acquires mutexes in the same defined order, eliminating the circular wait condition that produces deadlock regardless of priority inheritance configuration.

02

FreeRTOS Stack Overflow Detection in Production Firmware

FreeRTOS's configCHECK_FOR_STACK_OVERFLOW enables stack overflow checking at the task switch boundary — but checking only at the task switch means that a stack overflow occurring entirely within a task's execution between switches (a transient overflow from a deep function call that returns before the next switch) is invisible to the stack check. The vApplicationStackOverflowHook() is called when the check detects an overflow — but at that point the stack has already overflowed, the TCB may be corrupted, and the hook itself may not execute correctly. Ankh uses FreeRTOS stack watermark monitoring in development firmware to identify tasks operating close to their stack limit, and adds conservative margin (typically 25–30% above the measured high-water mark) for production — so the stack overflow that FreeRTOS detects at the task switch boundary is preceded by a substantial margin that the watermark monitoring has already flagged.

03

FreeRTOS Tickless Idle for Sub-10µA Average Current

FreeRTOS's tickless idle mode suppresses the SysTick interrupt during periods when no tasks are ready to run, allowing the MCU to enter a deep sleep state that the SysTick interrupt would otherwise prevent. Implementing tickless idle requires the port's vPortSuppressTicksAndSleep() to: calculate the maximum sleep duration from the next FreeRTOS timer expiry; configure the MCU's low-power timer to wake after that duration; enter the MCU's deep sleep mode; on wake, correct the FreeRTOS tick count by the actual elapsed sleep time; and restore SysTick to resume normal operation. The tickless implementation for a specific MCU and FreeRTOS port is not always correct in the vendor-supplied port — Ankh verifies tick count accuracy after sleep and wake transitions using a hardware timer reference and measures the MCU current consumption in tickless idle mode to confirm that the expected low-power state is being entered.

01

Stack size is not a number to increase until the product stops crashing

The FreeRTOS firmware debugged by increasing task stack sizes until stability is restored has not fixed the stack overflow problem — it has hidden it. The task stack overflowing at 512 bytes is still overflowing at 1024 bytes if the root cause is a recursive function call without a depth limit or a large local array that the developer did not account for. Ankh sizes stacks from a systematic analysis of the maximum call depth and local variable usage for each task's call tree — and validates the sizing with watermark monitoring in development before reducing the margin to the production allocation.

02

FreeRTOS is not thread-safe by default for every use case

The FreeRTOS queue API is thread-safe when used between tasks and from ISRs using the correct xQueueSendFromISR variants. The C standard library is not thread-safe in the default newlib implementation — malloc(), printf(), and strtok() use global state not protected against concurrent access from multiple FreeRTOS tasks. Products that use the C standard library from multiple tasks require either the newlib-nano reentrant variant with per-task reentrancy structures, or restriction of C standard library calls to a single task context. This is discovered at the worst possible time — under production load conditions — if not designed for from the first firmware architecture decision.

03

configASSERT is a development tool, not a production feature to disable

FreeRTOS's configASSERT() macro provides runtime validation of API usage correctness — checking that xSemaphoreTake() is not called from ISR context, that task priorities are within the configured range, and that queue handles are valid before use. configASSERT() should be enabled in development firmware and configured to call a fault handler that captures the assertion location and dumps it to the debug interface. Ankh's recommendation is to retain configASSERT() in production firmware in a form that logs the assertion failure to non-volatile storage for post-mortem analysis — not to disable it and lose fault detection entirely.

Quote your project

Using FreeRTOS on your product?Let's design the task architecture from the response time requirements.