FreeRTOS任务挂起与恢复

在 FreeRTOS 中,任务的 挂起(Suspend) 和 恢复(Resume) 是常用的任务控制机制,用于临时停止和重新启动任务。以下是详细的使用方法及示例代码(C语言)。


1. 任务挂起(Suspend)

挂起任务会使其停止运行,但仍然占用内存资源,直到被恢复。

API 函数

void vTaskSuspend(TaskHandle_t xTaskToSuspend);
  • 参数

    • xTaskToSuspend:要挂起的任务的句柄(TaskHandle_t),如果传入 NULL,则挂起 当前任务

示例:挂起任务

#include "FreeRTOS.h"
#include "task.h"

TaskHandle_t xTask1Handle = NULL; // 任务句柄

void Task1(void *pvParameters) {
    while(1) {
        printf("Task1 is running...\n");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void Task2(void *pvParameters) {
    while(1) {
        printf("Task2 is running...\n");
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        
        // 挂起 Task1
        printf("Suspending Task1...\n");
        vTaskSuspend(xTask1Handle);
        vTaskDelay(5000 / portTICK_PERIOD_MS); // 等待 5 秒
        
        // 恢复 Task1
        printf("Resuming Task1...\n");
        vTaskResume(xTask1Handle);
    }
}
int main() {
    // 创建任务
    xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, &xTask1Handle);
    xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
    
    // 启动调度器
    vTaskStartScheduler();
    
    while(1);
    return 0;
}

运行结果

Task1 is running...
Task2 is running...
Task1 is running...
Task2 is running...
Suspending Task1...  (Task1 被挂起,不再输出)
Task2 is running...
Task2 is running...
Resuming Task1...    (Task1 恢复运行)
Task1 is running...
Task2 is running...
...

2. 任务恢复(Resume)

恢复被挂起的任务,使其重新进入就绪状态,等待调度。

API 函数

void vTaskResume(TaskHandle_t xTaskToResume);
  • 参数

    • xTaskToResume:要恢复的任务句柄(TaskHandle_t)。

示例:恢复任务

见上面的 Task2 示例,vTaskResume(xTask1Handle) 恢复 Task1


3. 从 ISR(中断)中恢复任务

如果需要在 中断服务程序(ISR) 中恢复任务,必须使用 带 FromISR 的 API

BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume);
  • 参数

    • xTaskToResume:要恢复的任务句柄。

  • 返回值

    • pdTRUE:恢复任务导致更高优先级任务就绪,可能需要手动触发任务切换(portYIELD_FROM_ISR())。

    • pdFALSE:没有触发更高优先级任务切换。

示例:在中断中恢复任务

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

TaskHandle_t xTask1Handle = NULL;

void Task1(void *pvParameters) {
    while(1) {
        printf("Task1 is running...\n");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

// 模拟中断服务程序(ISR)
void Some_IRQ_Handler(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    
    // 从 ISR 恢复 Task1
    xTaskResumeFromISR(xTask1Handle);
    
    // 如果需要,手动触发任务切换
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

int main() {
    xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, &xTask1Handle);
    vTaskStartScheduler();
    
    while(1);
    return 0;
}

4. 挂起所有任务(挂起调度器)

如果需要临时挂起 所有任务(但不挂起调度器本身),可以使用:

void vTaskSuspendAll(void);  // 挂起所有任务
BaseType_t xTaskResumeAll(void);  // 恢复所有任务

适用场景

  • 在 非任务环境(如初始化代码)中临时禁止任务调度。

  • 执行 关键代码段,避免被其他任务打断。

示例:挂起所有任务

void CriticalFunction(void) {
    vTaskSuspendAll();  // 禁止任务调度
    
    // 执行关键操作(不会被其他任务打断)
    SomeCriticalOperation();
    
    xTaskResumeAll();   // 恢复任务调度
}

5. 注意事项

  1. 任务挂起不会释放内存,只是暂停执行。

  2. 不能挂起空闲任务(Idle Task),否则可能导致系统死锁。

  3. 中断中恢复任务 必须使用 xTaskResumeFromISR,不能直接调用 vTaskResume

  4. 避免频繁挂起/恢复,可能影响实时性。


总结

操作API适用场景
挂起任务vTaskSuspend()临时停止某个任务
恢复任务vTaskResume()恢复被挂起的任务
中断中恢复任务xTaskResumeFromISR()在 ISR 中恢复任务
挂起所有任务vTaskSuspendAll()禁止任务调度(关键代码段)
恢复所有任务xTaskResumeAll()恢复任务调度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值