一、任务管理
1、基本概念
任务是系统资源竞争的最小单元,FreeRTOS为每个任务分配独立的堆栈空间,同一时刻,系统中只允许一个任务运行,由FreeRTOS调度器决定运行的任务,负责任务调度,在任务的切换过程中保存上下文到任务的堆栈空间,任务运行前使用堆栈指针MSP,任务运行时使用PSP。
任务有不同的状态:阻塞、就绪、运行、暂停。不同状态间能实现状态迁移,迁移过程如下图:
2、任务调度
优先级:当有多个处于就绪态的任务时,通过优先级决定谁来运行,FreeRTOS中优先级数值越大,优先级越高,最大优先级由configMAX_PRIORITIES定义。比较优先级大小的方法有两种,当设置宏configUSE_PORT_OPTIMISED_TASK_SELECTION时,将通过架构指令,用类似位图的方法找到最高优先级,这种情况下,最大优先级configMAX_PRIORITIES不能超过32;另一种是通过c函数比较优先级,效率低了,但能把优先级设置的更大。
抢占:任务调度主要考虑不同优先级任务之间、相同优先级之间,对于不同优先级任务需要考虑是否允许抢占,设置configUSE_PREEMPTION宏开启抢占,这时如果有更高优先级的任务就绪,将立刻进行任务切换。不设置抢占则采取协商调度,这时高优先级任务无法抢占低优先级任务的CPU资源,只有当前任务主动让度才会切换。
时间片:相同优先级任务之间考虑是否轮转运行,配置configUSE_TIME_SLICING开启时间片轮转,抢占情况下,在没有高优先级任务打断时,相同优先级任务轮流执行,时间片用完后就切换下一个任务。时间片以Tick为单位,FreeRTOS中时间片只能是一个Tick,Tick的长度由configTICK_RATE_HZ 决定,例如设置1000,则一个Tick是1ms。
3、创建任务
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
const char * const pcName, // 任务的名字
const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节
void * const pvParameters, // 调用任务函数时传入的参数
UBaseType_t uxPriority, // 优先级
TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务
4、删除任务
void vTaskDelete( TaskHandle_t xTaskToDelete )
5、任务挂起&恢复
//挂起,被挂起的任务只能由其他任务恢复
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
//恢复
void vTaskResume( TaskHandle_t xTaskToResume )
6、非阻塞延时
//参数一般通过宏pdMS_TO_TICKS将时间转换为ticks
void vTaskDelay( const TickType_t xTicksToDelay ); /* xTicksToDelay: 等待多少给Tick */
/* pxPreviousWakeTime: 上一次被唤醒的时间
* xTimeIncrement: 要阻塞到(pxPreviousWakeTime + xTimeIncrement)
* 单位都是Tick Count
*/
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement );