1、前言
某客戶發現修改代碼后,STM32U59 SPI DMA 發送未產生傳輸完成中斷,但修改的代碼跟 SPI 以及 DMA 毫無關聯。
2、調研
回退代碼修改后問題消失,可以確認硬件正常。檢查 SPI 發送對應的 DMA 句柄的ErrorCode,發現 HAL_DMA_ERROR_DTE(Date Transfer Error)置位。嘗試修改軟件,發現調整下某個全局變量初值,或屏蔽某些變量,都能解決問題。
為屏蔽 RTOS 及應用代碼可能帶來的影響,調整客戶 SPI 和 DMA 初始化代碼位置到緊跟 MCU 復位后配置時鐘,初始化全局變量,并在初始化完成后立即發送一包數據,測試下來問題仍存在,說明問題和后續 RTOS 及應用代碼代碼無關。
為澄清全局變量初始化對 SPI 和 DMA 的影響,在全局變量初始化完成、初始化 SPI和 DMA 前、后,分別檢查 RCC、SPI 和 DMA 寄存器,和正常時對比無差異。
3、分析
客戶使用的是 GPDMA 的 Linked List 模式,此模式下 DMA 傳輸相關的 8 個寄存器不通過軟件直接設置,而是需要軟件把待設定的寄存器參數先放入緩沖區,再將緩沖區地址賦到 DMA 寄存器 CxLBAR(高 16 位)和 CxLLR(低 16 位),使能 DMA 時硬件自動將這些參數加載到 DMA 通道對應的寄存器中。
跟蹤代碼執行,在 DMA 使能前,查看參數緩沖區(地址:0x2001 FFF0)。確認DMA 參數緩沖區中源地址寄存器參數 0x200 e0618、目標地址寄存器參數 0x4001 3020都是正確的;使能 DMA 后,發現 DMA CxDAR 寄存器數據異常 0x1382 932e。
查閱參考手冊,找到其對對緩沖區限制的描述:必須 4 字節對齊,且不能跨 64Kbyte邊界;而用戶的緩沖區地址 0x2001 FFF0(32 字節)剛好跨了 64Kbyte 邊界。鏈接器分配的地址范圍是 0x2001 FFF0 ~ 0x2002 0010,而 GPDMA 實際訪問的數據區間是0x2001 FFF0 ~ 0x2001 FFFF 和 0x20010000 ~ 0x2001000F,把 2001 0000 對應的數據加載到了 DAR 中,隨即引發了 DTE 錯誤。
4、處理
處由于增減全局變量、修改變量初值為零或非零,都會影響最終鏈接結果,故通過設置預編譯選項對所有 DMA 鏈表數據結構變量的地址作出限制,來滿足 4 字節對齊且不跨64K Byte 邊界這個約束條件,再次編譯鏈接后進行測試,SPI DMA 功能恢復正常。
5、小結
對這種看似怪異的問題,需要仔細觀察并記錄整個數據傳輸過程,各個關鍵操作前后相關寄存器的變化來獲取第一手資料,對比正常情況并結合參考手冊尋找具體原因。
-
mcu
+關注
關注
146文章
17148瀏覽量
351186 -
SPI
+關注
關注
17文章
1706瀏覽量
91578 -
中斷
+關注
關注
5文章
898瀏覽量
41495 -
dma
+關注
關注
3文章
561瀏覽量
100584
原文標題:工程師筆記|DMA 不產生傳輸完成中斷
文章出處:【微信號:STM32_STM8_MCU,微信公眾號:STM32單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論