stm32待机模式被意外唤醒之原因分析

1. 故障现象

客户在项目中使用 STM32G0B1, 由产品内置电池供电. 客户在程序中有使用到 standby 模式, 通过 WKUP2(PC13), WKUP6 引脚唤醒. 除此之外并没有其它唤醒源. 代码中有使用到 RTC,但只是用来记录日期和时间, 并没有参与 standby 的唤醒.

有两种故障现象 :

  • 第一种 : standby 被意外唤醒, 即使两个 WKUP 引脚均无触发信号.
  • 第二种 : PC13 引脚上输出一 1Hz 的方波, 即使代码中并没有配置.

Figure 1 PC13 引脚输出 1Hz 方波, 原因未明
Figure 1 PC13 引脚输出 1Hz 方波, 原因未明
故障是随机, 一般两到三天可能会出现, 暂未发现固定规律. 一旦出现, 按复位键无法恢复, 必须断电后上电才会恢复正常.

2. 故障分析

因为故障表现为断电后才能恢复, 所以判断与 RTC 域相关. 拜访客户后, 查看 RTC 和 TAMP相关寄存器,结果发现寄存器内容均于 0.
查看勘误手册, 在 2.2.6 节中发现 PC13 可能会干扰 LSE
Figure 2
Figure 2
但怎么看都跟此问题应该不相干. 为了缩小问题范围, 现场临时做了一个测试程序. 只用
WKUP2(PC13)引脚唤醒 Standby, WKUP6 则直接不用. 再代码烧进程序, 结果问题依旧, 仍然
是莫名被唤醒. 查看唤醒信号源, 结果发现 PWR_SR1.WUFI=1. 其定义如下 :
在这里插入图片描述
为内部唤醒线来的信号. 但具体是指什么并不清楚.
鉴于客户急于想解决问题, 因此, 首先想到一个 workaround. 即, 先对 RTC 域复位. 在现场测试了下对 RTC 反初始化, 结果一切都恢复正常了. 其实, RTC 域复位还可以用下面几行代码来实现 :

__HAL_RCC_PWR_CLK_ENABLE();
 HAL_PWR_EnableBkUpAccess();
 __HAL_RCC_BACKUPRESET_FORCE();
 __HAL_RCC_BACKUPRESET_RELEASE();
 HAL_PWR_DisableBkUpAccess();

至此, 客户至少有了一个 workaround 措施, 问题变得没那么紧急了. 接下来就需要查找根本原因了.

首先用 PC5 替换 PC13, 由 PC5 来做为 Standby 的唤醒源. 让客户做压力测试, 看看问题跟PC13 引脚到底有没有关系 ? 结果在测试了一周后, 问题重现. 因此得出结论 : 问题与 PC13 引脚无关. 我们不得不转换方向 .

排除了触发信号, 那么剩下的就只可能是与操作 RTC 域相关了. 客户的代码中, 与操作 RTC域相关的操作只有更新 RTC 的日期和时间操作. 客户产品是通过 CAN 总线经转换器连接 PC 的,每次连接 PC 时, PC 会发送消息给到 MCU,要求更新 RTC 日期和时间. 于是要求客户想办法让更新 RTC 的操作变得更加频繁. 很快客户反馈, 如果通过 PC 连续多次发送消息让 MCU 频繁更新RTC 的话, 问题很容易重现 ! 至此, 问题出现重大转机 !

问题变得很容易重现, 也就意味着距离找到原因不远了.

于是接下来, 让客户将更新 RTC 的操作直接由 systick 中断来触发, 每隔一定时间就更新一次RTC. 测试结果为 : 同样容易重现.

于是要客户将更新 RTC 的相关代码发过来看看.与此同时, 客户自已发现 :
在这里插入图片描述
如上所示, 图中蓝色所选的两行代码原本是没有的, 如果加上, 问题消失 。 客户询问原因.
我立即推断客户可能没有对 rtctime 这个变量做完整地初始化. 于是让客户在定义 rtctime 这个局部变量时, 同时对其进行初始化, 然后做对比测试 :

RTC_TimeTypeDef rtctime = {0};

测试结果为正常!
至此, 我们终于找到问题触发点了. 正是由于这个局部结构体变量未初始化, 导致其值一开始就是个未知的随机值, 在后面 RTC 更新操作前, 其部分成员并未显式赋值, 因此, 其值仍然为一随机值. 在 HAL_RTC_SetTime()函数中, 有这么一行语句:

hrtc->Instance->CR |= (uint32_t)(sTime->DayLightSaving | sTime->StoreOperation);

