打印
[STM32U0]

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

[复制链接]
2897|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以提示一轮完毕,然后再次循环。用伪码表示就是:
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模式进入与退出均正常,但由于笔者万用表电流档烧了,所以不能测出对应模式的功耗,不然视频做得更好。

使用特权

评论回复
沙发
咕咕呱呱孤寡| | 2024-6-28 08:45 | 只看该作者
六种低功耗模式的讲解很通俗易懂,感谢大佬的分享

使用特权

评论回复
板凳
中国龙芯CDX| | 2024-6-28 18:09 | 只看该作者
六种低功耗模式都在哪些情况下使用呢?

使用特权

评论回复
地板
kepe| | 2024-7-31 01:02 | 只看该作者
针对STM32U083的低功耗模式测试需求,你可以使用一个程序来测试这六种低功耗模式的进入和唤醒。这种方式能够有效地验证每种低功耗模式的行为。

使用特权

评论回复
5
4c1l| | 2024-8-31 22:54 | 只看该作者
可以使用一个框架,逐个进入每种模式,并检测进入和退出这些模式的正确性。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

68

帖子

0

粉丝