1 空闲任务
空闲任务也是任务,只不过优先级最低,也要像其它静态任务的创建声明各句柄和任务栈。
而且,空闲任务的静态创建是内嵌在vTaskStartScheduler 任务开启调度函数中,这说明空闲任务控制块的名字,栈空间的命名,空闲任务的实现函数这些应该都是固定好了的,该函数还把空闲任务加入了就绪列表。如果要在空闲任务做些事情,可以找到这个空闲任务的具体实现函数prvIdleTask里面去添加一些。当然,动态空闲任务的创建也是在这里,无非是在配置头文件里改一下,以及不需要声明任务栈。
2 阻塞延时
首先是在任务控制增加入一个成员。
TickType_t xTicksToDelay;
这个表示延时的时间。
当任务主动调用vTaskDelay();就会申请阻塞,在这个函数中只是把申请阻塞的时候赋值给TCB下的这个新增成员,然后调用任务切换函数taskYIELD()。如之前所讲,这个函数最后触发PendSV中断,而在PendSV中断函数中,最重要的当然是这个寻找下一个任务的函数vTaskSwitchContext()。该函数修改了代码实现了在空闲任务存在的时候任务切换的选择。它去查看各任务的TCB是否为0,为0则表示延时时间到,则切换到这个延时时间到的,如果都不为0,则就去执行空闲任务。
Systick中断服务函数实现了在每个Tick到的时候对各控制块的xTicksToDelay减一。其中具体调用了一个xTaskIncrementTick()函数。这个函数很简单,就是把一个表示当前计算的总的计数Tick加1,并且把各TCB的xTicksToDelay减一,然后执行一次taskYIELD(),又去开启任务调度,挂起PendSV,当Systick中断退出的时候,又执行任务切换,又调用vTaskSwitchContext函数。
为了顺利的产生Systick中断,则必须有对Systick的初始化函数,这个初始函数被内嵌到xPortStartScheduler--->xPortStartScheduler()函数中。
当前,空闲任务的创建以及Systick的初始化函数都被内嵌到了xPortStartScheduler中了。
至此。空闲任务以及延时阻塞的函数差不多完了。