0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

MCU外設(shè)寄存器謹(jǐn)慎賦值法

Dp1040 ? 來(lái)源:痞子衡嵌入式 ? 2023-12-12 09:14 ? 次閱讀

今天給大家介紹的是改動(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模塊工作異常的問(wèn)題。經(jīng)過(guò)一番排查,發(fā)現(xiàn)了i.MXRT芯片系統(tǒng)設(shè)計(jì)里的一個(gè)小秘密,這個(gè)秘密警示我們?cè)?a target="_blank">MCU里應(yīng)盡量遵循謹(jǐn)慎的外設(shè)寄存器賦值法。

這個(gè)寄存器謹(jǐn)慎賦值法是什么?這里先賣個(gè)關(guān)子,文末會(huì)揭秘。今天就將這個(gè)問(wèn)題解決過(guò)程還原一下,希望對(duì)大家有所啟發(fā):

一、重配FlexRAM影響WDOG的表象問(wèn)題

先交待一下問(wèn)題背景,這個(gè)網(wǎng)友是在i.MXRT1062板子上做的測(cè)試,使用的是 SDK_EVK-MIMXRT1060oardsevkmimxrt1060driver_exampleswdogiar 例程(XiP),他對(duì)工程啟動(dòng)文件和主函數(shù)改動(dòng)如下:

9f3ed286-9886-11ee-8b88-92fbcf53809c.png

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基本知識(shí),這種FlexRAM動(dòng)態(tài)調(diào)整方式僅適用XiP工程。最終運(yùn)行結(jié)果里看,應(yīng)用程序似乎僅運(yùn)行了一次,沒有像預(yù)想得那樣重復(fù)啟動(dòng)執(zhí)行。

9f4d98f2-9886-11ee-8b88-92fbcf53809c.png

如果在 startup_MIMXRT1062.s 里將重配FlexRAM代碼去掉,這個(gè)WDOG例程是可以正常工作的,串口助手里可以看到循環(huán)打印,所以這很容易讓人推斷出FlexRAM重配功能導(dǎo)致WDOG模塊工作異常了。

9f5151b8-9886-11ee-8b88-92fbcf53809c.png

二、找到程序異常的根本原因

由于這個(gè)WDOG例程并不是完全功能異常,至少首次打印是有的,說(shuō)明重配FlexRAM并沒有對(duì)程序堆棧運(yùn)存等造成實(shí)質(zhì)影響,啟動(dòng)文件里那段重配FlexRAM代碼本身沒有邏輯問(wèn)題。而打印輸出在WDOG超時(shí)時(shí)間到了之后就沒有了,看起來(lái)WDOG模塊應(yīng)該是正常產(chǎn)生了軟復(fù)位。