很明显, DayLinghtSaving, StoreOperation 由于未显式赋值, 其值为随机值, 结果在运行完这一行代码之后, RTC_CR 寄存器会被写入一个随机值! 一个不确定的随机值写入控制寄存器会发生什么就难以预料,这也就不难理解为什么故障会有两种不同的现象了.
修改后的代码在经过半个月的压力测试后, 问题不再重现. 至此, 问题可以判定为解决.

3. 后记

此问题我们采用的是常见的排除法来定位和解决的. 希望读者能从中吸取经验.克服浮躁本身
就成功了一半!

文件编号文件标题版本号发布日期
RM0444Reference manual STM32G0x1 advanced Arm®-based 32-bit MCUsRev 52020-11-20
ES0548Errata sheet STM32G0B1xB/xC/xE device errataRev 22022-04-11

本文档参考ST官方的《【应用笔记】LAT1271+待机模式被意外唤醒之原因分析》文档。
参考下载地址:https://download.csdn.net/download/u014319604/89034100

1设计要求 要求系统按如下方式进入和退出睡眠模式: 在系统启动2秒后,将RTC在3秒钟之后配置为产生一个报警事件,接着通过WFI指令使系统进入停机模式。 如果要唤醒系统到正常模式,可通过按Key按钮;否则,在3秒钟后,会产生RTC报警中断自动将系统唤醒。 一旦退出停机模式,系统时钟被配置成先前的状态(在停机模式下,外部高速振荡器HSE和PLL是不可用的)。 经过一段延时之后,系统将再次进入停机状态,并可按上述操作无限重复。 2 硬件电路设计 硬件电路采用与7.1小节应用实例一样硬件电路,可见图7-10。其中Key按钮用于通过PB9产生一个外部中断, LED1、LED2、LED3、LED4则用于显示处理器所处的模式和中断触发情况。 3 软件程序设计 根据任务要求,程序内容主要包括: (1) 配置GPIOB口,配置RTC,配置外部中断; (2) 配置PB口第9个引脚作为外部中断,下降延触发;配置RTC报警中断,上升沿触发; (3) 两个中断服务子程序的内容分别是:切换LED2和LED3灯的状态; 整个工程包含3个源文件:STM32F10x.s、stm32f10x_it.c和main.c,其中STM32F10x.s为启动代码,所有中断 服务子程序均在stm32f10x_it.c中,其它函数则在main.c中。下面分别介绍相关的函数,具体程序清单见参考程序。 函数SYSCLKConfig_STOP用于当处理器从停机模式唤醒之后,配置系统时钟、使能HSE和PLL,并以PLL作为系统时钟源。当处理器处理停机模式的时候,HSE、PLL是不可用的。 函数GPIO_Configuration用于配置GPIO的PC6、PC7、PC8、PC9和PB9。 函数EXTI_Configuration用于配置外部中断线9(PB9)和17(RTC报警)。 函数NVIC_Configuration配置NVIC及中断向量表,这里主要是配置外部中断线9和17。 函数EXTI9_5_IRQHandler处理按钮Key(PB9)所触发的中断,其主要作用是将LED2灯的状态翻转一次。 函数RTCAlarm_IRQHandler处理RTC报警所触发的中断,其主要作用事将LED3 灯的状态翻转一次,如果设置了唤醒标志则清除之。 运行过程: (1) 使用Keil uVision3 通过ULINK 2仿真器连接EduKit-M3实验平台,打开实验例程目录PWR_TEST子目录下的PWR.Uv2 例程,编译链接工程; (2) 选择软件调试模式,点击MDK 的Debug菜单,选择Start/Stop Debug Session项或Ctrl+F5键,在逻 辑分析仪中添加GPIOC_ODR.6、GPIOC_ODR.7、GPIOC_ODR.8、GPIOC_ODR.9,点击Run按钮即可在逻辑分析 仪中看到如图7-14,还可用Peripherals-General Port-GPIOB来模拟KEY按钮的动作; (3) 选择硬件调试模式,选择Start/Stop Debug Session项或Ctrl+F5键,下载程序并运行,观察LED灯 的变化情况。注意,当目标系统进入停机模式之后,将无法使用仿真器进行调试了; (4) 退出Debug模式,打开Flash菜单>Download,将程序下载到EduKit-M3实验平台的Flash中,按RESET键复位,观察 LED灯的情况,正常情况应为:系统处于运行模式时LED1亮、LED4灭;系统处于停机状态时LED1灭、LED4亮; 当按下KEY按钮时LED2灯状态发生反转;当发生RTC报警时LED3状态发生反转。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值