有人使用STM32H7系列芯片,用到UART做字符串輸出時遇到點小問題。這里一起聊聊該問題,并分析問題原因?!咀ⅲ合旅嫠肐DE乃ARM keil MDK】
事情是這樣的,他基于DMA方式通過UART對外發(fā)送“Hello”字符串,可無意中發(fā)現(xiàn)當(dāng)該字符串以不同的變量形式提供給函數(shù)時結(jié)果卻不一樣。不妨以下面示意的功能代碼為例來看。
上圖中的主要功能就是基于DMA方式通過UART發(fā)送兩次字符串,一個字符串是“Hello,STM32-1!”,另一個是“Hello,STM32-2!”,兩字符串一字之差以示區(qū)別,便于調(diào)試。
可是,按照上面寫法和默認(rèn)編譯條件,測試發(fā)現(xiàn)只有第一個UART發(fā)送函數(shù)有效,第二個UART發(fā)送函數(shù)沒有相應(yīng)輸出。見下面輸出截圖:
那是為什么呢?兩個函數(shù)的實現(xiàn)及變量幾乎一模一樣。如果不使用DMA方式做UART發(fā)送會怎么樣呢?即將UART的發(fā)送改成查詢方式的API函數(shù),見下面截圖:
結(jié)果發(fā)現(xiàn),如果按照上面的寫法,兩行功能代碼的輸出又是正常的,見下面輸出結(jié)果截圖。
看來,問題的出現(xiàn)跟使用DMA有關(guān)。既然問題跟DMA有關(guān),為什么同樣使用基于DMA方式的UART發(fā)送函數(shù),一行可以另一行卻無效呢?這兩行的唯一差別就是在提供發(fā)送字符串的形式上的差異。一行是基于字符串常量提供給函數(shù),一行是基于內(nèi)存變量提供給函數(shù)。
現(xiàn)在的情況是,基于字符串常量提供給函數(shù)的可行,基于內(nèi)存變量提供給函數(shù)的不可行。
這就可能涉及到DMA訪問地址空間的可行性問題,一般來講,每個DMA往往有其可訪問的地址范圍問題,并非無所不達(dá)。具體到STM32H7系列,其通用DMA是沒法訪問TCM區(qū)域的。當(dāng)然,對于內(nèi)核CUP而言,它自然沒有訪問不到的地址空間問題,所以剛才基于查詢式做發(fā)送時兩行函數(shù)功能都正常。
具體到這里,第一個字符串以常量形式提供給UART發(fā)送函數(shù)時,DMA可以訪問到,第二個字符串以內(nèi)存變量形式提供給UART發(fā)送函數(shù)時,DMA則訪問不到。我們可以知道,字符串以常量形式提供給UART發(fā)送函數(shù)時,字符串是存放在FLASH里的。我們可以借助調(diào)試工具找到此時第一個字符串的具體存放地址,顯然是片內(nèi)Flash地址。見下圖:
在STM32H7系列里,通用DMA方式片內(nèi)Flash是沒有問題的。所以解釋了第一行代碼輸出正常。
那么,當(dāng)?shù)诙€字符串以內(nèi)存變量形式提供給UART發(fā)送函數(shù)時,該字符串到底存放在哪里呢?其實,其地址如果沒有刻意通過用戶指定的話,是編譯器根據(jù)當(dāng)前的編譯配置自動安排的。我們借助調(diào)試工具,不難看到第二個字符串變量【TX_Buffer】就是存放下面的地址,即0x20000008開始的一段地址空間:
結(jié)合STM32H7系列手冊相關(guān)地址布局說明,不難得知第二個字符串存放在DTCM區(qū)域,正是通用DMA訪問不到的地址空間。
既然知道了原因,解決起來就就簡單了。我們可以在代碼里直接將字符串存放地址指定到通用DMA可以訪問到的地方,比方AXIRAM,SRAM1/SRAM2/SRAM3任意區(qū)間。
我在下面使用AXI RAM作為默認(rèn)的內(nèi)存空間,也無須通過用戶代碼做地址的指定,只是稍微調(diào)整了ARM MDK IDE的鏈接配置選項,見下面示意圖?!咀ⅲ翰煌腎DE,這個地方的操作會略有差異?!?/p>
然后基于之前的代碼重新編譯、運行,結(jié)果正常,不再有發(fā)不出去的Hello了。
DMA作為CPU的強力幫手,也有鞭長莫及的時候,我們在STM32應(yīng)用中要加以留意。
-
芯片
+關(guān)注
關(guān)注
456文章
51004瀏覽量
425206 -
uart
+關(guān)注
關(guān)注
22文章
1242瀏覽量
101526 -
字符串
+關(guān)注
關(guān)注
1文章
585瀏覽量
20560
原文標(biāo)題:發(fā)不出去的hello問題
文章出處:【微信號:stmcu832,微信公眾號:茶話MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論