freertos

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

FreeRTOS

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.
指导开发者进行FreeRTOS应用开发:包括任务创建与优先级设置、通过队列和信号量实现任务间通信、堆栈溢出检测、configASSERT配置,以及使用GDB和OpenOCD进行FreeRTOS感知调试。

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?"
  • "如何创建FreeRTOS任务?"
  • "如何在FreeRTOS任务间传递数据?"
  • "我的FreeRTOS任务崩溃了——如何检测堆栈溢出?"
  • "如何使用FreeRTOS互斥量?"
  • "如何使用GDB调试FreeRTOS任务?"
  • "如何配置FreeRTOSConfig.h?"

Workflow

工作流程

1. Task creation and priorities

1. 任务创建与优先级设置

c
#include "FreeRTOS.h"
#include "task.h"

// Task function signature
void vMyTask(void *pvParameters) {
    const char *name = (const char *)pvParameters;
    for (;;) {
        // Task body — must never return
        printf("Task %s running\n", name);
        vTaskDelay(pdMS_TO_TICKS(500));  // yield for 500ms
    }
}

int main(void) {
    // xTaskCreate(function, name, stack_depth_words, param, priority, handle)
    TaskHandle_t xHandle = NULL;
    xTaskCreate(vMyTask, "MyTask",
                configMINIMAL_STACK_SIZE + 128,  // words, not bytes!
                (void *)"sensor",
                tskIDLE_PRIORITY + 2,            // higher = more urgent
                &xHandle);

    vTaskStartScheduler();  // never returns if heap is sufficient
    for (;;);               // should never reach here
}
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
c
#include "FreeRTOS.h"
#include "task.h"

// Task function signature
void vMyTask(void *pvParameters) {
    const char *name = (const char *)pvParameters;
    for (;;) {
        // Task body — must never return
        printf("Task %s running\n", name);
        vTaskDelay(pdMS_TO_TICKS(500));  // yield for 500ms
    }
}

int main(void) {
    // xTaskCreate(function, name, stack_depth_words, param, priority, handle)
    TaskHandle_t xHandle = NULL;
    xTaskCreate(vMyTask, "MyTask",
                configMINIMAL_STACK_SIZE + 128,  // words, not bytes!
                (void *)"sensor",
                tskIDLE_PRIORITY + 2,            // higher = more urgent
                &xHandle);

    vTaskStartScheduler();  // never returns if heap is sufficient
    for (;;);               // should never reach here
}
优先级指南:
  • tskIDLE_PRIORITY
    (0)——空闲任务,请勿在此任务中阻塞
  • 中断延迟任务——设置最高优先级以快速响应中断
  • 避免使用高于
    configMAX_PRIORITIES - 1
    的优先级

2. Queues — inter-task data passing

2. 队列——任务间数据传递

c
#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();
        // Send; block max 10ms if queue full
        xQueueSend(xSensorQueue, &reading, pdMS_TO_TICKS(10));
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

void vConsumerTask(void *pvParam) {
    SensorReading_t reading;
    for (;;) {
        // Block forever until item available
        if (xQueueReceive(xSensorQueue, &reading, portMAX_DELAY) == pdTRUE) {
            process(reading.value);
        }
    }
}

// Create before starting scheduler
xSensorQueue = xQueueCreate(10, sizeof(SensorReading_t));
From ISR: use
xQueueSendFromISR()
and pass
&xHigherPriorityTaskWoken
.
c
#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();
        // Send; block max 10ms if queue full
        xQueueSend(xSensorQueue, &reading, pdMS_TO_TICKS(10));
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

void vConsumerTask(void *pvParam) {
    SensorReading_t reading;
    for (;;) {
        // Block forever until item available
        if (xQueueReceive(xSensorQueue, &reading, portMAX_DELAY) == pdTRUE) {
            process(reading.value);
        }
    }
}

// Create before starting scheduler
xSensorQueue = xQueueCreate(10, sizeof(SensorReading_t));
在中断服务程序(ISR)中使用:请调用
xQueueSendFromISR()
并传入
&xHigherPriorityTaskWoken

3. Semaphores and mutexes

3. 信号量与互斥量

c
#include "semphr.h"

// Binary semaphore — signaling (ISR→task)
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);
        // process received data
    }
}

// Mutex — mutual exclusion (NOT from ISR)
SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();

void vCriticalSection(void) {
    if (xSemaphoreTake(xMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
        // protected access
        shared_resource++;
        xSemaphoreGive(xMutex);
    }
}

// Recursive mutex (same task can take multiple times)
SemaphoreHandle_t xRecursive = xSemaphoreCreateRecursiveMutex();
xSemaphoreTakeRecursive(xRecursive, portMAX_DELAY);
xSemaphoreGiveRecursive(xRecursive);
Use mutex (not binary semaphore) for shared resources to get priority inheritance.
c
#include "semphr.h"

// Binary semaphore — signaling (ISR→task)
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);
        // process received data
    }
}

