STM32 FreeRTOS基础

发布于:2025-07-27 ⋅ 阅读:(20) ⋅ 点赞:(0)

FreeRTOS 核心 API 函数详解:从任务管理到定时器控制

介绍 FreeRTOS 中几个最常用的核心 API 函数,包括任务管理、延时控制和定时器操作等关键功能。

任务管理核心函数

xTaskCreate:创建任务

xTaskCreate是 FreeRTOS 中创建任务的基础函数,用于在系统中创建一个新任务并将其添加到就绪列表中。

BaseType_t xTaskCreate(
    TaskFunction_t pvTaskCode, // 任务函数指针
    const char *const pcName, // 任务名称(调试用)
    const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小
    void *pvParameters, // 传递给任务的参数
    UBaseType_t uxPriority, // 任务优先级(0~configMAX_PRIORITIES-1)
    TaskHandle_t *pxCreatedTask // 任务句柄(可用于后续操作)
);

参数说明

  • pvTaskCode:任务函数,必须是一个无限循环结构,不能返回
  • pcName:任务名称,仅用于调试识别,最大长度由configMAX_TASK_NAME_LEN定义
  • usStackDepth:任务栈大小,单位是字 (不是字节),与处理器架构有关
  • pvParameters:传递给任务函数的参数,可以为 NULL
  • uxPriority:任务优先级,数值越大优先级越高
  • pxCreatedTask:输出参数,用于接收创建的任务句柄,可设为 NULL

返回值

  • pdPASS:任务创建成功
  • errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY:内存不足,任务创建失败

vTaskDelete:删除任务

vTaskDelete用于永久删除一个任务,被删除的任务将从所有就绪、阻塞、挂起等列表中移除。

void vTaskDelete(TaskHandle_t xTaskToDelete);

参数说明

  • xTaskToDelete:要删除的任务句柄,若为 NULL 则删除当前任务

注意事项

  • 被删除任务所占用的内存 (栈和 TCB) 只有在使用动态内存管理时才会自动释放
  • 不能删除空闲任务和定时器服务任务
  • 删除其他任务时要确保该任务不再被使用,避免悬空句柄

vTaskSuspend:挂起任务

vTaskSuspend用于将指定任务挂起,挂起的任务不会被调度器选中运行,直到被恢复。

void vTaskSuspend(TaskHandle_t xTaskToSuspend);

参数说明

  • xTaskToSuspend:要挂起的任务句柄,若为 NULL 则挂起当前任务

特点

  • 挂起操作可以嵌套,即多次挂起需要相同次数的恢复操作
  • 挂起不会释放任务已获取的资源
  • 处于任何状态的任务都可以被挂起

vTaskResume:恢复任务

vTaskResume用于恢复被挂起的任务,使其重新进入调度队列。

void vTaskResume(TaskHandle_t xTaskToResume);

参数说明

  • xTaskToResume:要恢复的任务句柄,不能为 NULL

使用示例

// 挂起任务

vTaskSuspend(xHandle);

// 一段时间后恢复任务

vTaskResume(xHandle);

延时函数

vTaskDelay:相对延时

vTaskDelay提供相对延时功能,使当前任务进入阻塞状态指定的时间。

void vTaskDelay(const TickType_t xTicksToDelay);

参数说明

  • xTicksToDelay:延时的节拍数,系统节拍由configTICK_RATE_HZ配置

特点

  • 相对延时:从调用时刻开始计算延时时间
  • 延时期间任务进入阻塞状态,CPU 可以调度其他任务
  • 实际延时时间可能大于等于指定时间,受系统调度影响

使用示例

// 延时100个节拍,如果configTICK_RATE_HZ=1000,则约为100ms

vTaskDelay(100);

// 延时1秒的跨平台写法

vTaskDelay(pdMS_TO_TICKS(1000));

定时器控制函数

xTimerCreate:创建软件定时器

xTimerCreate用于创建一个软件定时器,软件定时器是基于系统节拍的定时机制。

TimerHandle_t xTimerCreate(
    const char *const pcTimerName, // 定时器名称
    const TickType_t xTimerPeriodInTicks, // 定时器周期(节拍数)
    const UBaseType_t uxAutoReload, // 是否自动重载
    void *pvTimerID, // 定时器ID
    TimerCallbackFunction_t pxCallbackFunction // 回调函数
);

参数说明

  • pcTimerName:定时器名称,仅用于调试
  • xTimerPeriodInTicks:定时器周期,单位为节拍
  • uxAutoReload:pdTRUE表示自动重载 (周期性触发),pdFALSE表示一次性触发
  • pvTimerID:定时器 ID,可用于在回调函数中区分不同定时器
  • pxCallbackFunction:定时器超时回调函数

返回值

  • 成功:返回创建的定时器句柄
  • 失败:返回 NULL (通常是内存不足)

