FreeRTOS TICKLESS_IDLE模式相关技术疑问
FreeRTOS Tickless Idle模式常见疑问解答
问题1:Tickless模式下SysTick的工作状态?
在Tickless idle模式下,SysTick定时器会被主动停止——毕竟进入低功耗的核心目的就是减少不必要的时钟消耗,SysTick作为高频定时器,持续运行会浪费功耗。
当调用__WFI()进入休眠前,FreeRTOS会先计算本次需要休眠的时长(对应xExpectedIdleTime的实际时间),然后切换到一个低功耗定时器(比如RTC、LPTIM这类支持低功耗运行的外设)负责唤醒。当MCU被低功耗定时器或其他唤醒源唤醒后,FreeRTOS会先计算休眠期间“丢失”的tick数,完成tick计数的补偿,之后才会重新启动SysTick定时器,恢复正常的tick调度。
简单说:休眠时SysTick停转,唤醒后先补tick,再恢复SysTick工作,不是退出__WFI()就立刻重启。
问题2:全局中断关闭后,如何触发中断唤醒?
你看到的__disable_interrupt()是关闭全局可屏蔽中断,但MCU的低功耗唤醒机制,依赖的是不可屏蔽中断(NMI)或者专门配置的唤醒源中断——这类中断不受全局中断开关的影响,即使全局中断关闭,只要唤醒源触发,就能唤醒MCU退出__WFI()。
再结合代码流程看:
- 调用
__disable_interrupt()后,会先执行eTaskConfirmSleepModeStatus()检查是否有任务需要立即调度(比如有中断刚触发、任务就绪),如果返回eAbortSleep,就不会进入休眠,直接开中断返回。 - 只有确认可以安全休眠时,才会配置好低功耗唤醒定时器(时长对应
xModifiableIdleTime),然后执行__WFI()。此时没有pending的可屏蔽中断,而唤醒源已经就绪,一旦触发就能唤醒MCU。 - 唤醒后,代码会立刻调用
__enable_interrupt()打开全局中断,之后处理唤醒中断对应的逻辑,再恢复任务调度。
附你提供的源码片段:
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { ... __disable_interrupt(); if( eTaskConfirmSleepModeStatus() == eAbortSleep ) { ... } else { ... if( xModifiableIdleTime > 0 ) { __WFI(); } ... __enable_interrupt(); ... }
内容的提问来源于stack exchange,提问作者ricky rocky
相关产品推荐
相关产品推荐

