STM32U083支持如下这几种低功耗模式:sleep, low power run, low power sleep, stop0, stop1, stop2, standby, shutdown。笔者对前面六种低功耗模式比较感兴趣,所以想尝试下这些低功耗模式的进 入与唤醒。STM32Cube_FW_U0_V1.0.0中关于低功耗模式有无数个样例程序代码,那么能否只用一个程序只跑一次来测试这六种低功耗模式呢?笔者思考一番后实现了这样的代码,这就是标题中所谓一箭六雕。
低功耗模式个人解读
说明:这是阅读stm32手册后个人的猜测,可能不太准确。
sleep
以笔者的理解,sleep其实就是处理器没事做的时候在SLEEPDEEP==0的情形下执行WFI指令,cpu本身会 进入clock gating状态,手册里说CPU is stopped,其实可以更精确些“CPU clock is stopped”。退出sleep很简单,任何中断都或事件都可以退出sleep模式
low power run
手册说得比较多,笔者个人感觉一句话说清楚的,不就是DVFS嘛,降频降压。进入这种模式,cpu仍然 处于运行状态。退出low power run模式也简单,升压升频。
low power sleep
这种模式就是DVFS降频降压后,cpu无事做的时候在SLEEPDEEP==0的情形下执行WFI指令,cpu本身会进 入clock gating状态,因为电压和频率相比sleep模式都低了所以这个模式的功耗相比sleep模式会降低。
stop0
这应该是cpu处于power gating状态,但外设啥的只clock gating,regulator应该没动。进入stop0模 式的方法就是设置SLEEPDEEP=1且PWR_CR1寄存器的LPMS字段='000',执行WFI指令即可。EXTI中断线有 中断即会退出stop0模式
stop1
相比stop0,把main regulator关了。进入方式和stop0差不多,区别是设置PWR_CR1寄存器的LPMS字段='001'
stop2
在stop1基础上再进一步,把大部分的vcore域的设备都给power gating了。进入方式和stop0差不多, 区别是设置PWR_CR1寄存器的LPMS字段=‘002’
程序框架
时钟源只用MSI,启动后慢闪LED 5s, 进入每一个模式前块闪LED 5s,然后熄灭进入对应low power模式,通过USER按键中断唤醒。六个模式都测完后,LED慢闪10s以提示一轮完毕,然后再次循环。用伪码表示就是:
复制
for (;;) {
toggle_speed = LED_TOGGLE_FAST;
try_sleep();
try_lprun();
try_lpsleep();
try_stop0();
try_stop1();
try_stop2();
toggle_speed = LED_TOGGLE_SLOW;
HAL_Delay(10000);
}
实现try_sleep()函数如下:
复制
static void try_sleep(void)
{
/* Insert 5 second delay */
HAL_Delay(5000);
/* Turn off LED4 */
BSP_LED_Off(LED4);
/* Suspend Tick increment */
HAL_SuspendTick();
/* Enter the CPU to SLEEP mode */
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI) ;
/* Resume Tick increment */
HAL_ResumeTick();
}
实现try_lprun()函数如下:
复制
static void try_lprun(void)
{
/* Insert 5 second delay */
HAL_Delay(5000);
/* Reduce the System clock */
SystemClock_Decrease();
/* Set regulator voltage to scale 2 */
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);
/* De-init LED4 */
BSP_LED_DeInit(LED4);
/* Enter LP RUN Mode */
HAL_PWREx_EnableLowPowerRunMode();
/* Wait until User push-button pressed */
while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_RESET)
{
}
/* Wait until User push-button released */
while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_SET)
{
}
/* Disable low power run mode and reset the clock to initialization configuration */
HAL_PWREx_DisableLowPowerRunMode();
/* Set regulator voltage to scale 1 */
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Re-init LED4 to toggle during Run mode */
BSP_LED_Init(LED4);
/* Configure the system clock for the RUN mode */
SystemClock_Config();
}
实现try_lpsleep()函数如下:
复制
static void try_lpsleep(void)
{
/* Insert 5 second delay */
HAL_Delay(5000);
/* Reduce the System clock */
SystemClock_Decrease();
/* Set regulator voltage to scale 2 */
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);
/* Enter LP RUN Mode */
HAL_PWREx_EnableLowPowerRunMode();
/* Turn off LED4 */
BSP_LED_Off(LED4);
/* Suspend Tick increment */
HAL_SuspendTick();
/* Enter the CPU to Low Power SLEEP mode */
HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI) ;
/* Resume Tick increment */
HAL_ResumeTick();
/* Disable low power run mode and reset the clock to initialization configuration */
HAL_PWREx_DisableLowPowerRunMode();
/* Set regulator voltage to scale 1 */
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Configure the system clock for the RUN mode */
SystemClock_Config();
}
实现try_stop0()函数如下:
复制
static void try_stop0(void)
{
/* Insert 5 second delay */
HAL_Delay(5000);
/* Turn off LED4 */
BSP_LED_Off(LED4);
/* Suspend Tick increment to prevent wakeup by Systick interrupt. */
/* Otherwise the Systick interrupt will wake up the device within 1ms */
/* (HAL time base). */
HAL_SuspendTick();
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
/* ... STOP 0 mode ... */
/* Re-configure the system clock to 48 MHz based on MSI */
SystemClock_Config();
}
实现try_stop1()函数如下:
复制
static void try_stop1(void)
{
/* Insert 5 second delay */
HAL_Delay(5000);
/* Turn off LED4 */
BSP_LED_Off(LED4);
/* Suspend Tick increment to prevent wakeup by Systick interrupt. */
/* Otherwise the Systick interrupt will wake up the device within 1ms */
/* (HAL time base). */
HAL_SuspendTick();
HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
/* ... STOP 1 mode ... */
/* Re-configure the system clock to 48 MHz based on MSI */
SystemClock_Config();
}
实现try_stop2()函数如下:
复制
static void try_stop1(void)
{
/* Insert 5 second delay */
HAL_Delay(5000);
/* Turn off LED4 */
BSP_LED_Off(LED4);
/* Suspend Tick increment to prevent wakeup by Systick interrupt. */
/* Otherwise the Systick interrupt will wake up the device within 1ms */
/* (HAL time base). */
HAL_SuspendTick();
HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
/* ... STOP 1 mode ... */
/* Re-configure the system clock to 48 MHz based on MSI */
SystemClock_Config();
}
运行视频在https://www.bilibili.com/video/BV1Nb421B7zV/?vd_source=e03ac0ea40b8a1877cedbbaee5737b10
由此可看到sleep、low power run、low power sleep、stop0、stop1和stop2模式进入与退出均正常,但由于笔者万用表电流档烧了,所以不能测出对应模式的功耗,不然视频做得更好。
---------------------
作者:xhackerustc
链接:https://bbs.21ic.com/icview-3379734-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。