关于 freertos
这项技能指导 Agent 开发和调试 FreeRTOS 应用,涵盖任务调度、任务间通信、配置、内存检查,以及通过 GDB 和 OpenOCD 调试。
主要功能
- 01创建任务并设置优先级
- 02通过队列和信号量传递数据
- 03检测任务栈溢出
- 04配置 FreeRTOSConfig.h
- 05使用 GDB 和 OpenOCD 调试任务
- 06使用 FreeRTOS+TCP 和 TrustZone 功能
适用场景
- 01组织任务并安排中断处理优先级
- 02在任务和 ISR 间交换数据
- 03排查任务崩溃和栈空间问题
- 04配置网络或 MPU 任务区域
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill freertos安装后在 Claude Code 中输入/freertos确认已加载。
附带文件references/freertos-config.md
详细介绍
FreeRTOS
用途
指导 Agent 进行 FreeRTOS 应用开发:创建任务和设置优先级、使用队列和信号量进行任务间通信、检测栈溢出、使用 configASSERT,以及使用 GDB 和 OpenOCD 进行 FreeRTOS 感知调试。
触发条件
- “如何创建 FreeRTOS 任务?”
- “如何在 FreeRTOS 任务之间传递数据?”
- “我的 FreeRTOS 任务崩溃了——如何检测栈溢出?”
- “如何使用 FreeRTOS 互斥锁?”
- “如何使用 GDB 调试 FreeRTOS 任务?”
- “如何配置 FreeRTOSConfig.h?”
工作流
1. 创建任务和设置优先级
#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)——空闲任务,不要在此阻塞- ISR 延迟处理任务——最高优先级,以便快速处理中断
- 避免使用高于
configMAX_PRIORITIES - 1的优先级
2. 队列——任务间数据传递
#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. 信号量和互斥锁
#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. 检测栈溢出
// 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);
}
在运行时检查水位标记:
// 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. 必要的 FreeRTOSConfig.h 设置
// 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. 使用 OpenOCD 进行 GDB 调试
# Connect GDB with FreeRTOS thread awareness
# OpenOCD provides FreeRTOS-aware RTOS plugin
# openocd.cfg addition
# source [find rtos/FreeRTOS.cfg] # auto-loads with most targets
# 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
# Print task list from GDB (if trace facility enabled)
(gdb) call vTaskList(buf)
(gdb) printf "%s\n", buf
7. FreeRTOS v11 API 更新
FreeRTOS v11(2024 年及之后)扩展了任务通知和流缓冲区:
// Task notifications v2 — 32-bit values with action semantics
xTaskNotifyIndexed(xHandle, 0, ulValue, eSetValueWithOverwrite);
xTaskNotifyWaitIndexed(0, 0, ULONG_MAX, &ulNotified, portMAX_DELAY);
// Stream buffers — ISR-safe send with trigger level
xStreamBufferSend(xStream, data, len, 0);
xStreamBufferSetTriggerLevel(xStream, 1); // wake receiver on 1 byte
编译时检查 FreeRTOS.h 中的 tskKERNEL_VERSION_NUMBER,以确定 API 是否可用。
8. ARM TrustZone 集成
在 Cortex-M33/M55 上划分安全/非安全世界:
#include "secure_context.h"
// Initialize secure context management (secure side or NSC veneer)
SecureContext_Init();
// Allocate secure context for task calling secure functions
xTaskCreateSecure(vSecureTask, "SecTask", STACK, NULL, priority, &xHandle);
// MPU defines NSC (Non-Secure Callable) regions for SG veneers
需要启用 TrustZone 的 MCU、安全固件分区,以及 NSC 链接器段放置。
9. FreeRTOS+TCP 基础
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
// After network stack init (FreeRTOS_IPInit)
Socket_t xSocket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM,
FREERTOS_IPPROTO_TCP);
FreeRTOS_connect(xSocket, &xAddress, sizeof(xAddress));
FreeRTOS_send(xSocket, buffer, len, 0);
在 FreeRTOSIPConfig.h 中配置缓冲区数量和 TCP/IP 选项(例如 ipconfigUSE_TCP、ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS)。需配合以太网 MAC 驱动程序和 FreeRTOS+TCP 缓冲区管理使用。
10. MPU 区域配置
// Restricted task with MPU regions (Cortex-M with MPU)
static const TaskParameters_t xRestrictedTaskParams = {
.pvTaskCode = vRestrictedTask,
.pcName = "Restricted",
.usStackDepth = configMINIMAL_STACK_SIZE,
.pvParameters = NULL,
.uxPriority = tskIDLE_PRIORITY + 1,
.puxStackBuffer = stackBuffer,
.xRegions = {
{ .pvBaseAddress = 0x20000000, .ulLength = 0x10000,
.ulParameters = tskMPU_REGION_READ_ONLY | tskMPU_REGION_EXECUTE_NEVER },
{ .pvBaseAddress = 0x00000000, .ulLength = 0, .ulParameters = 0 } // terminator
}
};
xTaskCreateRestricted(&xRestrictedTaskParams, &xHandle);
为只读代码/数据、特权外设和任务私有栈定义独立的 RAM 区域。
有关 OpenOCD 设置详情,请参阅 skills/embedded/openocd-jtag。
有关 FreeRTOSConfig.h 参考信息,请参阅 references/freertos-config.md。
相关技能
- 使用
skills/embedded/openocd-jtag设置 GDB/OpenOCD 远程调试 - 使用
skills/embedded/linker-scripts将 FreeRTOS 堆放置在特定 RAM 区域 - 使用
skills/debuggers/gdb管理常规 GDB 会话 - 使用
skills/embedded/zephyr了解具备内置设备管理功能的替代 RTOS