客户反馈说HA(arm -m7)串口开了DMA后进休眠后自动重启,读RSSR的唤醒源发现是LPACK
先介绍一下LPACK这个唤醒源:
当PCU模块向芯片系统发出即将进入低功耗的消息时,要求各外设模块尽快调整状态准备进入低功耗(相当于要熄灯睡觉了),每个外设模块在准备好之后,最后向PCU回发应答确认。只有当所有的外设都应答后,PCU才能开始调整供电系统(关闭一部分供电,切换一部分供电电源)。但如果有应答迟迟未到,那是不能随意切换电源的,此时,系统判定可能有一些模块可能工作异常,因此试图通过重启系统实现修复 –安德鲁的设计笔记本
根据我之前的经验,在还有通讯正在进行中或者是DMA没停都可能会造成LPACK,并且客户反馈如果不使用DMA能够正常进休眠,反映出来的现象就是和DMA强相关的
让客户用了各种让DMA和串口停止运行的API,Stop,Release,Abort,deinit依然会复现
后面我尝试在demo板上复现这种情况,即使用开了DMA的串口在进入低功耗发送一段较长的字符,现象是在进入低功耗后,发送的字符给截断了,从串口助手看到的现象可以判断出,在进入低功耗的时刻,这个时候DMA和串口都是在工作的,但是并没有出现复位的情况
这个时候就隐约感觉这个问题和DMA关联可能不是这么大的。
到现场查看客户代码时就感觉情况有点不太妙,MCAL和SDK混合使用,代码工程也是巨大。好在客户那边有一个熟悉他们代码流程的研发在和配合debug
基本的思路就是把复杂的问题的简单化,先把关联不大的代码慢慢注释,看问题是否能够复现,逐步定位问题
在逐步注释的过程中就发现,工程里面把串口初始化了两次,用MCAL初始化一次,用SDK初始化一次。在把后面一个初始化注释掉后,发现这个时候进休眠只会重启一次,看上去似乎是有了进展。
后面发现他进休眠前会有一个把所有外设都deinit,唤醒后重新初始化的操作。其实在这个低功耗模式下部分外设寄存器都是保持的。将这个操作去掉后程序就能正常进入低功耗了
总结一下:复杂的问题简单化,排查时要大体明白各个模块的作用,确定关联性后再做注释;对不理解的操作需要保持怀疑,不然容易被带偏