為了最小化代碼去定位問(wèn)題,我們將這個(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模塊無(wú)關(guān)。

intmain(void)
{
BOARD_ConfigMPU();
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();

PRINTF("
********System Start********
");

while(1)
{
NVIC_SystemReset();
}
}

我們現(xiàn)在將焦點(diǎn)放回到重配FlexRAM那段匯編代碼本身,代碼很簡(jiǎn)單,就是將i.MXRT芯片內(nèi)部的IOMUXC_GPR->GPR17(基址0x400ac044)和IOMUXC_GPR->GPR16(基址0x400ac040)分別整體賦值為0x5555aaaa和0x00000007,單純從寄存器有效功能位定義上來(lái)看,這樣操作是沒問(wèn)題的。

  LDR R0,=0x400AC044
  LDR R1,=0x5555aaaa
  STR R1,[R0]
  LDR R0,=0x400AC040
  LDR R1,=0x00000007
  STR R1,[R0]

翻看手冊(cè)里關(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 這樣的賦值語(yǔ)句會(huì)將其bit21誤清零,并且IOMUXC_GPR寄存器在軟復(fù)位后也不會(huì)改變其值 。

9f5c3056-9886-11ee-8b88-92fbcf53809c.png

難道問(wèn)題是由IOMUXC_GPR->GPR16[21]保留位被誤清零導(dǎo)致的?死馬當(dāng)活馬醫(yī)吧,我們修改一下重配FlexRAM代碼如下(兩種方式都行),將IOMUXC_GPR->GPR16[21]保持為默認(rèn)1。

運(yùn)行后發(fā)現(xiàn),異常問(wèn)題解決了,串口助手里可以看到循環(huán)打印?,F(xiàn)在我們知道了IOMUXC_GPR寄存器即使是保留位也不要輕易當(dāng)用戶標(biāo)志位使用,更不要輕易改變其默認(rèn)值,因?yàn)镾oC占用了這些位,具體用途未詳述。由此可以推測(cè)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ì)里不同功能位賦值有先后順序的限制問(wèn)題,也可以防止誤改某些保留位默認(rèn)值的異常情況發(fā)生。當(dāng)然,這也是有小小代價(jià)的,那就是會(huì)增加了一些代碼長(zhǎng)度。

//如果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)載自痞子衡嵌入式公眾號(hào)

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 芯片
    +關(guān)注

    關(guān)注

    450

    文章

    49636

    瀏覽量

    417148
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    146

    文章

    16667

    瀏覽量

    347772
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5253

    瀏覽量

    119201
  • 應(yīng)用程序
    +關(guān)注

    關(guān)注

    37

    文章

    3198

    瀏覽量

    57360

原文標(biāo)題:什么是MCU里應(yīng)盡量遵循的寄存器謹(jǐn)慎賦值法?

文章出處:【微信號(hào):玩點(diǎn)嵌入式,微信公眾號(hào):玩點(diǎn)嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    為什么把main函數(shù)的地址賦值給pc寄存器

    pc寄存器存放的是將要執(zhí)行指令的地址norflash有一個(gè)main函數(shù),SDRAM也有一個(gè)main函數(shù),為什么把main函數(shù)的地址賦值給pc寄存器,就一定是把SDRAM上的main函數(shù)地址賦值
    發(fā)表于 03-06 07:45

    為什么SSI通信接口的數(shù)據(jù)寄存器不能直接賦值?

    在學(xué)SSI的通信接口,試著通過(guò)寄存器直接控制,可是調(diào)試時(shí)發(fā)現(xiàn),對(duì)SSI的數(shù)據(jù)寄存器直接賦值根本就不能賦值,換句話說(shuō)賦值是無(wú)效的。這是什么情況
    發(fā)表于 09-04 06:11

    寄存器,寄存器是什么意思

    寄存器,寄存器是什么意思 寄存器定義  寄存器是中央處理內(nèi)的組成部分。寄存器是有限存貯容量
    發(fā)表于 03-08 14:26 ?2.2w次閱讀

    數(shù)據(jù)寄存器,數(shù)據(jù)寄存器是什么意思

    數(shù)據(jù)寄存器,數(shù)據(jù)寄存器是什么意思 數(shù)據(jù)寄存器數(shù)據(jù)寄存器包括累加AX、基址寄存器BX、計(jì)數(shù)
    發(fā)表于 03-08 14:38 ?1.2w次閱讀

    移位寄存器,移位寄存器是什么意思

    移位寄存器,移位寄存器是什么意思 移位寄存器_
    發(fā)表于 03-08 14:50 ?1.7w次閱讀

    ARM寄存器詳解

    ARM有37個(gè)寄存器,其中31個(gè)通用寄存器,6個(gè)狀態(tài)寄存器。   這里尤其要注意區(qū)別的是ARM自身寄存器和它的一些外設(shè)
    發(fā)表于 07-10 10:04 ?2890次閱讀

    FPGA 調(diào)試 – 外設(shè)寄存器視圖

    作為設(shè)計(jì)者,在 FPGA 設(shè)計(jì)中您可以訪問(wèn)眾多外設(shè)器件的內(nèi)部 寄存器 。一旦將FPGA設(shè)計(jì)下載到目標(biāo)器件中并且代碼已經(jīng)運(yùn)行在相應(yīng)處理上,與這些寄存器進(jìn)行交互的典型方法是通過(guò)嵌入
    發(fā)表于 05-15 11:49 ?3185次閱讀
    FPGA 調(diào)試 – <b class='flag-5'>外設(shè)</b><b class='flag-5'>寄存器</b>視圖

    STM32寄存器外設(shè)驅(qū)動(dòng)x_實(shí)驗(yàn)四

    主要介紹STM32寄存器——外設(shè)驅(qū)動(dòng),圖文詳情,非常合適看
    發(fā)表于 02-22 15:46 ?0次下載

    DSP2407片內(nèi)外設(shè)寄存器定義

    DSP2407片內(nèi)外設(shè)寄存器定義,有需要的下來(lái)看看
    發(fā)表于 05-06 15:29 ?25次下載

    寄存器與移位寄存器

    寄存器與移位寄存器:介紹寄存器原理和移位寄存器的原理及實(shí)現(xiàn)。
    發(fā)表于 05-20 11:47 ?0次下載

    STM32系列MCU,寫寄存器Or利用固件庫(kù)

    嵌入式的編程,往下說(shuō)就是操作MCU寄存器。而固件庫(kù)就是函數(shù)的集合,固件庫(kù)函數(shù)的作用是向下負(fù)責(zé)與寄存器直接打交道,向上提供用戶函數(shù)調(diào)用的接口(API)。相對(duì)于固件庫(kù)的方式,直接寫寄存器
    的頭像 發(fā)表于 08-09 17:22 ?7084次閱讀
    STM32系列<b class='flag-5'>MCU</b>,寫<b class='flag-5'>寄存器</b>Or利用固件庫(kù)

    C語(yǔ)言訪問(wèn)MCU寄存器

    C語(yǔ)言訪問(wèn)MCU寄存器問(wèn)題由來(lái)://下面這行代碼的意思是直接操作0X020C4068這個(gè)寄存器//具體寄存器的作用是通過(guò)手冊(cè)得到的#define CCM_CCGR0 *((volati
    發(fā)表于 10-25 13:21 ?3次下載
    C語(yǔ)言訪問(wèn)<b class='flag-5'>MCU</b><b class='flag-5'>寄存器</b>

    ---GD32 MCU---SYSCFG相關(guān)寄存器無(wú)法寫入

    問(wèn)題描述:客戶在使用中斷時(shí),進(jìn)行中斷的相關(guān)配置,操作SYSCFG的相關(guān)寄存器,始終無(wú)法寫入往SYSCFG的相關(guān)寄存器中寫入非0的數(shù)據(jù)。原因:GD與ST的操作有差異,GD必須保證先打開外設(shè)時(shí)鐘才能
    發(fā)表于 11-18 16:36 ?2次下載
    ---GD32 <b class='flag-5'>MCU</b>---SYSCFG相關(guān)<b class='flag-5'>寄存器</b>無(wú)法寫入

    干貨滿滿:ARM的內(nèi)核寄存器講解

    內(nèi)核寄存器外設(shè)寄存器: 內(nèi)核寄存器外設(shè)寄存器是完全不同的概念。內(nèi)核
    發(fā)表于 04-17 11:47 ?1905次閱讀
    干貨滿滿:ARM的內(nèi)核<b class='flag-5'>寄存器</b>講解

    寄存器分為基本寄存器和什么兩種

    寄存器是計(jì)算機(jī)中用于存儲(chǔ)數(shù)據(jù)的高速存儲(chǔ)單元,它們是CPU內(nèi)部的重要組成部分。寄存器可以分為基本寄存器和擴(kuò)展寄存器兩種類型。 一、基本寄存器
    的頭像 發(fā)表于 07-12 10:31 ?634次閱讀