最近在維護一個基於STM32F4 Discovery的USB Audio項目,以前在Mac OSX環境下測試正常,但今天在Windows10上測試了下沒有聲音輸出。
使用Keil Debug了下發如今Windows 10 USB鏈接下有個關於DMA配置的全局變量被莫名其妙的改寫成其餘值,致使I2S DMA傳輸出錯。數組
能夠發現DMA_InitStructure被改寫的面目全非,難怪要出現DMA Tranfer Error了。測試
添加斷點發現只要一進USB中斷DMA_InitStructure就會被改寫,先懷疑是中斷致使的重入問題,由於這裏面涉及到I2S DMA和USB 2箇中斷處理都會對這個全局變量進行寫操做,因此屏蔽了全部對DMA_InitStructure的寫操做,問題依舊。spa
後來想一想剛開始思路不對,在Mac OSX上是能正常工做的,爲何在Windows10上不行呢?那必定是USB Host驅動不一樣致使的問題。因而用USB分析儀對比了二者的交互流程:code
二者之間明顯的區別是Windows每次第一個發起的setup token包中請求的長度都是255(應該是它能處理的最大長度),而Mac OSX則是用8, 2,9這類小的長度進行試探,這無可厚非,或許Windows更喜歡採用一次性到位的策略吧。比較了USB的整個交互過程沒發現其餘不一樣。token
又想了想,仍是看看編譯出來的map文件或許能有新的發現。果真:it
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)io
根據經驗頗有可能USBD_StrDesc越界致使把DMA_InitStructure改寫了,看了下USBD_StrDesc被填充的值的末尾數據:編譯
00530046不正是被改寫的值嗎?看了下大小是66,在代碼中check了下發現USBD_StrDesc被定義爲50字節的數組,難怪會出現問題,將USBD_StrDesc大小改大問題果真被解決了。變量
但一開始爲何在Mac OSX上是正常的呢?是由於DMA_InitStructure是放在第一次setup token裏面實現的,因爲Mac OSX第一次發起的請求的長度是2,沒有觸發覆寫的邊界條件,幸運的避開了這個問題。配置