多次插拔后USB无法再工作问题解决方案
问题描述客户使用的 MCU 是 STM32F446,反馈在做压力测试时发现多次插拔后, 产品意外无法再
工作。 分析了几天仍然无进展,只有 MCU 复位后才能恢复正常。
问题分析
由于此问题以属于偶发现象,一时半刻无法重现。首先能想到的是可能客户使用到了动态内
存。 通过与客户沟通,发现客户在一个比较老的 HAL 库版本上的基础上进行了改造,将原来的
动态内存方式改成了静态内存,因此,不应该是内存分析失败导致。
好在之前客户有通过 USB 分析仪采集通信过程,如下图所示:
从上图可以看出,当出现问题时,有一堆异常数据,显示为 1044 个字节,展开内容却发现
大部分字节值为 0Xff,如下图所示:
这部分数据没有合法格式,姑且认为是 USB 总线上的干扰数据,由插拔操作导致。
接下来要客户尝试在调试模式下重现问题,然后再截取异常出现时 USB 各寄存器的值,检
查是否有异常。好在不断努力下问题终于重现,并抓到异常寄存器的值 :
立即通过参考手册找到对应寄存器的对应位的描述:
从这段英文描述可以看出,当这个 EERR 位被置位时则表示 USB 内核检测到了一个莫名的
错误,并进入到挂起状态,并会产生一个早挂起中断,在这种情况下,软件需要操作软断开并恢
复。
原来是需要在这种情况下由软件复位 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 插拔的过程中,由
于电气方面的原因导致那一堆乱码, 这个不太好量化。 好在我们基于微处理器的相关出错提示确
实能解决该问题,不失为一种解决问题的参考。
有那种专用的修复工具吗 为什么会导致这样呢 是不是进入异常的中断了啊 这个异常的位置是如何找到的啊 也就是说会产生很多垃圾数据是吗 产生了很多的坏块是吗 感觉好复杂呢~~~
页:
[1]