| name | freertos |
| description | FreeRTOS skill for embedded RTOS development. Use when creating tasks, managing priorities, using queues and mutexes, detecting stack overflows, configuring FreeRTOS via FreeRTOSConfig.h, or debugging FreeRTOS applications with OpenOCD and GDB. Activates on queries about FreeRTOS tasks, queues, semaphores, mutexes, configASSERT, stack overflow, vTaskDelay, or FreeRTOS-aware debugging. |
FreeRTOS
Purpose
Guide agents through FreeRTOS application development: task creation and priorities, inter-task communication with queues and semaphores, stack overflow detection, configASSERT, and FreeRTOS-aware debugging with GDB and OpenOCD.
Triggers
- "How do I create a FreeRTOS task?"
- "How do I pass data between FreeRTOS tasks?"
- "My FreeRTOS task is crashing — how do I detect stack overflow?"
- "How do I use FreeRTOS mutexes?"
- "How do I debug FreeRTOS tasks with GDB?"
- "How do I configure FreeRTOSConfig.h?"
Workflow
1. Task creation and priorities
#include "FreeRTOS.h"
#include "task.h"
void vMyTask(void *pvParameters) {
const char *name = (const char *)pvParameters;
for (;;) {
printf("Task %s running\n", name);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
int main(void) {
TaskHandle_t xHandle = NULL;
xTaskCreate(vMyTask, "MyTask",
configMINIMAL_STACK_SIZE + 128,
(void *)"sensor",
tskIDLE_PRIORITY + 2,
&xHandle);
vTaskStartScheduler();
for (;;);
}
Priority guidelines:
tskIDLE_PRIORITY (0) — idle task, never block here
- ISR-deferred tasks — highest priority to service interrupts quickly
- Avoid priorities above
configMAX_PRIORITIES - 1
2. Queues — inter-task data passing
#include "queue.h"
typedef struct { uint32_t sensor_id; float value; } SensorReading_t;
QueueHandle_t xSensorQueue;
void vProducerTask(void *pvParam) {
SensorReading_t reading;
for (;;) {
reading.sensor_id = 1;
reading.value = read_adc();
xQueueSend(xSensorQueue, &reading, pdMS_TO_TICKS(10));
vTaskDelay(pdMS_TO_TICKS(100));
}
}
void vConsumerTask(void *pvParam) {
SensorReading_t reading;
for (;;) {
if (xQueueReceive(xSensorQueue, &reading, portMAX_DELAY) == pdTRUE) {
process(reading.value);
}
}
}
xSensorQueue = xQueueCreate(10, sizeof(SensorReading_t));
From ISR: use xQueueSendFromISR() and pass &xHigherPriorityTaskWoken.
3. Semaphores and mutexes
#include "semphr.h"
SemaphoreHandle_t xSem = xSemaphoreCreateBinary();
void UART_ISR(void) {
BaseType_t xWoken = pdFALSE;
xSemaphoreGiveFromISR(xSem, &xWoken);
portYIELD_FROM_ISR(xWoken);
}
void vUartTask(void *p) {
for (;;) {
xSemaphoreTake(xSem, portMAX_DELAY);
}
}
SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();
void vCriticalSection(void) {
if (xSemaphoreTake(xMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
shared_resource++;
xSemaphoreGive(xMutex);
}
}
SemaphoreHandle_t xRecursive = xSemaphoreCreateRecursiveMutex();
xSemaphoreTakeRecursive(xRecursive, portMAX_DELAY);
xSemaphoreGiveRecursive(xRecursive);
Use mutex (not binary semaphore) for shared resources to get priority inheritance.
4. Stack overflow detection
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_MALLOC_FAILED_HOOK 1
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
configASSERT(0);
}
void vApplicationMallocFailedHook(void) {
configASSERT(0);
}
Check watermarks at runtime:
UBaseType_t uxHighWaterMark = uxTaskGetStackHighWaterMark(xHandle);
printf("Stack headroom: %lu words\n", uxHighWaterMark);
5. Essential FreeRTOSConfig.h settings
#define configCPU_CLOCK_HZ (SystemCoreClock)
#define configTICK_RATE_HZ 1000
#define configMAX_PRIORITIES 8
#define configMINIMAL_STACK_SIZE 128
#define configTOTAL_HEAP_SIZE (16 * 1024)
#define configMAX_TASK_NAME_LEN 16
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_MALLOC_FAILED_HOOK 1
#define configASSERT(x) if((x)==0) { taskDISABLE_INTERRUPTS(); for(;;); }
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_TIMERS 1
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2)
6. GDB debugging with OpenOCD
(gdb) info threads
(gdb) thread 3
(gdb) bt
(gdb) frame 2
(gdb) call vTaskList(buf)
(gdb) printf "%s\n", buf
For OpenOCD setup details, see skills/embedded/openocd-jtag.
For FreeRTOSConfig.h reference, see references/freertos-config.md.
Related skills
- Use
skills/embedded/openocd-jtag for GDB/OpenOCD remote debugging setup
- Use
skills/embedded/linker-scripts for placing FreeRTOS heap in specific RAM regions
- Use
skills/debuggers/gdb for general GDB session management
- Use
skills/embedded/zephyr for an alternative RTOS with built-in device management