应用笔记 | 看似无法唤醒的一种异常现象分析

发布者:平静宁静最新更新时间:2024-06-21 来源: elecfans关键字:异常现象  STM32 手机看文章 扫描二维码
随时随地手机看文章

1. 引言

STM32 G0 系列产品具有丰富的外设和强大的处理性能以及良好的低功耗特性,被广泛用于各类工业产品中,包括一些需要低功耗需求的应用。

2.问题描述


用户使用STM32G0B1 作为汽车多媒体音响控制器的控制芯片,用来作为收音机频道存贮和各种检测控制。在实验室条件下模拟汽车频繁打火的情形进行测试,连续工作72 小时实验中,进入STOP 模式后,会出现无法再继续运行的情况(屏幕没有显示输出,外部中断无反应)。



3. 问题重现


通常调查问题时采取调试监控的方式。但是用户产品是在检测外部掉电时,测外部电压(汽车ACC 电源,轿车12V)下降后,立刻进入低功耗模式,然后通过RTC 和外部中断(PC13 下降沿触发即汽车打火上电)唤醒MCU 继续工作。


那么既然是已经进入低功耗模式,并且在几十个小时内才会出现故障,通常的用ST-LINK 在线调试方式显然很困难重现问题,即使幸运的遇到了故障,也很容易错过引起故障的代码部分,看到了现象却无法定位。


在此种情况下,正面分析出问题的可能性极小,况且用户代码量超过200k。这时候采用排除法不失为一种可行的办法。通过增加测试样本数量,进行并行测试提高定位效率。


图1 是为了方便说明问题,模拟用户关键程序。主要是进入STOP 前后外设的处理,来复现故障现象。


15e90e7e-2a0f-11ee-a368-dac502259ad0.png

图1 模拟ACC掉电唤醒程序


在经过一段时间的实验,并从增加和减少该段代码的排除中,最后验证并定位到下面的代码引起故障发生。


1601bdd4-2a0f-11ee-a368-dac502259ad0.png

图2 定位到引起的故障代码


反复分析我们可以看到,在进入STOP前,用户需要停止ADC和DMA。但是在停止DMA时,用户程序直接停掉DMA的时钟。从函数名称上看,是从其他软件直接搬过来,并且误以为是DMA的默认初始化动作。


16112274-2a0f-11ee-a368-dac502259ad0.png

图3 DMA正确的停止方式


查询参考手册,停止循环模式的DMA应该从外设停止开始,而不是简单粗暴的停止DMA时钟。而且,在程序顺序上客户是先停止了DMA的时钟然后才去停止ADC的DMA请求。显然,当DMA开始工作时,突然停止时钟会使DMA和总线处于一个不确定阶段状态,因此才有极低概率发生唤醒故障。


到此已经找到了发生的原因,按说应该找到了前因后果。但奇怪的是无意中发现振荡器的波形比较奇怪,并不符合低功耗模式。


166c9672-2a0f-11ee-a368-dac502259ad0.png

图 4 外部振荡器HSE 波形


在发生故障状态时发现外部震荡器还在持续震荡,因此判定此时并非进入低功耗模式。利用IAR编译器以HOT PLUG的方式连接调试与观测。


通过调试界面可以看到,代码会不停的进入DMA中断。


16dcfe76-2a0f-11ee-a368-dac502259ad0.png

图5 故障模式下的调试


172f9474-2a0f-11ee-a368-dac502259ad0.png

图6 代码进入循环过程


奇怪的是每次并没有看到DMA的寄存器内容,原因是已经关闭了DMA外设的时钟。所以无法看到任何状态标志。退出中断时在C语言下就无法单步调试了。切换到汇编界面下,可以看到代码可以继续运行到系统时钟配置函数,但是在配置函数中的除法部分进入了循环,然后又发生了DMA中断,并且循环没有出来。


显然,正常的调试手段已显示出逻辑的不正常。


4.小结


至此,情况已经明了。由于软件在进入低功耗前试图关闭ADC加DMA工作,没有按照手册的规范,通过外设停止的方式关闭,而是简单粗暴的关闭DMA时钟,导致总线和运行逻辑出错,无法继续执行。


外部看起来像是进入低功耗模式后,外部中断触发没有执行,芯片没有唤醒,实际上是DMA进入了不正常的循环中断方式导致了系统卡在循环代码下。


芯片的外设功能强大,每种外设运行的方式也不相同,因此停止外设时需根据外设特点以及参考手册的建议来实施,切不可按自己想象的方式执行,这样引起隐蔽的偶发故障就很难去定位解决了。


此外ST已经建立好完整强大的生态系统,按照cube 软件库的规范编写调用驱动函数可以避免少走类似的弯路。


关键字:异常现象  STM32 引用地址:应用笔记 | 看似无法唤醒的一种异常现象分析

上一篇:基于keil mdk 标准外设库的软件开发
下一篇:基于IAR IDE创建工程程序不能运行怎么解决

推荐阅读最新更新时间:2024-11-03 03:04