// Mutex — mutual exclusion (NOT from ISR)
SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();

void vCriticalSection(void) {
    if (xSemaphoreTake(xMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
        // protected access
        shared_resource++;
        xSemaphoreGive(xMutex);
    }
}

// Recursive mutex (same task can take multiple times)
SemaphoreHandle_t xRecursive = xSemaphoreCreateRecursiveMutex();
xSemaphoreTakeRecursive(xRecursive, portMAX_DELAY);
xSemaphoreGiveRecursive(xRecursive);
针对共享资源,请使用互斥量(而非二进制信号量)以获得优先级继承特性。

4. Stack overflow detection

4. 堆栈溢出检测

c
// FreeRTOSConfig.h
#define configCHECK_FOR_STACK_OVERFLOW  2  // Method 2 (pattern + watermark)
#define configUSE_MALLOC_FAILED_HOOK    1

// Implement the hook (called when overflow detected)
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
    // Log the offending task name, then halt
    configASSERT(0);  // triggers assertion failure
}

void vApplicationMallocFailedHook(void) {
    configASSERT(0);
}
Check watermarks at runtime:
c
// Returns minimum ever free stack words
UBaseType_t uxHighWaterMark = uxTaskGetStackHighWaterMark(xHandle);
printf("Stack headroom: %lu words\n", uxHighWaterMark);
// Rule of thumb: keep headroom > 20 words
c
// FreeRTOSConfig.h
#define configCHECK_FOR_STACK_OVERFLOW  2  // Method 2 (pattern + watermark)
#define configUSE_MALLOC_FAILED_HOOK    1

// Implement the hook (called when overflow detected)
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
    // Log the offending task name, then halt
    configASSERT(0);  // triggers assertion failure
}

void vApplicationMallocFailedHook(void) {
    configASSERT(0);
}
运行时检查堆栈水印:
c
// Returns minimum ever free stack words
UBaseType_t uxHighWaterMark = uxTaskGetStackHighWaterMark(xHandle);
printf("Stack headroom: %lu words\n", uxHighWaterMark);
// Rule of thumb: keep headroom > 20 words

5. Essential FreeRTOSConfig.h settings

5. FreeRTOSConfig.h关键配置

c
// FreeRTOSConfig.h — adapt to your MCU
#define configCPU_CLOCK_HZ              (SystemCoreClock)
#define configTICK_RATE_HZ              1000          // 1ms tick
#define configMAX_PRIORITIES            8
#define configMINIMAL_STACK_SIZE        128           // words
#define configTOTAL_HEAP_SIZE           (16 * 1024)  // bytes
#define configMAX_TASK_NAME_LEN         16

// Debug / safety
#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(;;); }

// Features
#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)
c
// FreeRTOSConfig.h — adapt to your MCU
#define configCPU_CLOCK_HZ              (SystemCoreClock)
#define configTICK_RATE_HZ              1000          // 1ms tick
#define configMAX_PRIORITIES            8
#define configMINIMAL_STACK_SIZE        128           // words
#define configTOTAL_HEAP_SIZE           (16 * 1024)  // bytes
#define configMAX_TASK_NAME_LEN         16

// Debug / safety
#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(;;); }

// Features
#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

6. 使用OpenOCD进行GDB调试

bash
undefined
bash
undefined

Connect GDB with FreeRTOS thread awareness

Connect GDB with FreeRTOS thread awareness

OpenOCD provides FreeRTOS-aware RTOS plugin

OpenOCD provides FreeRTOS-aware RTOS plugin

openocd.cfg addition

openocd.cfg addition

source [find rtos/FreeRTOS.cfg] # auto-loads with most targets

source [find rtos/FreeRTOS.cfg] # auto-loads with most targets

GDB session

GDB session

(gdb) info threads # lists all FreeRTOS tasks (gdb) thread 3 # switch to task 3 (gdb) bt # backtrace of that task's stack (gdb) frame 2 # inspect specific frame
(gdb) info threads # lists all FreeRTOS tasks (gdb) thread 3 # switch to task 3 (gdb) bt # backtrace of that task's stack (gdb) frame 2 # inspect specific frame

Print task list from GDB (if trace facility enabled)

Print task list from GDB (if trace facility enabled)

(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](references/freertos-config.md).
(gdb) call vTaskList(buf) (gdb) printf "%s\n", buf

有关OpenOCD的设置详情,请参阅`skills/embedded/openocd-jtag`。
有关FreeRTOSConfig.h的参考,请参阅[references/freertos-config.md](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
  • 使用
    skills/embedded/openocd-jtag
    进行GDB/OpenOCD远程调试设置
  • 使用
    skills/embedded/linker-scripts
    将FreeRTOS堆放置在特定RAM区域
  • 使用
    skills/debuggers/gdb
    进行通用GDB会话管理
  • 使用
    skills/embedded/zephyr
    作为替代RTOS,它内置设备管理功能