当前位置: 首页 > news >正文

FreeRTOS任务相关API简介

FreeRTOS任务相关API简介

  • 前言
  • 任务的创建和删除
    • 动态创建任务(xTaskCreate)
      • 参数说明
      • 示例代码
      • 特点
    • 静态创建任务(xTaskCreateStatic)
      • 参数说明
      • 示例代码
      • 特点
    • 受MPU保护的任务(xTaskCreateRestricted)
      • 参数说明
      • 任务定义结构体 TaskParameters_t
      • 示例代码
      • 注意事项
    • 删除任务(vTaskDelete)
      • 参数说明
      • 注意事项
      • 函数执行流程
  • 任务的挂起和恢复
    • vTaskSuspend()
    • vTaskResume()
    • xTaskResumeFromISR()
    • 使用场景示例
    • 注意事项

前言

本文介绍了几个常用的FreeRTOS任务相关的API,列举了任务的创建、删除,挂起和恢复的API,并介绍了函数功能、入参等信息。专为初学者入门而写。希望可以给大家带来帮助。

任务的创建和删除

下面简介各种任务创建API和任务删除API:

函数描述
xTaskCreat()使用动态的方法创建一个任务
xTaskCreatStatic()使用静态的方法创建一个任务
xTaskCreatRestricted()创建一个使用MPU进行限制的任务,使用动态内存分配此任务使用的内存
vTaskDelet()删除一个任务

动态创建任务(xTaskCreate)

使用此API创建的任务,会自动从FreeRTOS的堆里面分配RAM空间,来存储任务控制块(TCB)和任务堆栈。所以在使用之前要确保内存管理文件在工程中被使用,并且确保下面这个宏的值是1:

#define configSUPPORT_DYNAMIC_ALLOCATION 1

另外,此API创建的任务默认处于就绪态,所有处于就绪态的任务,按照优先级的高低以此执行。在惹怒我调度器启动前后都可以调用此API创建任务。函数原型如下:

BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,        // 任务函数指针const char * const pcName,        // 任务名称unsigned short usStackDepth,      // 任务栈大小(单位:字,4字节)void *pvParameters,              // 传递给任务函数的参数UBaseType_t uxPriority,           // 任务优先级TaskHandle_t * const pxCreatedTask // 任务句柄
);

参数说明

参数名类型说明
pvTaskCodeTaskFunction_t任务的入口函数,即任务函数的地址。
pcNameconst char * const任务的名称,用于调试时识别任务。最大长度由configMAX_TASK_NAME_LEN定义。
usStackDepthunsigned short任务栈的大小,单位为字(4字节)。建议根据任务需求合理设置。
pvParametersvoid *传递给任务函数的参数,可以是任意类型的数据。
uxPriorityUBaseType_t任务的优先级,数值越小,优先级越高。
pxCreatedTaskTaskHandle_t *用于返回任务的句柄,以便后续操作任务。

示例代码

