[STM32U0] 【STM32U083测评】一箭六雕测试低功耗模式的进入与唤醒

[复制链接]
3490|5
 楼主| xhackerustc 发表于 2024-5-26 18:20 | 显示全部楼层 |阅读模式
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以提示一轮完毕,然后再次循环。用伪码表示就是:
  1. for (;;) {
  2.     toggle_speed = LED_TOGGLE_FAST;
  3.     try_sleep();
  4.     try_lprun();
  5.     try_lpsleep();
  6.     try_stop0();
  7.     try_stop1();
  8.     try_stop2();
  9.     toggle_speed = LED_TOGGLE_SLOW;
  10.     HAL_Delay(10000);
  11.   }

实现try_sleep()函数如下:
  1. static void try_sleep(void)
  2. {
  3.   /* Insert 5 second delay */
  4.   HAL_Delay(5000);

  5.   /* Turn off LED4 */
  6.   BSP_LED_Off(LED4);

  7.   /* Suspend Tick increment */
  8.   HAL_SuspendTick();

  9.   /* Enter the CPU to SLEEP mode */
  10.   HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI) ;

  11.   /* Resume Tick increment */
  12.   HAL_ResumeTick();
  13. }

实现try_lprun()函数如下:
  1. static void try_lprun(void)
  2. {
  3.   /* Insert 5 second delay */
  4.   HAL_Delay(5000);

  5.   /* Reduce the System clock */
  6.   SystemClock_Decrease();

  7.   /* Set regulator voltage to scale 2 */
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);

  9.   /* De-init LED4 */
  10.   BSP_LED_DeInit(LED4);

  11.   /* Enter LP RUN Mode */
  12.   HAL_PWREx_EnableLowPowerRunMode();

  13.   /* Wait until User push-button pressed */
  14.   while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_RESET)
  15.   {
  16.   }

  17.   /* Wait until User push-button released */
  18.   while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_SET)
  19.   {
  20.   }

  21.   /* Disable low power run mode and reset the clock to initialization configuration */
  22.   HAL_PWREx_DisableLowPowerRunMode();

  23.   /* Set regulator voltage to scale 1 */
  24.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  25.   /* Re-init LED4 to toggle during Run mode */
  26.   BSP_LED_Init(LED4);

  27.   /* Configure the system clock for the RUN mode */
  28.   SystemClock_Config();
  29. }

实现try_lpsleep()函数如下:
  1. static void try_lpsleep(void)
  2. {
  3.   /* Insert 5 second delay */
  4.   HAL_Delay(5000);

  5.   /* Reduce the System clock */
  6.   SystemClock_Decrease();

  7.   /* Set regulator voltage to scale 2 */
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);

  9.   /* Enter LP RUN Mode */
  10.   HAL_PWREx_EnableLowPowerRunMode();

  11.   /* Turn off LED4 */
  12.   BSP_LED_Off(LED4);

  13.   /* Suspend Tick increment */
  14.   HAL_SuspendTick();

  15.   /* Enter the CPU to Low Power SLEEP mode */
  16.   HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI) ;

  17.   /* Resume Tick increment */
  18.   HAL_ResumeTick();

  19.   /* Disable low power run mode and reset the clock to initialization configuration */
  20.   HAL_PWREx_DisableLowPowerRunMode();

  21.   /* Set regulator voltage to scale 1 */
  22.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  23.   /* Configure the system clock for the RUN mode */
  24.   SystemClock_Config();
  25. }

实现try_stop0()函数如下:
  1. static void try_stop0(void)
  2. {
  3.   /* Insert 5 second delay */
  4.   HAL_Delay(5000);

  5.   /* Turn off LED4 */
  6.   BSP_LED_Off(LED4);

  7.   /* Suspend Tick increment to prevent wakeup by Systick interrupt.         */
  8.   /* Otherwise the Systick interrupt will wake up the device within 1ms     */
  9.   /* (HAL time base).                                                       */
  10.   HAL_SuspendTick();

  11.   HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
  12.   /* ... STOP 0 mode ... */

  13.   /* Re-configure the system clock to 48 MHz based on MSI */
  14.   SystemClock_Config();
  15. }


实现try_stop1()函数如下:

  1. static void try_stop1(void)
  2. {
  3.   /* Insert 5 second delay */
  4.   HAL_Delay(5000);

  5.   /* Turn off LED4 */
  6.   BSP_LED_Off(LED4);

  7.   /* Suspend Tick increment to prevent wakeup by Systick interrupt.         */
  8.   /* Otherwise the Systick interrupt will wake up the device within 1ms     */
  9.   /* (HAL time base).                                                       */
  10.   HAL_SuspendTick();

  11.   HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
  12.   /* ... STOP 1 mode ... */

  13.   /* Re-configure the system clock to 48 MHz based on MSI */
  14.   SystemClock_Config();
  15. }

实现try_stop2()函数如下:

  1. static void try_stop1(void)
  2. {
  3.   /* Insert 5 second delay */
  4.   HAL_Delay(5000);

  5.   /* Turn off LED4 */
  6.   BSP_LED_Off(LED4);

  7.   /* Suspend Tick increment to prevent wakeup by Systick interrupt.         */
  8.   /* Otherwise the Systick interrupt will wake up the device within 1ms     */
  9.   /* (HAL time base).                                                       */
  10.   HAL_SuspendTick();

  11.   HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
  12.   /* ... STOP 1 mode ... */

  13.   /* Re-configure the system clock to 48 MHz based on MSI */
  14.   SystemClock_Config();
  15. }

运行视频在https://www.bilibili.com/video/BV1Nb421B7zV/?vd_source=e03ac0ea40b8a1877cedbbaee5737b10

由此可看到sleep、low power run、low power sleep、stop0、stop1和stop2模式进入与退出均正常,但由于笔者万用表电流档烧了,所以不能测出对应模式的功耗,不然视频做得更好。

咕咕呱呱孤寡 发表于 2024-6-28 08:45 | 显示全部楼层
六种低功耗模式的讲解很通俗易懂,感谢大佬的分享
中国龙芯CDX 发表于 2024-6-28 18:09 | 显示全部楼层
六种低功耗模式都在哪些情况下使用呢?
kepe 发表于 2024-7-31 01:02 | 显示全部楼层
针对STM32U083的低功耗模式测试需求,你可以使用一个程序来测试这六种低功耗模式的进入和唤醒。这种方式能够有效地验证每种低功耗模式的行为。
4c1l 发表于 2024-8-31 22:54 | 显示全部楼层
可以使用一个框架,逐个进入每种模式,并检测进入和退出这些模式的正确性。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

42

主题

166

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部