FreeRTOS——空闲任务与钩子函数
当创建的任务大部分时间都处于阻塞态。这种状态下所有的任务都不可运行,所以也不能被调度器选中。
但处理器总是需要代码来执行——所以至少要有一个任务处于运行态。为了保证这一点,当调用 vTaskStartScheduler()时,调度器会自动创建一个空闲任务。空闲任务是一个非常短小的循环——和最早的示例任务十分相似,总是可以运行。
空闲任务拥有最低优先级(优先级 0)以保证其不会妨碍具有更高优先级的应用任务进入运行态——当然,没有任何限制说是不能把应用任务创建在与空闲任务相同的优先级上;如果需要的话,你一样可以和空闲任务一起共享优先级。
运行在最低优先级可以保证一旦有更高优先级的任务进入就绪态,空闲任务就会立即切出运行态。这一点可以在 图 9 的 tn 时刻看出来,当任务 2 退出阻塞态时,空闲任务立即切换出来以让任务 2 执行。任务 2 被看作是抢占(pre-empted)了空闲任务。抢占是自动发生的,也并不需要通知被抢占任务。
空闲任务钩子函数
通过空闲任务钩子函数(或称回调,hook, or call-back),可以直接在空闲任务中添加应用程序相关的功能。空闲任务钩子函数会被空闲任务每循环一次就自动调用一次。
通常空闲任务钩子函数被用于:
~ 执行低优先级,后台或需要不停处理的功能代码。
~ 测试出系统处理裕量(空闲任务只会在所有其它任务都不运行时才有机会执行,所以测量出空闲任务占用的处理时间就可以清楚的知道系统有多少富余的处理时间)。
~ 将处理器配置到低功耗模式——提供一种自动省电方法,使得在没有任何应用功能需要处理的时候,系统自动进入省电模式。
空闲任务钩子函数的实现限制
空闲任务钩子函数必须遵从以下规则
1. 绝不能阻塞或挂起。空闲任务只会在其它任务都不运行时才会被执行(除非有应用任务共享空闲任务优先级)。以任何方式阻塞空闲任务都可能导致没有任务能够进入运行态!
2. 如果应用程序用到了 vTaskDelete() API 函数,则空闲钩子函数必须能够尽快返回。因为在任务被删除后,空闲任务负责回收内核资源。如果空闲任务一直运行在钩子函数中,则无法进行回收工作。
空闲任务钩子函数函数原型:void vApplicationIdleHook( void );
定义一个空闲任务钩子函数
调用了带阻塞性质的 vTaskDelay() API 函数,会产生大量的空闲时间——在这期间空闲任务会得到执行,因为两个应用任务均处于阻塞态。下面的例子将通过空闲钩子函数来使用这些空间时间。
FreeRTOSConfig.h 中的配置常量 configUSE_IDLE_HOOK 必须定义为 1,这样空闲任务钩子函数才会被调用。对应用任务实现函数进行了少量的修改,用以打印输出变量 ulIdleCycleCount 的值,如 程序清单 19 所示。
欢迎加入作者的小圈子
扫描下方左边二维码加入QQ交流群,扫描下方右边二维码关注个人微信公众号并,获取更多隐藏干货,QQ交流群:859800032 微信公众号:Crystal软件学堂
作者:Liu_Jing bilibili视频教程地址:https://space.bilibili.com/5782182 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在转载文章页面给出原文连接。 如果你觉得文章对你有所帮助,烦请点个推荐,你的支持是我更文的动力。 文中若有错误,请您务必指出,感谢给予我建议并让我提高的你。 |