RC522读写程序代码分享
#include stm32f10x.h #include stm32f10x_spi.h #include stm32f10x_gpio.h #include stm32f10x_rcc.h #include delay.h #include mfrc522.h #include stdio.h #define SPI_CE_LOW() GPIO_ResetBits(GPIOA,GPIO_Pin_4) #define SPI_CE_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_4) void SPI1_Init(void) { RCC_AP
[单片机]
STM32失能时钟和复位外设的区别
在STM32参考手册中,都有Reset and Clock Control(RCC)复位和时钟控制的章节。 在这一章节就可以看到有两类寄存器: peripheral reset register(RSTR)外设复位寄存器。 peripheral clock enable register(ENR)外设时钟使能寄存器。 我们拿STM32F1参考手册为例,可以看到如下图寄存器: 一种是控制外设时钟的寄存器,一种是复位外设的寄存器。 外设时钟使能和失能 我们都知道,配置STM32外设,会先开启对应的时钟(也就是使能外设时钟)。 比如使能USART1时钟: RCC_APB2PeriphClockCmd(RCC_APB2Periph
[单片机]
<font color='red'>STM32</font>失能时钟和复位外设的区别
stm32实际运用中遇到的问题
1.不要太相信stm32内部的IO上下拉,必要的话,在外部接上下拉电阻。 2.当把JTAG的IO口当成普通IO口来使用时,要先禁止JTAG。 即:要使用到PB3、PB4、PA13、PA14、PA15时,要先禁止JTAG。 在库函数中,调用一下函数: GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//关闭jtag,保留swd 在寄存器编程中,用: //JTAG模式设置,用于设置JTAG的模式 //mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭; //#define JTAG_SWD_DISABLE
[单片机]
stm32 的Flash Loader Demonstrator改写
本来是写在了baidu的blog上的,不知触犯了什么规矩,居然发布失败,只能改在这里了,我觉得我的一些想法,一些工作中的闪光的发现,能告诉大家,挺好的。 因为让设备Boot0 = 1后,设备一直狂发00,所以,st的那个Flash Loader demo无法Next成功。 实际上,这个ISP的协议早已经公开了,大家可以自己编写下载工具的。 首先先说一下,我使用的是V2.6.0的版本,其它的应该类似吧。或者以后的版本,ST自己会改正这部分。 在安装目录里有一个Src 之后打开STMicroelectronics Flash Loader project.sln 查找STUARTBLLIB.cpp 里面的这
[单片机]
STM32学习笔记——系统定时器SysTick的使用
//Cortex系统定时器SysTick提供1个24位、降序、零约束、写清除的计数器,具有灵活的控制机制 #include stm32f10x_lib.h GPIO_InitTypeDef GPIO_InitStructure; //定义用于初始化配置GPIO的结构体变量 static vu32 TimingDelay; //定义为volatile类型 ErrorStatus HSEStartUpStatus; //定义枚举类型的错误状态 void TimingDelay_Decrement(void); void RCC_Configuration(void); void
[单片机]
STM32学习笔记(4) 高级定时器-两路互补的PWM输出(带死区和刹车控制)
1.实验目的 使用高级定时器,输出两路互补的PWM输出,需要有带死区和不带死区两种情况 2.实验效果 图1:不带死区的两路互补的PWM输出 图2 :带死区的两路互补的PWM输出 3.理论部分 3.1时钟源 内部时钟(基本定时器,通用定时器时钟源来自PCLK1,但高级定时器的时钟源来自PCLK2(72M)) 实践中几乎无需使用:外部时钟模式1、外部时钟模式2 3.2时基单元 组成: 16bit预分频PSC 16bit计数器CNT 8bit重复计数器RCR(高级定时器独有) 16bit自动重装载寄存器ARR 3.3输入捕获 作用:对输入信号的上升沿/下降沿/双边沿进行捕获,测量输入信号的脉宽,和
[单片机]
<font color='red'>STM32</font>学习笔记(4) 高级定时器-两路互补的PWM输出(带死区和刹车控制)
STM32的CAN总线中继器设计及应用
引言 CAN总线是一种多主方式的串行通信总线,具有优良的稳定性、实时性、远程通信能力以及超强的硬件CRC纠错等特性;CAN总线技术的应用不再仅限于汽车行业,而是扩展到了机械、纺织、控制等行业,并被公认为是最有前途的现场总线之一。然而由于受制于CAN收发器,CAN总线通信距离和网络中节点数被分别限制在10 km和110个之内。但是在稍大型的CAN总线系统中,这往往是不够的,这时就需要用CAN总线中继器对CAN总线网络进行扩展。 CAN中继器是系统组网的关键技术设备之一,使用中继器可以提高网络设计的灵活性,并且通过中继器还可以连接两个不同波特率的CAN总线网络;在两个网络间进行数据转发,极大地扩展其使用范围。基于此,本文设计出
[单片机]
<font color='red'>STM32</font>的CAN总线中继器设计及应用
STM32 UART2程序
USART1程序很多,看看USART2程序。注意红色部分,首先要使能相关端口的时钟。 因为USART2可以映射成不同的端口,所以要端口映射。 结合你自己的开发板,设置正确的映射口.(正点原子的是PA03PA02.) STM32F103ZE默认的USART2就是PA03PA02,如果配置映射,USART2端口是PD05PD06了。 程序在正点原子开发板SRAM中调试通过,开发环境IAR5.30. void USART2_Initialise( u32 bound ) { GPIO_InitTypeDef GPIO_InitStructure;//I/O¿ú3õê¼»ˉ½á11ìå NVIC_InitTypeDef N
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved