一、简介
当创建的所有的任务都处于阻塞或者挂起状态时,没有任务能够运行,但FreeRTOS必须始终至少有一个任务可以进入Running状态。为了确保这一点,调度程序在调用vTaskStartScheduler()时自动创建一个Idle任务。空闲任务只在循环中执行很少的操作——因此,就像最初的第一个示例中的任务一样,它总是能够运行。空闲任务具有尽可能低的优先级(优先级为零),以确保它永远不会阻止更高优先级的应用程序任务进入“运行”状态——尽管没有什么可以阻止应用程序设计人员以空闲任务优先级创建任务,并因此共享空闲任务优先级(如果需要的话)。可以使用FreeRTOSConfig.h中的configIDLE_SHOULD_YIELD编译时配置常数来防止Idle任务消耗处理时间,而这些处理时间本可以更有效地分配给应用程序任务。以最低优先级运行可确保在高优先级任务进入就绪状态时,将Idle任务从“运行”状态转换出来。
注意:如果应用程序使用vTaskDelete() API函数,那么Idle任务不缺乏处理时间是至关重要的。这是因为Idle任务负责在任务被删除后清理内核资源。
二、空闲任务钩子函数
可以通过使用空闲钩子(或空闲回调)函数将特定于应用程序的功能直接添加到空闲任务中,该函数在空闲任务循环的每次迭代中由空闲任务自动调用一次。
空闲任务钩子的常见用途包括:
1、执行低优先级、后台或连续处理功能。
2、测量空闲处理能力的数量。(空闲任务只有在所有高优先级应用程序任务没有工作可执行时才会运行;因此,测量分配给空闲任务的处理时间可以清楚地表明有多少处理时间是空闲的)
3、将处理器置于低功耗模式,当没有应用程序处理要执行时,提供一种简单而自动的省电方法。
三、对空闲任务钩子函数实现的限制
空闲任务钩子函数必须遵守以下规则:
1、空闲任务钩子函数绝不能试图阻塞或挂起。
注意:以任何方式阻塞空闲任务都可能导致没有任务可以进入Running状态。
2、如果应用程序使用vTaskDelete() API函数,那么空闲任务钩子必须总是在合理的时间段内返回到其调用者。这是因为Idle任务负责在任务被删除后清理内核资源。如果空闲任务永久地保留在idle钩子函数中,则不能进行清理。
空闲任务钩子函数必须具有如下所示的名称和原型:
void vApplicationIdleHook( void );
若要使用钩子函数还需将在FreeRTOSConfig.h中的configUSE_IDLE_HOOK必须设置为1,这样空闲钩子函数才能被调用。
四、实例:定义空闲任务钩子函数
创建2个任务,然后让2个任务都会被同时阻塞一段时间,任务创建参考FreeRTOS-任务管理-CSDN博客,除此之外再创建一个空闲钩子函数,空闲钩子函数的功能是将Flag置3,然后通过keil仿真观察逻辑分析仪。 2个任务和空闲钩子函数如下:
void task1(void *pvparameter)
{
while(1)
{
taskflagrun=0;
int i=0xffff;
while(i--);//让任务等一会再进入阻塞状态
vTaskDelay(2);
}
}
void task2(void *pvparameter)
{
while(1)
{
taskflagrun=1;
int i=0xffff;
while(i--);//让任务等一会再进入阻塞状态
vTaskDelay(5);
}
}
void vApplicationIdleHook(void)
{
taskflagrun=3;
}
逻辑分析仪现象如图1所示,任务1和2都处于阻塞状态时将会运行空闲任务。