任务转移
任务状态
讲到任务调度,就要先讲讲任务的几种状态:大类分为:非运行态和运行态,非运行态又可分为三种状态,如下:
阻塞状态:非运行态的子状态,表示任务正处于等待某个事件的状态;
任务可以进入阻塞态以等待以下两种不同类型的事件:定时(时间相关)事件——这类事件可以是延迟到期或是绝对时间到点。比如说某个任务可以进入阻塞态以延迟 10ms;
这个有两个API函数可以调用来进行延时,第一个函数
void vTaskDelay( const TickType_t xTicksToDelay )
,
xTicksToDelay:表示延时多少个心跳周期,调用该延迟函数的任务将进入阻塞态,经延迟指定的心跳周期数后,再转移到就绪态;经常使用portTICK_PERIOD_MS将延时周期转换为Ms为单位,如延时100Ms:
VTaskDelay(100/portTICK_PERIOD_MS)
;
第二个函数
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
,
该函数于实现某个任务以固定频率周期性执行,
pxPreviousWakeTime: 保存了上次被唤醒的时刻值,
xTimeIncrement :则指定任务固定频率的周期;举个例子:
static void vLEDTask( void *pvParameters )
{
TickType_t previousWakeTime;
previousWakeTime = xTaskGetTickCount();
while(1)
{
LED_Toggle(GREEN_LED_Toggle);
printf("LED Toggle\n");
vTaskDelay(300/portTICK_PERIOD_MS);//延时300Ms
vTaskDelayUntil(&previousWakeTime, 100/portTICK_PERIOD_MS);//以100Ms为单位周期性执行
}
}
同步事件——源于其它任务或中断的事件。比如说,某个任务可以进入阻塞
态以等待队列中有数据到来。同步事件囊括了所有板级范围内的事件类型。
挂起状态:非运行态的子状态,在这个状态下,调度器无法调度该任务;进入该状态只能调用 vTaskSuspend() API 函数,而将一个挂起的任务唤醒只能调用vTaskResume() 或
vTaskResumeFromISR() API 函数。就绪状态:非运行态的子状态,处于非运行态的任务如果没有被挂起或阻塞,那么该任务处于准备运行状态及就绪状态,但是还没有运行,只是准备运行。
运行态:表示该任务当前正在运行,执行相关的代码。
任务状态转移图
下面就用一个图来说明个状态之间的转移: