大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是改動i.MXRT1xxx裡IOMUXC_GPR寄存器保留位可能會造成系統異常。
痞子衡的嵌入式技術交流群裡有一位非常活躍的朋友(網名:文,痞子衡已經指定他為副群主)近日向痞子衡反映了一個在i.MXRT1062應用程式裡動态調整FlexRAM導緻WDOG子產品工作異常的問題,經過一番排查,痞子衡發現了i.MXRT晶片系統設計裡的一個小秘密,這個秘密警示我們在MCU裡應盡量遵循謹慎的外設寄存器指派法,這個寄存器謹慎指派法是什麼,痞子衡先賣個關子,文末會揭秘。痞子衡今天就将這個問題解決過程還原一下,希望對大家有所啟發:
痞子衡先交待一下問題背景,這個網友是在i.MXRT1062闆子上做的測試,使用的是 \SDK_EVK-MIMXRT1060\boards\evkmimxrt1060\driver_examples\wdog\iar 例程(XiP),他對工程啟動檔案和主函數改動如下:

他在啟動檔案 startup_MIMXRT1062.s 裡将預設128KB ITCM、128KB DTCM、256KB OCRAM的FlexRAM配置設定調整成了256KB DTCM、256KB OCRAM(關于FlexRAM基本知識詳見痞子衡舊文 《百變星君FlexRAM》),這種FlexRAM動态調整方式僅适用XiP工程。最終運作結果裡看,應用程式似乎僅運作了一次,沒有像預想得那樣重複啟動執行。
如果在 startup_MIMXRT1062.s 裡将重配FlexRAM代碼去掉,這個WDOG例程是可以正常工作的,序列槽助手裡可以看到循環列印,是以這很容易讓人推斷出FlexRAM重配功能導緻WDOG子產品工作異常了。
由于這個WDOG例程并不是完全功能異常,至少首次列印是有的,說明重配FlexRAM并沒有對程式堆棧運存等造成實質影響,啟動檔案裡那段重配FlexRAM代碼本身沒有邏輯問題。而列印輸出在WDOG逾時時間到了之後就沒有了,看起來WDOG子產品應該是正常産生了軟複位。為了最小化代碼去定位問題,痞子衡将這個網友WDOG例程主函數修改如下,去掉WDOG相關代碼,直接用 NVIC_SystemReset() 代替。運作後發現,仍然僅有一次列印,這個實驗的意義是那段重配FlexRAM代碼會導緻軟複位後程式沒法再次運作,而跟具體WDOG子產品無關。
我們現在将焦點放回到重配FlexRAM那段彙編代碼本身,代碼很簡單,就是将i.MXRT晶片内部的IOMUXC_GPR->GPR17(基址0x400ac044)和IOMUXC_GPR->GPR16(基址0x400ac040)分别整體指派為0x5555aaaa和0x00000007,單純從寄存器有效功能位定義上來看,這樣操作是沒問題的。
翻看手冊裡關于IOMUXC_GPR->GPR17和IOMUXC_GPR->GPR16寄存器的位定義,發現IOMUXC_GPR->GPR16寄存器中有很多bit是保留位,并且其中bit21保留位預設值是1,與其他保留位預設值0不一樣。顯然 IOMUXC_GPR->GPR16 = 0x00000007 這樣的指派語句會将其bit21誤清零,并且IOMUXC_GPR寄存器在軟複位後也不會改變其值 (參見《SystemReset不複位的GPR寄存器小結》一文)。
難道問題是由IOMUXC_GPR->GPR16[21]保留位被誤清零導緻的?死馬當活馬醫吧,我們修改一下重配FlexRAM代碼如下(兩種方式都行),将IOMUXC_GPR->GPR16[21]保持為預設1。運作後發現,異常問題解決了,序列槽助手裡可以看到循環列印。現在我們知道了IOMUXC_GPR寄存器即使是保留位也不要輕易當使用者标志位使用,更不要輕易改變其預設值,因為SoC占用了這些位,具體用途未詳述。可以推測IOMUXC_GPR->GPR16[21]位跟系統啟動有關,并且其值的設定是在軟複位後才生效的。
現在痞子衡揭秘文章開頭賣的關子,到底什麼是謹慎的外設寄存器指派法。其實可以從晶片頭檔案定義裡去學,假設我們有一個子產品叫PERIPH,子產品内部有一個名為REG的寄存器,這個寄存器中有功能位FUNC(單bit或者多bit),晶片頭檔案中通常定義如下:
謹慎寄存器指派法的核心要義就是每次操作都隻涉及一種功能位,并且不要影響其他功能位的值,就像下面代碼所示。切忌出現 PERIPH->REG = value1 | value2 | ... 這樣的一次性多個不同功能位一起指派的操作。
謹慎寄存器指派法既可以避免子產品設計裡不同功能位指派有先後順序的限制問題,也可以防止誤改某些保留位預設值的異常情況發生。當然這也是有小小代價的,那就是會增加了一些代碼長度。
至此,改動i.MXRT1xxx裡IOMUXC_GPR寄存器保留位可能會造成系統異常痞子衡便介紹完畢了,掌聲在哪裡~~~
文章會同時釋出到我的 部落格園首頁、CSDN首頁、知乎首頁、微信公衆号 平台上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。
最後歡迎關注痞子衡個人微信公衆号【痞子衡嵌入式】,一個專注嵌入式技術的公衆号,跟着痞子衡一起玩轉嵌入式。
衡傑(痞子衡),目前就職于恩智浦MCU系統部門,擔任嵌入式系統應用工程師。
專欄内所有文章的轉載請注明出處:http://www.cnblogs.com/henjay724/
與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]
可以關注痞子衡的Github首頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。
關于專欄文章有任何疑問請直接在部落格下面留言,痞子衡會及時回複免費(劃重點)答疑。
痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。