5.7 FreeRTOS 使用说明

本章说明 N32G033 开发包中 FreeRTOS 的中间件组成、内核接口来源,以及 LED_Blink 1 个示例。任务调度、移植层与中断优先级请配合 FreeRTOS 内核说明与用户手册的“中断和事件”章节阅读,芯片已知问题以勘误手册为准。

5.7.1 相关文件

相对路径 作用
Middlewares/freertos/include/FreeRTOSConfig.h 配置内核行为:节拍频率、最大优先级数、最小栈与堆大小、抢占开关,并映射移植层的异常处理函数
Middlewares/freertos/include/task.h 声明任务创建、调度启动、延时、删除与临界区等任务管理接口
Middlewares/freertos/tasks.c 实现任务管理与调度器等内核功能
Middlewares/freertos/portable/RVDS/ARM_CM0/port.c 提供 Cortex-M0 的移植层实现,含启动调度、任务切换与节拍所需函数
projects/n32g033_EVAL/examples/FreeRTOS/ FreeRTOS 示例根目录,含 LED_Blink 1 个示例
projects/n32g033_EVAL/examples/FreeRTOS/LED_Blink/ 该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt
projects/n32g033_EVAL/bsp/ 示例共用的板级支持文件:log.h 的串口日志接口

5.7.2 API 参考

本模块不提供独立的驱动库,接口来自开发包内的 FreeRTOS 内核与配置。任务管理接口声明于 Middlewares/freertos/include/task.h,由 Middlewares/freertos/tasks.c 实现;内核行为由 Middlewares/freertos/include/FreeRTOSConfig.h 配置,节拍频率、最大优先级数与堆大小是其中最常用的几项;Cortex-M0 的移植实现分别位于 Middlewares/freertos/portable/RVDS/ARM_CM0/port.c 与 Middlewares/freertos/portable/IAR/ARM_CM0/port.c。示例用到的接口有 xTaskCreate、vTaskStartScheduler、vTaskDelay、vTaskDelete、xTaskGetSchedulerState 以及临界区宏 taskENTER_CRITICAL、taskEXIT_CRITICAL;节拍与上下文切换由移植层提供的 xPortSysTickHandler、vPortSVCHandler、xPortPendSVHandler 完成。

5.7.3 Demo 示例说明

本节说明 FreeRTOS 的 1 个示例:LED_Blink 用三个任务分别负责翻转 LED、打印计数与控制时序,并由 TIM3 更新中断额外翻转一个 LED。

工程目录: projects/n32g033_EVAL/examples/FreeRTOS/LED_Blink/

初始化串口、LED 引脚、TIM3 与系统节拍→创建起始任务并启动调度器→起始任务以临界区创建 LED 与日志任务后删除自身→LED 任务周期翻转 LED 并延时、日志任务周期打印并延时

项目 源码解读
功能 用 FreeRTOS 调度 LED 翻转任务与串口打印任务,并由 TIM3 更新中断额外翻转一个 LED,展示任务与中断并存。
源码组成 src/main.c 含任务优先级与栈大小宏以及 main、bsp_initialized、start_task、led_task、log_task;
src/led.c 的 LED_GPIO_Config 配置两个 LED 引脚;
src/timer.c 的 TIM3_Config 与中断处理函数翻转一个 LED;
src/n32g033_it.c 的 SysTick_Handler 把节拍转发给内核;
工程文件在 MDK-ARM/ 与 EWARM/,readme.txt 给出配置与测试步骤。
关键配置 起始任务、日志任务、LED 任务优先级依次为 0、1、2,栈大小均为 100;
节拍频率 1000 Hz(1 ms 一个节拍),最大优先级数 5;
LED2 接 PA7、LED3 接 PB1 均推挽输出,TIM3 预分频 1000-1、周期 64000-1;
串口 115200,TX PA9、RX PA10。
程序与数据路径 main → bsp_initialized 初始化串口、LED 引脚、TIM3 并配置 1 ms 系统节拍 → xTaskCreate 创建起始任务 → vTaskStartScheduler 启动调度 → 起始任务在临界区内创建 LED 任务与日志任务后删除自身 → LED 任务每次翻转 PA7 后延时 500 个节拍,日志任务每次打印计数值后延时 1000 个节拍。
主要 API 本模块无独立驱动库,示例使用 Middlewares/freertos/ 的内核接口,见 API 参考节。
验证方法 编译烧录并复位,LED2 每 500 ms 闪烁,LED3 每 1 s 闪烁,串口每秒打印一个累加数。
使用提示 开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1,硬件基于评估板 N32G033K8Q7-1_STB V1.0;
系统时钟 64 MHz。
核心代码解读与移植

示例把 LED 翻转与日志打印拆成两个任务,用起始任务完成创建后再删除自身,并用 TIM3 中断演示中断与任务并存。

数据路径: main → bsp_initialized 初始化串口、LED 与 TIM3 并设 1 ms 节拍 → xTaskCreate 建起始任务 → vTaskStartScheduler 启动调度 → 起始任务建 LED 与日志任务后 vTaskDelete 自删 → 两个任务各用 vTaskDelay 让出 CPU

1. 硬件与节拍在内核启动前一次性初始化。 bsp_initialized 备好串口、LED、TIM3 与系统节拍后,main 才创建任务并启动调度。