xTaskCreate((TaskFunction_t)start_task,       // 任务函数"start_task",                     // 任务名称1024,                             // 任务栈大小NULL,                             // 任务参数tskIDLE_PRIORITY,                // 任务优先级&StartTask_Handler);              // 任务句柄

特点

  • 适用于大多数应用场景,系统自动管理内存。
  • 任务创建后,内存可以被系统回收。
  • 适合任务数量较多或内存动态分配的场景。

静态创建任务(xTaskCreateStatic)

静态创建任务需要用户手动分配任务栈空间和任务控制块(TCB),通常用于对内存使用有严格要求的嵌入式系统。该函数的原型如下:

BaseType_t xTaskCreateStatic(TaskFunction_t pvTaskCode,        // 任务函数指针const char * const pcName,        // 任务名称uint16_t usStackDepth,            // 任务栈大小void *pvParameters,               // 任务参数UBaseType_t uxPriority,           // 任务优先级StaticTask_t *pxTaskBuffer,       // 任务控制块StackType_t *pxStackBuffer,       // 任务栈TaskHandle_t * const pxCreatedTask // 任务句柄
);

参数说明

参数名类型说明
pvTaskCodeTaskFunction_t任务的入口函数。
pcNameconst char * const任务名称,用于调试。
usStackDepthuint16_t任务栈的大小,单位为字(4字节)。
pvParametersvoid *传递给任务函数的参数。
uxPriorityUBaseType_t任务的优先级。
pxTaskBufferStaticTask_t *任务控制块的地址,用于存储任务的TCB信息。
pxStackBufferStackType_t *任务栈的地址,用于存储任务的运行上下文。
pxCreatedTaskTaskHandle_t *任务句柄,用于返回任务的句柄。

示例代码

StaticTask_t xTaskBuffer;
StackType_t xStack[1024];xTaskCreateStatic((TaskFunction_t)start_task,       // 任务函数"start_task",                     // 任务名称1024,                             // 任务栈大小NULL,                             // 任务参数tskIDLE_PRIORITY,                // 任务优先级&xTaskBuffer,                     // 任务控制块xStack,                           // 任务栈&StartTask_Handler);              // 任务句柄

特点

  • 需要用户手动分配任务栈和控制块,适合对内存使用有严格要求的场景。
  • 任务创建后,内存不会被系统回收,需手动管理。
  • 适合任务数量较少或内存有限的嵌入式系统。

在实际开发中,动态创建任务是最常用的方式,因为它简化了内存管理,而静态创建任务则适用于对内存使用有严格要求的嵌入式系统。根据具体需求选择合适的任务创建方式,可以提高系统的效率和稳定性。

受MPU保护的任务(xTaskCreateRestricted)

xTaskCreateRestricted 是 FreeRTOS 提供的一个用于创建受内存保护单元(MPU)保护的任务的函数。它允许在具有 MPU 的 MCU 上创建任务,并对任务的内存访问进行限制。该函数的功能与 xTaskCreate() 类似,但增加了对 MPU 的支持,适用于需要保护任务内存的场景。函数原型如下:

BaseType_t xTaskCreateRestricted(const TaskParameters_t * const pxTaskDefinition,TaskHandle_t * const pxCreatedTask
);

参数说明

参数名类型说明
pxTaskDefinitionconst TaskParameters_t * const指向任务定义结构体的指针,包含任务的函数、名称、堆栈大小、参数、优先级等信息。
pxCreatedTaskTaskHandle_t * const用于返回创建任务的句柄,以便后续操作任务。

任务定义结构体 TaskParameters_t

TaskParameters_t 是一个包含任务所有必要信息的结构体,通常包括以下字段:

  • pvTaskCode:任务函数指针。
  • pcName:任务名称。
  • usStackDepth:任务栈大小。
  • pvParameters:传递给任务的参数。
  • uxPriority:任务优先级。
  • xRegions:内存区域定义,用于 MPU 保护。

示例代码

以下是一个使用 xTaskCreateRestricted 创建受 MPU 保护任务的示例代码:

#include "FreeRTOS.h"
#include "task.h"// 定义任务参数结构体
typedef struct {TaskFunction_t pvTaskCode;const char * const pcName;unsigned short usStackDepth;void *pvParameters;UBaseType_t uxPriority;const MemoryRegion_t * const xRegions;
} TaskParameters_t;// 任务函数
void vMyTask(void *pvParameters) {// 任务代码while (1) {// 任务逻辑}
}// 任务定义
TaskParameters_t xTaskDefinition = {.pvTaskCode = vMyTask,.pcName = "MyTask",.usStackDepth = 1024,.pvParameters = NULL,.uxPriority = tskIDLE_PRIORITY,.xRegions = NULL // 可以定义 MPU 保护区域
};// 创建任务
TaskHandle_t xTaskHandle;int main() {// 创建任务if (xTaskCreateRestricted(&xTaskDefinition, &xTaskHandle) != pdPASS) {// 任务创建失败}// 启动调度器vTaskStartScheduler();// 任务创建成功后,进入死循环for (;;);
}

注意事项

  1. MPU 支持xTaskCreateRestricted 仅在 FreeRTOS-MPU 环境下可用,因此需要在 FreeRTOSConfig.h 中启用 configSUPPORT_DYNAMIC_ALLOCATION
  2. 内存分配:该函数使用动态内存分配来创建任务的控制块和栈空间。
  3. 任务删除:使用 vTaskDelete() 删除任务时,需要提供任务的句柄和任务控制块的地址。

vTaskDelete 是 FreeRTOS 中用于删除任务的函数,其主要功能是将指定任务从系统中移除,并释放其占用的资源。以下是关于该函数的详细说明:


删除任务(vTaskDelete)

vTaskDelete 用于删除一个已创建的任务。该函数会从任务的就绪列表、阻塞列表、挂起列表和事件列表中移除该任务,并释放其任务控制块(TCB)和堆栈内存。需要注意的是,空闲任务(Idle Task)负责释放由系统分配的内存,而用户分配的内存需要在任务删除前手动释放,否则可能导致内存泄漏 。

void vTaskDelete(TaskHandle_t xTaskToDelete);

参数说明

  • xTaskToDelete:要删除的任务的句柄。若传入 NULL,则表示删除当前正在运行的任务(即调用该函数的任务)。

注意事项

  • 必须在 FreeRTOSConfig.h 中启用 INCLUDE_vTaskDelete,否则该函数不可用。
  • 删除任务时,需确保空闲任务有足够时间执行内存释放。通常,将空闲任务的优先级设置为最低,以避免内存泄漏 。
  • 删除任务后,系统会将该任务添加到“待删除列表” ,由空闲任务在下次运行时进行清理 。

函数执行流程

  1. 检查任务句柄:若 xTaskToDeleteNULL,则删除当前任务。
  2. 从任务列表中移除:将任务从就绪、阻塞、挂起和事件列表中移除。
  3. 更新任务状态:更新任务优先级记录,并递增 uxTaskNumber 以通知内核调试器重新生成任务列表。
  4. 释放内存
    • 若删除的是当前任务,将其插入“待删除列表”,并增加 uxDeletedTasksWaitingCleanUp 变量。
    • 若删除的是其他任务,调用 prvDeleteTCB() 函数释放任务的 TCB 和堆栈内存。
  5. 强制任务切换:若删除的是当前任务,调用 portPRE_TASK_DELETE_HOOK 钩子函数,并执行任务切换 。

任务的挂起和恢复

在 FreeRTOS 中,任务的挂起和恢复是通过一系列 API 函数实现的。这些函数允许开发人员在需要暂停任务执行时将其挂起,并在需要时恢复任务的运行。以下是主要的挂起和恢复 API 函数及其功能说明:

API 函数功能描述说明
vTaskSuspend(TaskHandle_t xTaskToSuspend)挂起指定任务将任务设置为挂起状态,任务将永远处于挂起状态,除非调用 vTaskResume()xTaskResumeFromISR()
vTaskResume(TaskHandle_t xTaskToResume)恢复挂起任务将任务从挂起状态恢复到就绪状态,如果此时被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换 。
xTaskResumeFromISR(TaskHandle_t xTaskToResume)在中断服务函数中恢复任务用于在中断服务函数中恢复任务,返回值指示是否需要进行上下文切换 。

vTaskSuspend()

  • 功能:将指定任务设置为挂起状态。
  • 参数xTaskToSuspend 是要挂起的任务句柄。如果传入 NULL,则表示挂起当前任务。
  • 特点:一旦任务被挂起,它将永远处于挂起状态,直到被显式恢复。

vTaskResume()

  • 功能:将挂起的任务恢复到就绪状态。
  • 参数xTaskToResume 是要恢复的任务句柄。
  • 特点:恢复任务后,任务将重新加入就绪队列,等待调度器调度。如果恢复任务的优先级高于当前运行任务,则会发生任务切换。

xTaskResumeFromISR()

  • 功能:在中断服务函数中恢复任务。
  • 参数xTaskToResume 是要恢复的任务句柄。
  • 特点:该函数用于在中断上下文中恢复任务,返回值 pdTRUE 表示需要进行上下文切换,pdFALSE 表示不需要。

使用场景示例

以下是一个简单的示例,展示了如何在按键中断中挂起和恢复任务:

#include "FreeRTOS.h"
#include "task.h"// 任务函数
void vTaskFunction(void *pvParameters) {while (1) {printf("Task is running\n");vTaskDelay(pdMS_TO_TICKS(1000));}
}int main() {TaskHandle_t xTaskHandle = NULL;// 创建任务xTaskCreate(vTaskFunction, "Task", 1024, NULL, tskIDLE_PRIORITY, &xTaskHandle);// 启动调度器vTaskStartScheduler();// 任务创建成功后,进入死循环for (;;);
}

在中断服务函数中,可以使用 vTaskSuspend()xTaskResumeFromISR() 来控制任务的挂起和恢复:

void EXTI0_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_LINE0) != RESET) {printf("Suspend task\n");vTaskSuspend(xTaskHandle); // 挂起任务EXTI_ClearITPendingBit(EXTI_LINE0);}
}void EXTI1_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_LINE1) != RESET) {printf("Resume task\n");xTaskResumeFromISR(xTaskHandle); // 恢复任务EXTI_ClearITPendingBit(EXTI_LINE1);}
}

