STM32进入standby时功耗异常分析

   日期:2020-07-08     浏览:316    评论:0    
核心提示:STM32进入standby功耗异常1. 重新烧录后功耗异常2. 重新烧录后功耗异常新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入1. 重新烧录后功耗异常2. 重新烧录后功耗异常使用STM32F031系列单片机进入s

STM32进入standby时功耗异常分析

  • 1. 前言
  • 2. 背景和现象
  • 3. 分析过程
      • Step-1 复现异常(追踪异常的发生场景)
      • Step-2 定位与故障相关硬件(缩小排查范围)
      • Step-3 尝试恢复异常(进一步摸索异常时现象)
      • Step-4 软件Debug(定位问题)
      • Step-5 验证想法
  • 4. 分析原因
  • 5. 解决方法
  • 附录A:STM32进入Standby状态完整的代码

1. 前言

本文主要用于记录STM32单片机功耗异常的分析过程,直接看 分析原因 部分可以快速知道问题原因和解决方法。

2. 背景和现象

  • 背景:使用STM32F031系列的单片机开发锂电池应用,在电池长时间不使用时,MCU需要进入极低功耗的Standby状态。
  • 开发过程: 开发过程中没有遇到太大障碍,参考ST的官方代码,实现了Standby功能。
  • 异常现象:但是在生产测试时发现,每次烧录新的程序,单片机进入Standby状态后,功耗异常。

各场景的功耗见下表:

模式 常规工作模式 Standby模式(正常) Standby模式(异常)
功耗 9mA 2uA 0.7mA

3. 分析过程

Step-1 复现异常(追踪异常的发生场景)

拿了几块功耗正常的板子,对开发与测试的场景进行了多次测试验证,发现了以下规律:

测试场景编号 开发环境 编译器 烧录器 Standby功耗
TD1 Eclipse (Oxygen-4.73) Arm-GCC J-Link 偶发性异常
TD2 Keil-MDK (v5.23) MDK默认编译器 J-Link 正常
TD3 Keil-MDK (v5.23) MDK默认编译器 ST-Link 正常
测试场景编号 生产烧录环境 烧录器 烧录器驱动 Standby功耗
TP1 STM32 ST-Link Utility (v3.7.0) ST-Link v4.4.0 全部异常
TP2 SEGGER J-Flash (v5.00) J-Link v6.10 正常

本步骤结论:特定场景的软件下载方式,会触发这个异常。

补充说明:在这一步时,怀疑烧录软件配置选项有问题,于是把烧录上位机所有的选项都改了一遍,但是没有效果。

Step-2 定位与故障相关硬件(缩小排查范围)

之前测试的是整个板子的功耗,需要在这一步定位是板上的哪个器件引起的功耗异常。

因为在烧录后会引起这个故障,所以MCU的嫌疑最大。于是,用一块只贴有MCU及其外围器件的板子(MCU核心板)再次进行了Step-1的几项测试。测得MCU自身的功耗与Step-1测的板功耗结果很接近。看来,板子功耗异常是MCU引起的

使用功耗正常、功耗异常的两块MCU核心板进行对比测试,用示波器量了MCU所有管脚的状态。发现在进入Standby状态后,异常功耗MCU的SWDIO-Pin为高电平,正常的为低电平。

查看ST Reference manual(RM0091),MCU进入Standby状态,PA13(SWDIO-Pin)是高阻态。
那么,Standby状态下SWIO-Pin输出为高电平应该是个异常状态

是因为没有固定这个脚电平?
于是,做了两个验证:

  • 外部下拉:在SWDIO脚加一个下拉电路到GND
  • 内部下拉:MCU进入Standby状态前,将SWDIO配置为下拉输入模式

结果这两种方式都没有效果。可以认定,SWDIO的高电平,与管脚电平未固定没有关系,是SWDIO自身输出(或内部上拉到)高电平。

本步骤结论:板子功耗异常是MCU引起的,此时MCU的SWDIO脚会异常输出(或内部上拉到)高电平。

Step-3 尝试恢复异常(进一步摸索异常时现象)

继续在MCU核心板上测试,尝试恢复Standby功耗异常的MCU,试了以下几种方法:

恢复方式 SWDIO状态 Standby功耗
唤醒信号给到Wakeup Pin (Wakeup event) 高电平 未恢复
拉低Reset Pin到GND1秒 (System Reset) 高电平 未恢复
使用Step-1中的5种方式重新烧录程序 (Download) 高电平 未恢复
断开板子电源后重新上电 (Power-on Reset) 低电平 恢复

