目录
一、低功耗Tickless模式
1、低功耗Tickless模式的引入
2、Tickless 具体实现
二、空闲任务
1、空闲任务相关知识点
2、钩子函数
3、空闲任务钩子函数
三、使用RTOS的好处
一、低功耗Tickless模式
1、低功耗Tickless模式的引入
FreeRTOS 的系统时钟是由滴答定时器中断来提供的,系统时钟频率越高,那么滴答定时器中断频率也就越高。中断是可以将MCU从睡眠模式中唤醒,周期性的滴答定时器中断就会导致MCU周期性的进入和退出睡眠模式。因此,如果滴答定时器中断频率太高的话会导致大量的能量和时间消耗在进出睡眠模式中,这样导致的结果就是低功耗模式的作用被大大的削弱。
为此,FreeRTOS 特地提供了一个解决方法——Tickless 模式,当处理器进入空闲任务周期以后就关闭系统节拍中断(滴答定时器中断),只有当其他中断发生或者其他任务需要处理的时候处理器才会被从低功耗模式中唤醒。
2、Tickless 具体实现
(1)宏 configUSE_TICKLESS_IDLE
要想使用Tickless模式,首先必须将FreeRTOSConfig.h 中的宏 configUSE_TICKLESS_IDLE 设置为1。
(2)宏 portSUPPRESS_TICKS_AND_SLEEP()
使能Tickless模式以后当下面两种情况都出现的时候FreeRTOS内核就会调用宏portSUPPRESS_TICKS_AND_SLEEPO来处理低功耗相关的工作:
①空闲任务是唯一可运行的任务,因为其他所有的任务都处于阻塞态或者挂起态。
②系统处于低功耗模式的时间至少大于configEXPECTED_IDLE_TIME_BEFORE_SLEEP个时钟节拍,宏configEXPECTED_IDLE_TIME_BEFORE_SLEEP默认在文件FreeRTOS.h中定 义为2,我们可以在FreeRTOSConfig.h中重新定义,此宏必须大于2!
(3)宏 configPRE_SLEEP_PROCESSING() 和 configPOST_SLEEP_PROCESSING()
在真正的低功耗设计中不仅仅是将处理器设置到低功耗模式就行了,还需要做一些其他的处理,比如:
①将处理器降低到合适的频率,因为频率越低功耗越小,甚至可以在进入低功耗模式以后关 闭系统时钟。
②修改时钟源,晶振的功耗肯定比处理器内部的时钟源高,进入低功耗模式以后可以切换到 内部时钟源,比如STM32的内部RC振荡器。
③关闭其他外设时钟,比如IO口的时钟。
④关闭板子上其他功能模块电源,这个需要在产品硬件设计的时候就要处理好,比如可以通 过 MOS 管来控制某个模块电源的开关,在处理器进入低功耗模式之前关闭这些模块的 电源。
FreeRTOS为我们提供了一个宏来完成这些操作,它就是configPRE_SLEEP_PROCESSING(),这个宏的具体实现内容需要用户去编写。
如果在进入低功耗模式之前我们降低了处理器频率、关闭了某些外设时钟等的话,那在退出低功耗模式以后就需要恢复处理器频率、重新打开外设时钟等,这个操作在宏configPOST_SLEEP-PROCESSING()中完成,同样的这个宏的具体内容也需要用户去编写。
(4)宏 configEXPECTED_IDLE_TIME_BEFORE_SLEEP
处理器工作在低功耗模式的时间太短没有意义,所以我们必须对工作在低功耗模式的时间做个限制,宏configEXPECTED_IDLE_TIME_BEFORE_SLEEP就是用来完成这个功能的。
默认情况下configEXPECTED_IDLE_TIME_BEFORE_SLEEP为2个时钟节拍,并且最小不能小于2个时钟节拍。如果要修改这个值的话可以在文件FreeRTOSConfi.h中对其重新定义。 此宏会在空闲任务函数prvldleTask()中使用!
二、空闲任务
1、空闲任务相关知识点
(1)当FreeRTOS的调度器启动以后就会自动的创建一个空闲任务,这样就可以确保至少有一任务可以运行。但是这个空闲任务使用最低优先级,如果应用中有其他高优先级任务处于就绪态的话这个空闲任务就不会跟高优先级的任务抢占CPU资源。
(2)空闲任务还有另外一个重要的职责,如果某个任务要调用函数vTaskDelete()删除自身,那么这个任务的任务控制块TCB和任务堆栈等这些由 FreeRTOS 系统自动分配的内存需要在空闲任务中释放掉,如果删除的是别的任务那么相应的内存就会被直接释放掉,不需要在空闲任务中释放。
2、钩子函数
(1)FreeRTOS 中有多个钩子函数,钩子函数类似回调函数,当某个功能(函数)执行的时候就会调用钩子函数,至于钩子函数的具体内容那就由用户来编写。
(2)钩子函数是一个可选功能,可以通过宏定义来选择使用哪个钩子函数,可选的钩子函数如下表所示:
钩子函数的使用方法基本相同,用户使能相应的钩子函数,然后自行根据实际需求编写钩子函数的内容。
3、空闲任务钩子函数
(1)要使用空闲任务钩子函数首先要在FreeRTOSConfig.h中将宏configUSE_IDLE_HOOK改为 1,然后编写空闲任务钩子函数vApplicationIdleHook()。
(2)在每个空闲任务运行周期都会调用空闲任务钩子函数,如果想在空闲任务优先级下处理某个任务有两种选择:
①在空闲任务钩子函数中处理任务。但是绝对不能在空闲任务钩子函数中调用任何可以 阻塞空闲任务的API函数,比如vTaskDelay(),或者其他带有阻塞时间的信号量或 队列操作函数。
②创建一个与空闲任务优先级相同的任务。创建一个任务是最好的解决方法,但是这种 方法会消耗更多的RAM。
(3)在空闲任务钩子函数中将处理器设置为低功耗模式,与FreeRTOS自带的Tickless模式比较:
①在空闲任务钩子函数进入低功耗模式的话每个滴答定时器中断都会将处理器从低功耗模式中唤醒,然后进入再进入低功耗;反复的进入低功耗、退出低功耗太需要时间,而且切换太频繁,系统不稳定。
②相对在空闲任务钩子函数进入低功耗模式, FreeRTOS自带的Tickless模式更加合理有效。
三、使用RTOS的好处
1、把功能按任务划分,减少功能代码之间的耦合性;
2、增加代码的扩展性,方便后期的维护,功能的添加或者删减;
3、增加代码的可读性;