本帖最后由 hoop 于 2022-3-19 14:08 编辑
MCU进入深度睡眠模式的函数浅析 应用中最常用的省电模式为深度模式(即Deepsleep mode),通常在PWC时钟开启后透过调用pwc_deep_sleep_mode_enter函数即可进入。
本文将以AT32F403A的V2版BSP驱动为基础,深入到底层介绍进入深度睡眠模式函数的一些要点。如下为该函数原型
void pwc_voltage_regulate_set(pwc_regulator_type pwc_regulator)
{
/* 注解① */
PWC->ctrl_bit.vrsel = pwc_regulator;
}
void pwc_deep_sleep_mode_enter(pwc_deep_sleep_enter_type pwc_deep_sleep_enter)
{
/* 注解② */
SCB->SCR |= 0x04;
if(pwc_deep_sleep_enter == PWC_DEEP_SLEEP_ENTER_WFE)
{
/* 注解④ */
__SEV();
__WFE();
__WFE();
}
else if(pwc_deep_sleep_enter == PWC_DEEP_SLEEP_ENTER_WFI)
{
/* 注解③ */
__WFI();
}
SCB->SCR &= (uint32_t)~0x4;
}
注解①
此四行命令仅实现一个功能,即设置MCU内置电压调节器俗称(LDO)在进入深度睡眠后的状态。
实际应用设计需要注入如下:
当选择参数PWC_REGULATOR_ON时,即进入深度睡眠后正常开启电压调节器,应用设计时需要注意,因正常开启LDO,故相应的功耗会略微增加,但此时退出深度睡眠时由于无需重新启动LDO,故深度睡眠的退出时间会缩短。
当选择参数PWC_REGULATOR_LOW_POWER时,即进入深度睡眠后电压调节器处于低功耗模式,应用设计时需要注意,因LDO处于低功耗模式,故相应的功耗会略微减少,但此时退出深度睡眠时因需重新启动LDO需要一点启动延时,故深度睡眠的整体退出时间会被略微拉长
注解②
设置 Cortex™-M4 系统控制寄存器中的 SLEEPDEEP 位,向系统指示可以停止Cortex™-M4时钟以保障CPU能真正进入深度睡眠模式
注解③
WFI指令为Cortex™-M4的内核指令,其相当于NOP指令,作用为等待中断。需要注意的是任意比执行WFI指令时的代码优先级更高的中断均有能力让CPU退出WFI等待。且如果执行WFI指令时,NVIC中已有其他被挂起的中断时,CPU将同样直接退出WFI等待。
实际应用设计需要注意如下:
1)调用pwc_deep_sleep_mode_enter进入深度睡眠时,需检查是否有其他中断处于挂起状态,重点针对于一些涉及有调用__disable_irq();命令来禁止中断响应的设计中;
2)如果需要在中断函数内调用pwc_deep_sleep_mode_enter进入深度睡眠时,此时要确保中断优先级的设定中,唤醒源的中断优先级必须设定为比调用pwc_deep_sleep_mode_enter的中断优先级要高,不然唤醒源将不具备唤醒能力
注解④
SEV指令为Cortex™-M4的内核指令,其相当于NOP指令,作用为发送事件。
WFE指令为Cortex™-M4的内核指令,其相当于NOP指令,作用为等待事件。
__SEV();
__WFE();
__WFE();
这一组合指令实际参考M4内核手册来写的,其实现的效果为:执行SEV,让Cortex™-M4挂起一个事件(如果之前就有事件挂起,则此指令将会变得无效,因为对于内核而言,事件不能累计记录)。随后执行第一次WFE,其会立即消耗掉挂起的事件并退出这个WFE。最后再执行第二次WFE,此时将会真正开始等待事件,如果后续有唤醒源产生唤醒事件时,才会再退出这个WFE。
实际应用设计需要注意如下:
某些MCU厂家的BSP驱动中实际上仅写一句WFE,而不是采用前述组合指令的方式。此时实际上是存在隐患的,如果实际在调用pwc_deep_sleep_mode_enter函数前已有事件挂起时,那将会立即退出深度睡眠,达不到应用期望的效果。
|