6.1 任务创建和删除 API 函数
函数 | 描述 |
xTaskCreate() | 使用动态的方法创建一个任务。 |
xTaskCreateStatic() | 使用静态的方法创建一个任务。 |
xTaskCreateRestricted() | 创建一个使用 MPU 进行限制的任务,相关内存使用动态内存分配。 |
vTaskDelete() | 删除一个任务 |
1、函数 xTaskCreate()
此函数用来创建一个任务,任务需要 RAM 来保存与任务有关的状态信息(任务控制块),任务也需要一定的 RAM 来作为任务堆栈。如果使用函数 xTaskCreate()来创建任务的话那么这些所需的 RAM 就会自动的从 FreeRTOS 的堆中分配, 因此必须提供内存管理文件,默认我们使用heap_4.c 这个内存管理文件,而且宏 configSUPPORT_DYNAMIC_ALLOCATION 必须为 1。 如果使用函数 xTaskCreateStatic()创建的话这些 RAM 就需要用户来提供了。新创建的任务默认就是就绪态的,如果当前没有比它更高优先级的任务运行那么此任务就会立即进入运行态开始运行,不管在任务调度器启动前还是启动后,都可以创建任务。 此函数也是我们以后经常用到的,本教程所有例程均用此函数来创建任务, 函数原型如下:
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, /*任务函数*/
const char * const pcName, /*任务名字,一般用于追踪和调试
长度不能超过 configMAX_TASK_NAME_LEN*/
const uint16_t usStackDepth, /*任务堆栈大小,注意实际申请到的堆栈是
usStackDepth 的4倍,空闲任务的任务堆栈
大小是 configMINIMAL_STACK_SIZE*/
void * const pvParameters, /*参数*/
UBaseType_t uxPriority, /*优先级 0~configMAX_PRIORITIES_1*/
TaskHandle_t * const pxCreatedTask ) /*任务句柄,就是任务的任务堆栈*/
返回值:
pdPASS: 任务创建成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任务创建失败,因为堆内存不足!
2、函数 xTaskCreateStatic()
使用此函数创建的任务所需 的 RAM 需 要 用 用 户 来 提 供 。 如 果 要 使 用 此 函 数 的 话 需 要 将 宏configSUPPORT_STATIC_ALLOCATION 定义为 1。函数原型如下:
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, /*任务函数*/
const char * const pcName, /*任务名字*/
const uint32_t ulStackDepth, /*堆栈大小*/
void * const pvParameters, /*参数*/
UBaseType_t uxPriority, /*优先级*/
StackType_t * const puxStackBuffer, /*任务堆栈,一般为数组*/
StaticTask_t * const pxTaskBuffer ) /*任务控制块*/
返回值:
NULL:任务创建失败,puxStackBuffer 或 pxTaskBuffer 为NULL 的时候会导致这个错误发生
其他值:任务创建成功,返回任务句柄
3、函数 xTaskCreateRestricted()
此函数也是用来创建任务的, 只不过此函数要求所使用的 MCU 有 MPU(内存保护单元),用此函数创建的任务会受到 MPU 的保护。 其他的功能和函数 xTaxkCreate()一样。
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
/*指向一个结构体 TaskParameters_t ,这个结构体描述了任务的任
务函数、堆栈大小、优先级等。此结构体在文件 task.h 中有定义*/
TaskHandle_t * pxCreatedTask)/*任务句柄*/
返回值:
pdPASS:任务创建成功
其他值:失败,可能是 FreeRTOS 的堆太小了
4、函数 vTaskDelete()
删除一个用函数 xTaskCreate()或者 xTaskCreateStatic()创建的任务,被删除了的任务不再存在,也就是说再也不会进入运行态。 任务被删除以后就不能再使用此任务的句柄!如果此任务是使用动态方法创建的,也就是使用函数 xTaskCreate()创建的,那么在此任务被删除以后此任务之前申请的堆栈和控制块内存会在空闲任务中被释放掉,因此当调用函数 vTaskDelete()删除
任务以后必须给空闲任务一定的运行时间。
只有那些由内核分配给任务的内存才会在任务被删除以后自动的释放掉,用户分配给任务的内存需要用户自行释放掉,比如某个任务中用户调用函数 pvPortMalloc()分配了 500 字节的内存,那么在此任务被删除以后用户也必须调用函数 vPortFree()将这 500 字节的内存释放掉,否则会导致内存泄露。此函数原型如下:
vTaskDelete( TaskHandle_t xTaskToDelete/*任务句柄*/ )
6.2 任务创建和删除实验(动态方法)
1、实验目的
学习如何使用这些API 函数
2、实验设计
本实验设计三个任务: start_task、 task1_task 和 task2_task ,这三个任务的任务功能如下:
start_task:用来创建其他两个任务。
task1_task :当此任务运行 5 此以后就会调用函数 vTaskDelete()删除任务 task2_task,此任务也会控制 LED0 的闪烁,并且周期性的刷新 LCD 指定区域的背景颜色。
task2_task : 此任务普通的应用任务,此任务也会控制 LED1 的闪烁,并且周期性的刷新LCD 指定区域的背景颜色。
3、实验程序与分析:
- 任务设置
- main 函数
- 任务函数
4、实验结果
6.3 任务创建和删除实验(静态方法)
6.4 任务挂起和恢复 API 函数
有时候我们需要暂停某个任务的运行,过一段时间以后在重新运行。这个时候要是使用任务删除和重建的方法的话那么任务中变量保存的值肯定丢失了! FreeRTOS 给我们提供了解决这种问题的方法, 那就是任务挂起和恢复,当某个任务要停止运行一段时间的话就将这个任务挂起,当要重新运行这个任务的话就恢复这个任务的运行。 FreeRTOS 的任务挂起和恢复 API 函数如表 6.2.1.1 所示:
函数 | 描述 |
vTaskSuspend() | 挂起一个任务。 |
vTaskResume() | 恢复一个任务的运行。 |
xTaskResumeFromISR() | 中断服务函数中恢复一个任务的运行。 |
1、函数 vTaskSuspend()
此函数用于将某个任务设置为挂起态, 进入挂起态的任务永远都不会进入运行态。退出挂起态的唯一方法就是调用任务恢复函数 vTaskResume()或 xTaskResumeFromISR()。,函数原型如下:
void vTaskSuspend( TaskHandle_t xTaskToSuspend) /*参数是要挂起的任务的任务句柄*/
2、函数 vTaskResume()
将一个任务从挂起态恢复到就绪态, 只有通过函数 vTaskSuspend()设置为挂起态的任务才可以使用 vTaskRexume()恢复!函数原型如下:
void vTaskResume( TaskHandle_t xTaskToResume)/*参数是要恢复的人物的 任务句柄
*/
3、函数 xTaskResumeFromISR()
此函数是 vTaskResume()的中断版本,用于在中断服务函数中恢复一个任务。函数原型如下:
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume)
返回值:
pdTRUE: 恢复运行的任务的任务优先级等于或者高于正在运行的任务(被中断打断的任务), 这意味着在退出中断服务函数以后必须 进行一次上下文切换。
pdFALSE: 恢复运行的任务的任务优先级低于当前正在运行的任务(被中断打断的任务),这意味着在退出中断服务函数的以后不需要 进行上下文切换。