mcpField
F
freertos

freertos

github.com/mohitmishra786开发269651 次安装18 周前更新
代码仓库

关于 freertos

这项技能指导 Agent 开发和调试 FreeRTOS 应用,涵盖任务调度、任务间通信、配置、内存检查,以及通过 GDB 和 OpenOCD 调试。

主要功能

  1. 01创建任务并设置优先级
  2. 02通过队列和信号量传递数据
  3. 03检测任务栈溢出
  4. 04配置 FreeRTOSConfig.h
  5. 05使用 GDB 和 OpenOCD 调试任务
  6. 06使用 FreeRTOS+TCP 和 TrustZone 功能

适用场景

  1. 01组织任务并安排中断处理优先级
  2. 02在任务和 ISR 间交换数据
  3. 03排查任务崩溃和栈空间问题
  4. 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

评论

支持 Markdown