今天給大家介紹的是改動(dòng)i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能會(huì)造成系統(tǒng)異常。
在群里有一位非常活躍的朋友,前段時(shí)間反映了一個(gè)在i.MXRT1062應(yīng)用程序里動(dòng)態(tài)調(diào)整FlexRAM導(dǎo)致WDOG模塊工作異常的問題。經(jīng)過一番排查,發(fā)現(xiàn)了i.MXRT芯片系統(tǒng)設(shè)計(jì)里的一個(gè)小秘密,這個(gè)秘密警示我們在MCU里應(yīng)盡量遵循謹(jǐn)慎的外設(shè)寄存器賦值法。
這個(gè)寄存器謹(jǐn)慎賦值法是什么?這里先賣個(gè)關(guān)子,文末會(huì)揭秘。今天就將這個(gè)問題解決過程還原一下,希望對大家有所啟發(fā):
一、重配FlexRAM影響WDOG的表象問題
先交待一下問題背景,這個(gè)網(wǎng)友是在i.MXRT1062板子上做的測試,使用的是 SDK_EVK-MIMXRT1060oardsevkmimxrt1060driver_exampleswdogiar 例程(XiP),他對工程啟動(dòng)文件和主函數(shù)改動(dòng)如下:
intmain(void) { wdog_config_tconfig; BOARD_ConfigMPU(); BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); PRINTF(" ********System Start******** "); //使能WDOG模塊,設(shè)置Timeout時(shí)間,不啟用中斷 WDOG_GetDefaultConfig(&config); //Timeout value is(0xF+1)/2=8 sec. config.timeoutValue=0xFU; WDOG_Init(DEMO_WDOG_BASE,&config); PRINTF("---wdog Init done--- "); while(1) { //故意不喂狗,讓W(xué)DOG超時(shí)復(fù)位系統(tǒng) //WDOG_Refresh(DEMO_WDOG_BASE); PRINTF(" WDOG has be refreshed!"); /*Delay.*/ delay(SystemCoreClock); } }
他在啟動(dòng)文件 startup_MIMXRT1062.s 里將默認(rèn)128KB ITCM、128KB DTCM、256KB OCRAM的FlexRAM分配調(diào)整成了256KB DTCM、256KB OCRAM(關(guān)于FlexRAM基本知識,這種FlexRAM動(dòng)態(tài)調(diào)整方式僅適用XiP工程。最終運(yùn)行結(jié)果里看,應(yīng)用程序似乎僅運(yùn)行了一次,沒有像預(yù)想得那樣重復(fù)啟動(dòng)執(zhí)行。
如果在 startup_MIMXRT1062.s 里將重配FlexRAM代碼去掉,這個(gè)WDOG例程是可以正常工作的,串口助手里可以看到循環(huán)打印,所以這很容易讓人推斷出FlexRAM重配功能導(dǎo)致WDOG模塊工作異常了。
二、找到程序異常的根本原因
由于這個(gè)WDOG例程并不是完全功能異常,至少首次打印是有的,說明重配FlexRAM并沒有對程序堆棧運(yùn)存等造成實(shí)質(zhì)影響,啟動(dòng)文件里那段重配FlexRAM代碼本身沒有邏輯問題。而打印輸出在WDOG超時(shí)時(shí)間到了之后就沒有了,看起來WDOG模塊應(yīng)該是正常產(chǎn)生了軟復(fù)位。
為了最小化代碼去定位問題,我們將這個(gè)網(wǎng)友WDOG例程主函數(shù)修改如下,去掉WDOG相關(guān)代碼,直接用 NVIC_SystemReset() 代替。運(yùn)行后發(fā)現(xiàn),仍然僅有一次打印,這個(gè)實(shí)驗(yàn)的意義是那段重配FlexRAM代碼會(huì)導(dǎo)致軟復(fù)位后程序沒法再次運(yùn)行,而跟具體WDOG模塊無關(guān)。
intmain(void) { BOARD_ConfigMPU(); BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); PRINTF(" ********System Start******** "); while(1) { NVIC_SystemReset(); } }
我們現(xiàn)在將焦點(diǎn)放回到重配FlexRAM那段匯編代碼本身,代碼很簡單,就是將i.MXRT芯片內(nèi)部的IOMUXC_GPR->GPR17(基址0x400ac044)和IOMUXC_GPR->GPR16(基址0x400ac040)分別整體賦值為0x5555aaaa和0x00000007,單純從寄存器有效功能位定義上來看,這樣操作是沒問題的。
LDR R0,=0x400AC044 LDR R1,=0x5555aaaa STR R1,[R0] LDR R0,=0x400AC040 LDR R1,=0x00000007 STR R1,[R0]
翻看手冊里關(guān)于IOMUXC_GPR->GPR17和IOMUXC_GPR->GPR16寄存器的位定義,發(fā)現(xiàn)IOMUXC_GPR->GPR16寄存器中有很多bit是保留位,并且其中bit21保留位默認(rèn)值是1,與其他保留位默認(rèn)值0不一樣。顯然 IOMUXC_GPR->GPR16 = 0x00000007 這樣的賦值語句會(huì)將其bit21誤清零,并且IOMUXC_GPR寄存器在軟復(fù)位后也不會(huì)改變其值 。
難道問題是由IOMUXC_GPR->GPR16[21]保留位被誤清零導(dǎo)致的?死馬當(dāng)活馬醫(yī)吧,我們修改一下重配FlexRAM代碼如下(兩種方式都行),將IOMUXC_GPR->GPR16[21]保持為默認(rèn)1。
運(yùn)行后發(fā)現(xiàn),異常問題解決了,串口助手里可以看到循環(huán)打印。現(xiàn)在我們知道了IOMUXC_GPR寄存器即使是保留位也不要輕易當(dāng)用戶標(biāo)志位使用,更不要輕易改變其默認(rèn)值,因?yàn)镾oC占用了這些位,具體用途未詳述。由此可以推測IOMUXC_GPR->GPR16[21]位跟系統(tǒng)啟動(dòng)有關(guān),并且其值的設(shè)置是在軟復(fù)位后才生效的。
#ifdef FLEXRAM_CFG_STANDARD LDR R0,=0x400AC044 MOV32 R1,0x5555aaaa STR R1,[R0] LDR R0,=0x400AC040 LDR R1,[R0] ORR R1,R1,#4 STR R1,[R0] #else LDR R0,=0x400AC044 LDR R1,=0x5555aaaa STR R1,[R0] LDR R0,=0x400AC040 LDR R1,=0x00200007 STR R1,[R0] #endif
三、MCU外設(shè)寄存器謹(jǐn)慎賦值法
現(xiàn)在為大家揭秘文章開頭賣的關(guān)子,到底什么是謹(jǐn)慎的外設(shè)寄存器賦值法?
其實(shí)可以從芯片頭文件定義里去學(xué),假設(shè)我們有一個(gè)模塊叫PERIPH,模塊內(nèi)部有一個(gè)名為REG的寄存器,這個(gè)寄存器中有功能位FUNC(單bit或者多bit),芯片頭文件中通常定義如下:
typedefstruct{ __IOuint32_tREG; }PERIPH_Type; #definePERIPH_REG_FUNC_MASK(0x4U)//或者(0xCU) #definePERIPH_REG_FUNC_SHIFT(2U) #definePERIPH_REG_FUNC(x)(((uint32_t)(((uint32_t)(x))< #definePERIPH_BASE(0x400AC000u) #definePERIPH((PERIPH_Type*)PERIPH_BASE)
謹(jǐn)慎寄存器賦值法的核心要義就是每次操作都只涉及一種功能位,并且不要影響其他功能位的值,就像下面代碼所示。切忌出現(xiàn) PERIPH->REG = value1 | value2 | ... 這樣的一次性多個(gè)不同功能位一起賦值的操作。
謹(jǐn)慎寄存器賦值法既可以避免模塊設(shè)計(jì)里不同功能位賦值有先后順序的限制問題,也可以防止誤改某些保留位默認(rèn)值的異常情況發(fā)生。當(dāng)然,這也是有小小代價(jià)的,那就是會(huì)增加了一些代碼長度。
//如果PERIPH->REG[FUNC]是單bit PERIPH->REG|=PERIPH_REG_FUNC_MASK; PERIPH->REG&=~PERIPH_REG_FUNC_MASK; //如果PERIPH->REG[FUNC]是多bit PERIPH->REG=(PERIPH->REG&(~PERIPH_REG_FUNC_MASK))|PERIPH_REG_FUNC(value);
至此,改動(dòng)i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能會(huì)造成系統(tǒng)異常便介紹完了。
本文轉(zhuǎn)載自痞子衡嵌入式公眾號
-
芯片
+關(guān)注
關(guān)注
456文章
51170瀏覽量
427227 -
mcu
+關(guān)注
關(guān)注
146文章
17317瀏覽量
352631 -
寄存器
+關(guān)注
關(guān)注
31文章
5363瀏覽量
121156 -
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3292瀏覽量
57911
原文標(biāo)題:什么是MCU里應(yīng)盡量遵循的寄存器謹(jǐn)慎賦值法?
文章出處:【微信號:玩點(diǎn)嵌入式,微信公眾號:玩點(diǎn)嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論