注意事项

  • 任务挂起和恢复的顺序:必须确保在恢复任务之前,任务已经被正确挂起。
  • 中断优先级:在中断服务函数中调用 xTaskResumeFromISR() 时,中断优先级不能高于 FreeRTOS 管理的最高优先级,否则可能导致程序异常 。
  • 任务状态:挂起的任务不会参与调度,也不会执行任何代码,直到被显式恢复 。

通过合理使用 vTaskSuspend()vTaskResume()xTaskResumeFromISR(),可以有效地管理任务的执行流程,确保任务在需要时暂停或恢复。


本文到此结束,欢迎点赞、转发、收藏!

相关文章:

  • KJY0047-J1阶段测试
  • 【游资悟道】陈小群成长历史与股市悟道心法
  • 玩转Docker | 使用Docker部署Blinko个人笔记工具
  • C++操作系统与网络编程(针对特定岗位)
  • 使用 MoviePy 实现图像序列合成视频并添加背景音乐
  • 有些植物果实结在土里,但是花开在枝叶上,果不结在花上,花需要授粉才能结果吗?不用授粉的话,开花的意义在哪里?
  • (javaSE)抽象类和接口:抽象类概念语法和特性, 抽象类的作用;接口的概念 接口特性 实现多个接口 接口间的继承 Object类
  • Linux操作系统之运维常用命令
  • JUC核心解析系列(五)——执行框架(Executor Framework)深度解析
  • 音频驱动数字人13款深度评测
  • 制品构建与管理 - Docker 镜像的最佳实践
  • 如何稳定地更新你的大模型知识(算法篇)
  • Java 常用类 Math:从“如何生成随机密码”讲起
  • k8s的开篇学习和安装
  • 灵界猫薄荷×贴贴诱发机制详解
  • 在docker中部署ollama
  • MySQL分库分表面试题深度解析
  • etcd基本数据库操作
  • CKA考试知识点分享(15)---etcd
  • 【Flutter】Widget、Element和Render的关系-Flutter三棵树
  • 陕西省建设厅的网站/磁力猫搜索引擎入口官网
  • 网站建设素材/营销推广活动方案
  • 知识产权教育网站建设方案/最新新闻
  • 网站怎么产品做推广/网络推广与营销
  • 律师网站建设建议/郑州seo培训
  • 无锡门户网站制作电话/如何提高网站的自然排名