一般而言,RTOS的运转需要一个滴答定时器周期性地产生中断来为系统提供时钟,通常是1毫秒或者10毫秒。
对于低功耗应用场景,定时器会频繁地产生中断,使得MCU频繁被唤醒,导致功耗升高,无法满足项目需求。
freeRTOS中引入了TICKLESS模式来实现低功耗应用。
TICKLESS模式的原理是动态地改变系统时钟的中断频率,当没有任务运行时,保持MCU处于睡眠模式,减少不必要的时钟中断。
nordic nrf52832的SDK中提供了freeRTOS的低功耗应用实例,阅读源码后做一些笔记:
在freeRTOS中全局变量[xNextTaskUnblockTime]记录着下一个任务唤醒的时间,[xTickCount]记录着当前系统时间,
当系统处于空闲任务时,使用[xNextTaskUnblockTime - xTickCount]计算出MCU可以睡眠的时长,
将计算结果传给portSUPPRESS_TICKS_AND_SLEEP函数,这个函数在port_cmsis_systick.c中实现,
该函数修改RTC的中断模式,然后使用WFE的方式让MCU进入睡眠模式,当MCU被事件唤醒之后,恢复RTC中断为之前的状态。
备注:WFE方式的唤醒方式可以是SEV指令,也可以是任意中断事件,使用中断唤醒需要提前设置SEVONPEND位。
SDK的代码中在port_cmsis.c使用了SCB->SCR |= SCB_SCR_SEVONPEND_Msk;