src/main.csrc/main.c · main
int main(void)
{
    /* hardware initialization */
    bsp_initialized();
    
    /* Create Start Task */
    xTaskCreate((TaskFunction_t )start_task,            //Task function
                (const char*    )"start_task",          //Task name
                (uint16_t       )START_STK_SIZE,        //Task stack size
                (void*          )NULL,                  //Parameters passed to the task function
                (UBaseType_t    )START_TASK_PRIO,       //Task priority
                (TaskHandle_t*  )&StartTask_Handler);   //task handle 

    /* Start task scheduling */
    vTaskStartScheduler();    

    while (1)
    {
    }
}
src/main.csrc/main.c · bsp_initialized
void bsp_initialized(void)
{
    log_init();
    LED_GPIO_Config();
    TIM3_Config();
    SysTick_Config(SystemCoreClock / configTICK_RATE_HZ);

    printf("bsp_initialized \r\n");
}

节拍由 SysTick_Config(SystemCoreClock / configTICK_RATE_HZ) 定成 1 ms,移植时要保证重装载值与内核节拍一致,否则任务延时的时间会失准。

2. 起始任务在临界区内创建其余任务后删除自身。 进入临界区可避免建任务过程中被调度打断,两个任务建好后再删除起始任务。

src/main.csrc/main.c · start_task
void start_task(void *pvParameters)
{
    /* Entering the critical zone */
    taskENTER_CRITICAL(); 
    
    /* Create LED Test task */
    xTaskCreate((TaskFunction_t )led_task,         
                (const char*    )"led_task",       
                (uint16_t       )LED_STK_SIZE, 
                (void*          )NULL,                
                (UBaseType_t    )LED_TASK_PRIO,    
                (TaskHandle_t*  )&LEDTask_Handler);   
    
    /* Create Uart Test task */
    xTaskCreate((TaskFunction_t )log_task,     
                (const char*    )"log_task",   
                (uint16_t       )LOG_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LOG_TASK_PRIO,
                (TaskHandle_t*  )&LOGTask_Handler);  

    /* Delete Start Task */
    vTaskDelete(StartTask_Handler);
    /* Exit the critical zone */            
    taskEXIT_CRITICAL();   
}

删除起始任务后它的栈与内存由内核回收;若把两个任务改到调度启动前创建,则不需要起始任务这一层。

3. 两个业务任务各自用延时让出 CPU。 LED 任务翻转 PA7 后延时 500 个节拍,日志任务打印后延时 1000 个节拍。

src/main.csrc/main.c · led_task
void led_task(void *pvParameters)
{
    while(1)
    {
        GPIO_TogglePin(GPIOA, GPIO_PIN_7);
        vTaskDelay(500);
    }
}
src/main.csrc/main.c · log_task
void log_task(void *pvParameters)
{
    uint32_t num = 0;

    while(1)
    {
        num += 1;

        printf("num: %d \r\n",num);
        vTaskDelay(1000);
    }
}

任务是死循环且必须以 vTaskDelay 之类的阻塞调用收尾,否则同优先级的其他任务得不到运行。

4. 节拍中断转发给内核,TIM3 中断独立工作。 系统节拍处理函数在调度器启动后把节拍交给内核,TIM3 更新中断则单独翻转 PB1。

src/n32g033_it.csrc/n32g033_it.c · SysTick_Handler
void SysTick_Handler(void)
{
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED) //The system is already running
    {
        xPortSysTickHandler();
    }
}
src/timer.csrc/timer.c · TIM3_IRQHandler
void TIM3_IRQHandler(void)
{
    if (TIM_GetIntStatus(TIM3, TIM_INT_UPDATE) != RESET)
    {
        TIM_ClrIntPendingBit(TIM3, TIM_INT_UPDATE);
        GPIO_TogglePin(GPIOB, GPIO_PIN_1);
    }
}

移植时要把这几个异常处理函数名与内核配置对应,并把调用内核接口的中断优先级设到内核允许的范围内。

对应源码: src/main.c、src/led.c、src/timer.c、src/n32g033_it.c、Middlewares/freertos/include/FreeRTOSConfig.h

5.7.4 注意与排障

场景 检查与建议 来源
中断优先级级数 用户手册中断和事件章写明 N32G033 有 4 个可编程优先等级(使用 2 位中断优先级);
配置内核与外设中断优先级时不要超过该级数。
用户手册
调用内核接口的中断优先级 用户手册中断和事件章给出各异常的向量优先级,如 SVCall 为 3、PendSV 为 5、SysTick 为 6;
调用内核接口的中断需按内核要求设置在允许范围内。
用户手册
节拍与时间基准 用户手册中断和事件章写明系统嘀嗒校准值固定为 8000,系统嘀嗒时钟设为 8 MHz 时产生 1 ms 时间基准;
节拍频率要与系统嘀嗒配置一致,否则任务延时失准。
用户手册
任务切换依赖的异常 用户手册中断和事件章写明 SVC 与 PendSV 由内核用于启动调度与任务切换,SysTick 用于产生节拍;
不要把这些异常的处理函数改为空实现。
用户手册

勘误手册 V1.0.0(2025.9.25)针对 A 版芯片,未列出 FreeRTOS 相关条目。

国民技术开发套件文档中心

按芯片系列在线查阅国民技术 MCU 开发套件的芯片资料、SDK、驱动 API 与 Demo 示例说明。

© 2026 国民技术股份有限公司 版权所有粤ICP备11069485号本站使用不含 Cookie 的匿名访问统计