xTimerStart:启动定时器

xTimerStart用于启动一个已创建的定时器,使其开始计时。

BaseType_t xTimerStart(TimerHandle_t xTimer, TickType_t xTicksToWait);

参数说明

  • xTimer:要启动的定时器句柄
  • xTicksToWait:等待时间,若定时器命令队列满,最多等待的节拍数

返回值

  • pdPASS:启动成功
  • errQUEUE_FULL:失败,通常是命令队列满

xTimerStop:停止定时器

xTimerStop用于停止一个正在运行的定时器。

BaseType_t xTimerStop(TimerHandle_t xTimer, TickType_t xTicksToWait);

参数说明

  • xTimer:要停止的定时器句柄
  • xTicksToWait:等待时间,若定时器命令队列满,最多等待的节拍数

返回值

  • pdPASS:停止成功
  • errQUEUE_FULL:失败,通常是命令队列满

例子:

创建两个任务,一个是普通任务,一个是定时器任务

  • 普通任务通过xTaskCreate创建,xTimerStart 和 xTimerStop 开启和关闭定时器任务。
  • 定时器任务通过xTimerCreate创建 ,vTaskSuspend 和 vTaskResume 挂起和恢复普通任务。

// Task priorities
#define START_TASK_PRIO		1
#define LED_TASK_PRIO		2

// Task stack sizes
#define START_STK_SIZE 		128
#define LED_STK_SIZE 		128

// Task handles
TaskHandle_t StartTask_Handler;
TaskHandle_t LedTask_Handler;
TimerHandle_t PrintTimer_Handler;

// Task functions
void start_task(void *pvParameters);
void led_task(void *pvParameters);

// Timer callback function
void TimerCallback(TimerHandle_t xTimer);

int main(void)
{ 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); // Set system interrupt priority group 4
    delay_init(168);            // Initialize delay function
    uart_init(115200);          // Initialize serial port
    LED_Init();                 // Initialize LED port
    
    printf("System initialization completed, preparing to start FreeRTOS...\r\n");

    // Create the start task
    xTaskCreate((TaskFunction_t )start_task,
                (const char*    )"start_task",
                (uint16_t       )START_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )START_TASK_PRIO,
                (TaskHandle_t*  )&StartTask_Handler);
                
    vTaskStartScheduler();      // Start task scheduling
    
    // If the program executes to this point, it means the scheduler failed to start
    while(1);
}

// Start task - Create other tasks and delete itself
void start_task(void *pvParameters)
{
    BaseType_t xResult;
    
    printf("Start task is executing, creating LED and OLED tasks...\r\n");
    
    // Create the LED task
    xResult = 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);
    
    if(xResult != pdPASS) 
    {
        printf("Failed to create LED task!\r\n");
    }

    // Create the timer, set to trigger
    PrintTimer_Handler = xTimerCreate(
        "PrintTimer",          // Timer name
        pdMS_TO_TICKS(1000),   // Timer period in ticks
        pdTRUE,                // Auto-reload timer
        (void*) 0,             // Timer ID
        TimerCallback          // Timer callback function
    );

    if(PrintTimer_Handler != NULL) 
    {
         // Start the timer
        if(xTimerStart(PrintTimer_Handler, 0) != pdPASS) 
        {
            printf("Failed to start timer!\r\n");
        }
    } 
    else 
    {
        printf("Failed to create timer!\r\n");
    }

    // Delete the start task
    vTaskDelete(NULL);
}
// LED task - Control LED blinking
void led_task(void *pvParameters)
{
    int nCount = 0;
    
    while(1)
    {
        nCount++;
        if (nCount == 10)
        {
            printf("[LED Task] nCount = %d, Stop Timer\r\n", nCount);
            xTimerStop(PrintTimer_Handler, 0);
        }
        else if (nCount == 20)
        {
            printf("[LED Task] nCount = %d, Start Timer\r\n", nCount);
            xTimerStart(PrintTimer_Handler, 0);
        }

        LED0 = ~LED0;  // Toggle LED state
        printf("[LED Task] LED state toggled, state: %d, nCount = %d\r\n", LED0, nCount);
			
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}


// Timer callback function
void TimerCallback(TimerHandle_t xTimer)
{
    static u16 count = 0;
    TickType_t currentTickCount = xTaskGetTickCount();
    printf("[Timer Task] Current TickCount: %lu, count = %d\r\n", (unsigned long)currentTickCount, count);
	
    count++;
    if(count == 10)
    {
        printf("[Timer Task] Suspend LED Task, count: %d\r\n", count);
        vTaskSuspend(LedTask_Handler);        
    }
    else if(count == 20)
    {
        printf("[Timer Task] Resume LED Task, count: %d\r\n", count);
        vTaskResume(LedTask_Handler);
        count = 0;
    }
 
}


网站公告

今日签到

点亮在社区的每一天
去签到