解决全局变量被覆写的BUG

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

最近在维护一个基于STM32F4 Discovery的USB Audio项目,之前在Mac OSX环境下测试正常,但今天在Windows10上测试了下没有声音输出。
使用Keil Debug了下发现在Windows 10 USB连接下有个关于DMA配置的全局变量被莫名其妙的改写成其他值,导致I2S DMA传输出错。

解决全局变量被覆写的BUG_第1张图片

可以发现DMA_InitStructure被改写的面目全非,难怪要出现DMA Tranfer Error了。

添加断点发现只要一进USB中断DMA_InitStructure就会被改写,先怀疑是中断导致的重入问题,因为这里面涉及到I2S DMA和USB 2个中断处理都会对这个全局变量进行写操作,所以屏蔽了所有对DMA_InitStructure的写操作,问题依旧。

后来想想刚开始思路不对,在Mac OSX上是能正常工作的,为什么在Windows10上不行呢?那一定是USB Host驱动不同导致的问题。于是用USB分析仪对比了两者的交互流程:

解决全局变量被覆写的BUG_第2张图片

两者之间明显的区别是Windows每次第一个发起的setup token包中请求的长度都是255(应该是它能处理的最大长度),而Mac OSX则是用8, 2,9这类小的长度进行试探,这无可厚非,或许Windows更喜欢采用一次性到位的策略吧。比较了USB的整个交互过程没发现其他不同。

又想了想,还是看看编译出来的map文件或许能有新的发现。果然:

sampleBuffer                           0x20000e48   Data       57600  usbd_audio_out_if.o(.bss)
USBD_StrDesc                         0x2000ef48   Data          50  usbd_req.o(.bss)
DMA_InitStructure                  0x2000ef7c   Data          60  stm32f4_discovery_audio_codec.o(.bss)

AUDIO_MAL_DMA_InitStructure0x2000efb8   Data          60  stm32f4_discovery_audio_codec.o(.bss)

根据经验很有可能USBD_StrDesc越界导致把DMA_InitStructure改写了,看了下USBD_StrDesc被填充的值的末尾数据:

解决全局变量被覆写的BUG_第3张图片

00530046不正是被改写的值吗?看了下大小是66,在代码中check了下发现USBD_StrDesc被定义为50字节的数组,难怪会出现问题,将USBD_StrDesc大小改大问题果然被解决了。

但一开始为什么在Mac OSX上是正常的呢?是因为DMA_InitStructure是放在第一次setup token里面实现的,由于Mac OSX第一次发起的请求的长度是2,没有触发覆写的边界条件,幸运的避开了这个问题。

转载于:https://my.oschina.net/u/2007478/blog/968413

你可能感兴趣的:(解决全局变量被覆写的BUG)