本步骤结论:只有Power-on reset才能恢复功耗异常。

Step-4 软件Debug(定位问题)

这一步的思路是 单片机状态的差异,往往会体现在它的寄存器值上。
经过前几步的分析,得到了一些结论:

  1. 烧录软件后会触发异常。
  2. 异常与SWDIO-Pin状态有很大的相关性。
  3. Power-on reset可以恢复异常,System reset无法恢复异常。

以上这些结论指向MCU的调试功能。于是,将排查重点放到调试相关的寄存器上。
查看ST Reference manual(RM0091)对DBG寄存器的描述(下图),发现:

  • DBG相关的寄存器可以在调试/烧录时被Debugger所配置,这一点与结论1吻合。
  • DBG相关的寄存器只在Power-on reset时恢复默认值,这一点与结论3吻合。

    使用Eclipse+J-Link调试功耗异常的MCU核心板,读取DBG相关的寄存器,其中DBGMCU-CR寄存器的DBG_STANDBY位为1。

查看ST Reference manual(RM0091)对该位的描述(下图)。DBG_STANDBY位为1时,进入Standby模式,HCLK不会停止,而是转换为内部RC电路(内部低速晶振)作为时钟源继续运行。所以就会在异常的Standby状态下处于 比正常工作模式低,比常规standby模式高的功耗。

又拿了个standby模式下功耗正常的MCU核心板测了下,它的DBG_STANDBY位为0。看来很可能是这个原因。

Step-5 验证想法

在代码中增加主动将DBG_STANDBY清0的动作,放在进入Standby之前。

SET_BIT(RCC->APB2ENR, RCC_APB2ENR_DBGMCUEN);
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);

补充说明:这里需要注意,因为DBG也是外设的一种,操作DBG寄存器前要使能其外设时钟。

将这个程序使用Step-1中的几种方式烧录到MCU中,Standby功耗都正常。
本步骤结论:DBG_STANDBY位在烧录时被Debugger配置为1,使得MCU进入Standby功耗异常。

4. 分析原因

通过以上几个步骤的排查,再结合Step-1的测试,发现与烧录上位机STM32 ST-Link Utility的设置有关。
其中有一项配置“Enable debug in low power mode”,如果勾选了。再连接MCU,点击“connect”后,会将MCU的DBG_STANDBY位写1,且在烧录完成、断开连接后不会清除。

又进行了4项测试:

测试编号 MCU核心板类型 是否勾选Enable debug in low power mode Standby功耗
1 功耗正常 勾选 异常
2 功耗正常 不勾选 正常
3 功耗异常 勾选 异常
4 功耗异常 勾选 异常

结论:

  • 使用STM32 ST-Link Utility烧录,如果在设置中勾选了“Enable debug in low power mode”,MCU进入Standby功耗会异常。
  • 如果对功耗正常的板子不勾选“Enable debug in low power mode”进行烧录,MCU进入Standby功耗正常。
  • 功耗异常的MCU无法通过不勾选“Enable debug in low power mode”再次烧录的方式恢复

5. 解决方法


参考ST Reference manual(RM0091), 如果MCU进入Standby功耗异常,以下三种方式可以恢复:

  1. 使用Debugger将DBG_STANDBY清0
  2. 在代码中添加了进入Standby关闭DBG_STANDBY语句,重新烧录程序(参考代码见附录)
  3. 将MCU断电,Power-on reset后恢复正常功耗

附录A:STM32进入Standby状态完整的代码

下面是STM32进入Standby模式的常规代码

void Bsp_Enter_Standby(void)
{
    
    PWR->CSR |= PWR_CSR_EWUP1;

    
    PWR->CR |= PWR_CR_CWUF;                             
    PWR->CR |= PWR_CR_CSBF;                             
    PWR->CR |= PWR_CR_PDDS;                             
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
    __WFI();                                            

    
}

下面是添加关闭DBG_STANDBY的代码

void Bsp_Enter_Standby(void)
{
    
    PWR->CSR |= PWR_CSR_EWUP1;

#if (!defined(DEBUG) || !defined(USE_DBG_STANDBY))
    
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_DBGMCUEN);
    CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
#endif

    
    PWR->CR |= PWR_CR_CWUF;                             
    PWR->CR |= PWR_CR_CSBF;                             
    PWR->CR |= PWR_CR_PDDS;                             
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
    __WFI();                                            

    
}
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服