bahaabdelwahed-embedded-claude-plugin

rtos-patterns

This skill should be used when the user asks about "FreeRTOS on STM32", "RTOS task creation", "task priorities", "stack sizing", "mutex", "semaphore", "queue", "event groups", "task notifications", "ISR safe API", "deferred interrupt processing", "FreeRTOSConfig.h", "heap management", "CMSIS-RTOS", "scheduling", "real-time application", or needs RTOS integration patterns for STM32 firmware.
étoiles7
forks0
observateurs0
mise à jour2026-10-08 14:03:29

RTOS Patterns for STM32

Provide RTOS integration guidance for STM32 using FreeRTOS (native API and CMSIS-RTOS v2 wrapper).

FreeRTOS + STM32 Integration

HAL Timebase Conflict

STM32 HAL uses SysTick as its timebase by default. FreeRTOS also needs SysTick for its scheduler tick. This creates a conflict.

Solution: Configure HAL to use a different timer (e.g., TIM6 or TIM7) for its timebase:

  • In STM32CubeMX: Pinout & Configuration -> SYS -> Timebase Source -> TIM6
  • Manually: Implement HAL_InitTick() and HAL_GetTick() using a basic timer

FreeRTOS keeps SysTick for its scheduler tick.

FreeRTOSConfig.h Key Parameters

Extract from documentation or configure based on the target MCU:

#define configCPU_CLOCK_HZ              (SystemCoreClock)  // From RCC config
#define configTICK_RATE_HZ              ((TickType_t)1000) // 1ms tick
#define configMAX_PRIORITIES            (7)                // 0-6 priority levels
#define configMINIMAL_STACK_SIZE        ((uint16_t)128)    // Words (512 bytes)
#define configTOTAL_HEAP_SIZE           ((size_t)15360)    // Bytes, adjust to SRAM
#define configUSE_PREEMPTION            1
#define configUSE_MUTEXES               1
#define configUSE_COUNTING_SEMAPHORES   1
#define configUSE_QUEUE_SETS            0

/* Cortex-M interrupt priority configuration - CRITICAL */
#define configPRIO_BITS                 4  // Check RM for __NVIC_PRIO_BITS
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY      15
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY  5

Critical: Interrupt Priority Boundary

configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY defines the boundary:

  • Interrupts with priority >= this value (lower urgency) CAN use FreeRTOS *FromISR() APIs
  • Interrupts with priority < this value (higher urgency) MUST NOT call any FreeRTOS API
  • This is the most common source of hard faults in FreeRTOS + STM32 projects

Check the reference manual NVIC section for the number of priority bits (__NVIC_PRIO_BITS).

Task Patterns

Task Creation

// Static allocation (recommended - deterministic)
StaticTask_t xTaskBuffer;
StackType_t xStack[256];
xTaskCreateStatic(vTaskFunction, "Name", 256, NULL, 2, xStack, &xTaskBuffer);

// Dynamic allocation
xTaskCreate(vTaskFunction, "Name", 256, NULL, 2, &xHandle);

Stack Sizing Guidelines

  • Minimal task (no printf, no float): 128 words (512 bytes)
  • Task with printf/sprintf: 256+ words (uses significant stack)
  • Task with floating-point: 256+ words (FPU context saving)
  • Task with deep call chains: analyze worst-case depth
  • Use uxTaskGetStackHighWaterMark() to check actual usage

Priority Assignment

  • Priority 0: Idle task (reserved by FreeRTOS)
  • Priority 1: Low-priority background tasks
  • Priority 2-3: Normal application tasks
  • Priority 4-5: Time-sensitive tasks
  • Priority 6 (configMAX_PRIORITIES-1): Highest priority, use sparingly

Synchronization Primitives

Binary Semaphore (Event Signaling)

Use for ISR-to-task signaling (deferred interrupt processing):

SemaphoreHandle_t xSem = xSemaphoreCreateBinary();
// In ISR:  xSemaphoreGiveFromISR(xSem, &xHigherPrioTaskWoken);
// In task: xSemaphoreTake(xSem, portMAX_DELAY);

Mutex (Resource Protection)

Use for mutual exclusion with priority inheritance:

SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();
xSemaphoreTake(xMutex, portMAX_DELAY);
// ... access shared resource ...
xSemaphoreGive(xMutex);

Never use a mutex from an ISR.

Queue (Data Transfer)

Use for passing data between tasks or from ISR to task:

QueueHandle_t xQueue = xQueueCreate(10, sizeof(uint32_t));
// Producer: xQueueSend(xQueue, &data, portMAX_DELAY);
// Consumer: xQueueReceive(xQueue, &data, portMAX_DELAY);
// From ISR: xQueueSendFromISR(xQueue, &data, &xHigherPrioTaskWoken);

Task Notifications (Lightweight)

Faster than semaphores/queues for simple signaling:

// Signal:  xTaskNotifyGive(xTaskHandle);
// Wait:    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// From ISR: vTaskNotifyGiveFromISR(xTaskHandle, &xHigherPrioTaskWoken);

ISR Safety Rules

  1. Only use *FromISR() API variants in interrupt handlers
  2. Never use blocking calls in ISRs (no xSemaphoreTake, no xQueueReceive, no vTaskDelay)
  3. Always check and yield: After *FromISR() calls, check xHigherPriorityTaskWoken and call portYIELD_FROM_ISR() if set
  4. Respect priority boundary: Only ISRs with priority >= configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY may call FreeRTOS APIs

Deferred Interrupt Processing Pattern

void USART2_IRQHandler(void) {
    BaseType_t xHigherPrioTaskWoken = pdFALSE;
    // Minimal ISR work: clear flag, grab data
    uint8_t data = USART2->DR;
    xQueueSendFromISR(xRxQueue, &data, &xHigherPrioTaskWoken);
    portYIELD_FROM_ISR(xHigherPrioTaskWoken);
}

void vRxTask(void *pvParameters) {
    uint8_t data;
    for (;;) {
        xQueueReceive(xRxQueue, &data, portMAX_DELAY);
        // Process data here (heavy work in task context)
    }
}

Heap Management

SchemeDescriptionUse Case
heap_1Allocate only, no freeStatic systems, tasks never deleted
heap_2Best fit, no coalescingFixed-size allocations
heap_3Wraps malloc/freeWhen libc malloc is available
heap_4First fit, coalescingRecommended for most projects
heap_5Like heap_4, multiple regionsSpanning multiple SRAM regions

heap_5 for Multi-Region SRAM

HeapRegion_t xHeapRegions[] = {
    { (uint8_t *)0x20000000, 0x10000 },  // SRAM1: 64KB
    { (uint8_t *)0x2001C000, 0x4000  },  // SRAM2: 16KB
    { NULL, 0 }  // Terminator
};
vPortDefineHeapRegions(xHeapRegions);

Where to Find RTOS-Related Info in Docs

  • RM NVIC section: __NVIC_PRIO_BITS value for configPRIO_BITS
  • RM SysTick section: SysTick configuration (FreeRTOS manages this)
  • AN5365: ST application note on FreeRTOS with STM32 (check docs/application-notes/)
  • Datasheet: Total SRAM size for configTOTAL_HEAP_SIZE calculation

Additional Resources

  • references/rtos-integration-guide.md - Complete FreeRTOS+STM32 setup walkthrough, HAL timebase workaround details, ISR-to-task communication patterns