我喜欢打游戏 发表于 2021-11-3 09:33

多次插拔后USB无法再工作问题解决方案

问题描述
客户使用的 MCU 是 STM32F446,反馈在做压力测试时发现多次插拔后, 产品意外无法再
工作。 分析了几天仍然无进展,只有 MCU 复位后才能恢复正常。

我喜欢打游戏 发表于 2021-11-3 09:34

问题分析
由于此问题以属于偶发现象,一时半刻无法重现。首先能想到的是可能客户使用到了动态内
存。 通过与客户沟通,发现客户在一个比较老的 HAL 库版本上的基础上进行了改造,将原来的
动态内存方式改成了静态内存,因此,不应该是内存分析失败导致。
好在之前客户有通过 USB 分析仪采集通信过程,如下图所示:


我喜欢打游戏 发表于 2021-11-3 09:35

从上图可以看出,当出现问题时,有一堆异常数据,显示为 1044 个字节,展开内容却发现
大部分字节值为 0Xff,如下图所示:



我喜欢打游戏 发表于 2021-11-3 09:36

这部分数据没有合法格式,姑且认为是 USB 总线上的干扰数据,由插拔操作导致。
接下来要客户尝试在调试模式下重现问题,然后再截取异常出现时 USB 各寄存器的值,检
查是否有异常。好在不断努力下问题终于重现,并抓到异常寄存器的值 :



立即通过参考手册找到对应寄存器的对应位的描述:

从这段英文描述可以看出,当这个 EERR 位被置位时则表示 USB 内核检测到了一个莫名的
错误,并进入到挂起状态,并会产生一个早挂起中断,在这种情况下,软件需要操作软断开并恢
复。


我喜欢打游戏 发表于 2021-11-3 09:37

原来是需要在这种情况下由软件复位 USB 啊。
于是接下来处理方法就变得很简单 :
1> USB 初始化时需要将 OTG_DCFG.ERRATIM=0,确保 USB 内核检测到错误时可以产生 Early
suspend 中断.
2> USB 初始化时确保使能 Early suspend 中断: OTG_GINTMSK.ESUSPM =1
3> 在 USB 中断处理函数中,在 Early suspend 中断时,判断当前 OTG_DSTS.EERR 是否为 1,如果
是,则表示出现了错误,此时需要将 USB 内核复位一下。
4> 具体 USB 内核复位过程建议先对 USB 做默认初始化,再通过 RCC 时钟控制单元单独切断 USB
的时钟再恢复,这样 USB 所有寄存器状态都能恢复到初始状态,然后再重新将 USB 初始化一
遍。
通过以上修改后当问题再现时,新增加的还原操作能将 USB 内核恢复到正常工作状态,最
终解决了问题。
至于为什么 USB 内核会检测到莫名的错误, 这里认为可能是在多次 USB 插拔的过程中,由
于电气方面的原因导致那一堆乱码, 这个不太好量化。 好在我们基于微处理器的相关出错提示确
实能解决该问题,不失为一种解决问题的参考。

keaibukelian 发表于 2021-12-1 13:15

有那种专用的修复工具吗

观海 发表于 2021-12-1 13:16

为什么会导致这样呢

guanjiaer 发表于 2021-12-1 13:17

是不是进入异常的中断了啊

heimaojingzhang 发表于 2021-12-1 13:19

这个异常的位置是如何找到的啊

tpgf 发表于 2021-12-1 13:19

也就是说会产生很多垃圾数据是吗

labasi 发表于 2021-12-1 13:26

产生了很多的坏块是吗

asmine 发表于 2021-12-2 17:17

感觉好复杂呢~~~
页: [1]
查看完整版本: 多次插拔后USB无法再工作问题解决方案