[应用相关]

MCU进入深度睡眠模式的函数浅析

[复制链接]
4375|12
手机看帖
扫描二维码
随时随地手机跟帖
hoop|  楼主 | 2021-6-19 16:09 | 显示全部楼层 |阅读模式
本帖最后由 hoop 于 2022-3-19 14:10 编辑

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函数前已有事件挂起时,那将会立即退出深度睡眠,达不到应用期望的效果。

使用特权

评论回复
skyred| | 2021-7-3 10:49 | 显示全部楼层
学习一下
一直没用过停机,低功耗,唤醒之类
没准哪天会有需求

使用特权

评论回复
koala889| | 2021-7-5 15:56 | 显示全部楼层
停机之后,要如何处理么?

使用特权

评论回复
hoop|  楼主 | 2021-7-5 19:19 | 显示全部楼层
koala889 发表于 2021-7-5 15:56
停机之后,要如何处理么?

你具体是指哪一部分?一般进入停机后就等待唤醒就好了,唤醒后的系统时钟是跑的HSI(PLL及HSE被强制关闭),如果有时钟要求,就需要手动去开并切换到你需要的时钟。

使用特权

评论回复
guijial511| | 2021-7-5 20:38 | 显示全部楼层
停机之后等待外部唤醒

使用特权

评论回复
两只袜子| | 2021-7-6 14:28 | 显示全部楼层
学习一下

使用特权

评论回复
koala889| | 2021-7-7 16:50 | 显示全部楼层
hoop 发表于 2021-7-5 19:19
你具体是指哪一部分?一般进入停机后就等待唤醒就好了,唤醒后的系统时钟是跑的HSI(PLL及HSE被强制关闭 ...

恩恩,我可能理解错了,
这个应该类似于休眠,待机
一说停机模式,我理解成全都停了,还纳闷呢,怎么不直接断电

使用特权

评论回复
fuqinyyy| | 2021-7-11 09:07 | 显示全部楼层
低功耗应用场景需要这些功能。

使用特权

评论回复
084425| | 2021-7-31 18:31 | 显示全部楼层
写得很详细

使用特权

评论回复
单片小菜| | 2021-8-2 17:09 | 显示全部楼层
我一直没有搞定低功耗的模式,不知道怎么搞比较好一些,sleep模式和stop模式的区别是什么?

使用特权

评论回复
hoop|  楼主 | 2021-8-4 19:06 | 显示全部楼层
单片小菜 发表于 2021-8-2 17:09
我一直没有搞定低功耗的模式,不知道怎么搞比较好一些,sleep模式和stop模式的区别是什么?
...

耗电量不同,可用于唤醒的唤醒源不同

使用特权

评论回复
单片小菜| | 2021-8-5 11:11 | 显示全部楼层
为什么我的函数进入不了停机模式呢?

使用特权

评论回复
hoop|  楼主 | 2021-8-10 19:50 | 显示全部楼层
单片小菜 发表于 2021-8-5 11:11
为什么我的函数进入不了停机模式呢?

这个要具体看代码才能找到原因
进不了停机是指执行进停机模式命令时不会停在里面,而直接跳过执行后续代码了吗?——如果是这样,建议重点查一查执行进停机模式命令前有无已挂起的唤醒请求
还是说进不了停机表现为代码停下来了,但是功耗没下去?——如果是这样,建议看看PWR时钟是否有正常打开,是不是错调成了进Sleep的函数了,以及SLEEPDEEP这些Bit位的状态检查等等

使用特权

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

本版积分规则

80

主题

322

帖子

0

粉丝