3. 任务优先级实验

任务说明

本实验在FreeRTOS中创建三个不同优先级的任务,通过串口输出观察高优先级任务如何抢占低优先级任务的CPU执行权。任务优先级数值越小优先级越低(FreeRTOS中数值越大优先级越高),实验中高优先级任务将周期性唤醒并立即抢占正在运行的低优先级任务。

硬件与环境依赖

  • 开发板:STM32F407最小系统板(或其他Cortex-M4内核板卡)
  • 调试器:ST-Link/J-Link
  • 软件:STM32CubeIDE 1.13+(含FreeRTOS中间件)或任意支持FreeRTOS的嵌入式IDE
  • 串口:USART2,波特率115200,PA2(TX)/PA3(RX)

核心实现

/* main.c — FreeRTOS任务优先级抢占演示 */
#include "FreeRTOS.h"
#include "task.h"
#include "usart.h"

/* 任务句柄 */
TaskHandle_t xLowTaskHandle, xMidTaskHandle, xHighTaskHandle;

/* 三个不同优先级的任务函数 */
void vLowPriorityTask(void *pvParameters)
{
    uint32_t ulCount = 0;
    for (;;)
    {
        printf("[LOW ] Running, count=%lu\r\n", ulCount++);
        vTaskDelay(pdMS_TO_TICKS(500));  /* 主动让出CPU */
    }
}

void vMidPriorityTask(void *pvParameters)
{
    uint32_t ulCount = 0;
    for (;;)
    {
        printf("[MID ] Running, count=%lu\r\n", ulCount++);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void vHighPriorityTask(void *pvParameters)
{
    uint32_t ulCount = 0;
    for (;;)
    {
        printf("[HIGH] Running, count=%lu\r\n", ulCount++);
        vTaskDelay(pdMS_TO_TICKS(200));   /* 高频率唤醒,频繁抢占 */
    }
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_USART2_UART_Init();

    /* 创建三个不同优先级的任务 */
    xTaskCreate(vLowPriorityTask,  "Low",  128, NULL, 1, &xLowTaskHandle);
    xTaskCreate(vMidPriorityTask,  "Mid",  128, NULL, 2, &xMidTaskHandle);
    xTaskCreate(vHighPriorityTask, "High", 128, NULL, 3, &xHighTaskHandle);

    /* 启动调度器 */
    vTaskStartScheduler();

    /* 正常情况下不会执行到这里 */
    for (;;);
}

运行与验证

  1. 将上述代码中的printf重定向到USART2(在fputc中调用HAL_UART_Transmit),或直接使用串口发送函数替代printf。
  2. 编译烧录后,打开串口助手(115200-8-N-1),观察输出。
  3. 通过判定标准:串口输出中[HIGH]出现的频率明显高于[MID]和[LOW];当[HIGH]任务从延时中唤醒时,会立即打断正在执行的[LOW]或[MID]任务,表现为高优先级任务的输出穿插在低优先级任务两次输出之间,且低优先级任务的输出间隔被拉长。

预期输出示例

[LOW ] Running, count=0
[HIGH] Running, count=0
[MID ] Running, count=0
[HIGH] Running, count=1
[LOW ] Running, count=1
[HIGH] Running, count=2
[MID ] Running, count=1
[HIGH] Running, count=3
[LOW ] Running, count=2
...

注意:由于高优先级任务每200ms唤醒一次,而低优先级任务延时500ms,高优先级任务会在低优先级任务延时期间多次运行,体现抢占式调度特性。

关键说明

  • FreeRTOS中优先级数值越大,任务优先级越高。本实验使用优先级1、2、3分别对应低、中、高三个任务。
  • 三个任务均通过vTaskDelay主动进入阻塞态,此时CPU会切换到当前就绪的最高优先级任务。
  • 若将高优先级任务的延时改为0(即vTaskDelay(0)),它将持续独占CPU,低优先级任务永远无法执行——这是验证优先级抢占的另一种极端方式,但本实验保留延时以观察周期性抢占行为。