历史上的今天
返回首页

历史上的今天

今天是:2026年02月01日(星期日)

正在发生

2023年02月01日 | 什么是MCU里应尽量遵循的寄存器谨慎赋值法

2023-02-01 来源:zhihu

今天给大家介绍的是改动i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能会造成系统异常。


在痞子衡的嵌入式技术交流群里有一位非常活跃的朋友,前段时间反映了一个在i.MXRT1062应用程序里动态调整FlexRAM导致WDOG模块工作异常的问题。经过一番排查,发现了i.MXRT芯片系统设计里的一个小秘密,这个秘密警示我们在MCU里应尽量遵循谨慎的外设寄存器赋值法。


这个寄存器谨慎赋值法是什么?这里先卖个关子,文末会揭秘。今天就将这个问题解决过程还原一下,希望对大家有所启发:


一、重配FlexRAM影响WDOG的表象问题

先交待一下问题背景,这个网友是在i.MXRT1062板子上做的测试,使用的是 SDK_EVK-MIMXRT1060boardsevkmimxrt1060driver_exampleswdogiar 例程(XiP),他对工程启动文件和主函数改动如下:

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!


无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。

int main(void)

{

    wdog_config_t config;

    BOARD_ConfigMPU();

    BOARD_InitPins();

    BOARD_BootClockRUN();

    BOARD_InitDebugConsole();


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


    // 使能WDOG模块,设置Timeout时间,不启用中断

    WDOG_GetDefaultConfig(&config);

    // Timeout value is (0xF + 1)/2 = 8 sec.

    config.timeoutValue = 0xFU;

    WDOG_Init(DEMO_WDOG_BASE, &config);

    PRINTF("--- wdog Init done---rn");


    while (1)

    {

        // 故意不喂狗,让WDOG超时复位系统

        //WDOG_Refresh(DEMO_WDOG_BASE);

        PRINTF(" rnWDOG has be refreshed!");


        /* Delay. */

        delay(SystemCoreClock);

    }

}

他在启动文件 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模块无关。


int main(void)

{

    BOARD_ConfigMPU();

    BOARD_InitPins();

    BOARD_BootClockRUN();

    BOARD_InitDebugConsole();


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


    while (1)

    {

        NVIC_SystemReset();

    }

}

我们现在将焦点放回到重配FlexRAM那段汇编代码本身,代码很简单,就是将i.MXRT芯片内部的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]

翻看手册里关于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]位跟系统启动有关,并且其值的设置是在软复位后才生效的。


#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外设寄存器谨慎赋值法

现在为大家揭秘文章开头卖的关子,到底什么是谨慎的外设寄存器赋值法?


其实可以从芯片头文件定义里去学,假设我们有一个模块叫PERIPH,模块内部有一个名为REG的寄存器,这个寄存器中有功能位FUNC(单bit或者多bit),芯片头文件中通常定义如下:


typedef struct {

  __IO uint32_t REG;

} PERIPH_Type;


#define PERIPH_REG_FUNC_MASK  (0x4U) // 或者 (0xCU)

#define PERIPH_REG_FUNC_SHIFT (2U)

#define PERIPH_REG_FUNC(x)    (((uint32_t)(((uint32_t)(x)) << PERIPH_REG_FUNC_SHIFT)) & PERIPH_REG_FUNC_MASK)


#define PERIPH_BASE           (0x400AC000u)

#define PERIPH                ((PERIPH_Type *)PERIPH_BASE)

谨慎寄存器赋值法的核心要义就是每次操作都只涉及一种功能位,并且不要影响其他功能位的值,就像下面代码所示。切忌出现 PERIPH->REG = value1 | value2 | ... 这样的一次性多个不同功能位一起赋值的操作。


谨慎寄存器赋值法既可以避免模块设计里不同功能位赋值有先后顺序的限制问题,也可以防止误改某些保留位默认值的异常情况发生。当然,这也是有小小代价的,那就是会增加了一些代码长度。


// 如果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);

至此,改动i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能会造成系统异常便介绍完毕了。


推荐阅读

史海拾趣

Devar Inc公司的发展小趣事

Devar Inc公司自创立之初,就致力于在增强现实(AR)领域取得突破。经过多年的研发,公司成功推出了世界上首个用于AR的生成式AI神经网络。这项技术允许用户通过简单的文本提示创建3D对象和其他AR资产,极大地简化了AR内容的创作过程。Devar的AR平台结合了神经网络和云解决方案,让用户能够轻松创建并分享AR内容,开启了AR创作的新时代。

China Semiconductor Corp公司的发展小趣事

技术创新的同时,CSC也注重市场拓展和品牌建设。公司积极参与国际交流与合作,与多家国际知名企业建立了战略合作关系。同时,CSC加强了对国内市场的开拓,通过提供优质的产品和服务,赢得了客户的信赖和好评。随着品牌知名度的提升,CSC的产品逐渐在国内外市场上占据了一席之地。

格科微电子(GALAXYCORE)公司的发展小趣事

技术创新的同时,CSC也注重市场拓展和品牌建设。公司积极参与国际交流与合作,与多家国际知名企业建立了战略合作关系。同时,CSC加强了对国内市场的开拓,通过提供优质的产品和服务,赢得了客户的信赖和好评。随着品牌知名度的提升,CSC的产品逐渐在国内外市场上占据了一席之地。

Electron Products Inc公司的发展小趣事

随着产品线的不断丰富和市场竞争的加剧,EPI开始积极拓展市场,寻求更广阔的发展空间。公司制定了国际化战略,通过参加国际展会、建立海外销售渠道等方式,成功将产品打入国际市场。同时,EPI还积极与海外企业合作,共同开发新产品,拓展业务领域。

Baneasa SA公司的发展小趣事

Baneasa SA公司成立之初,便专注于电子元器件的研发与生产。公司凭借创始团队的技术积累和市场洞察力,成功开发出一款高性能的半导体芯片,迅速在行业内崭露头角。这款芯片以其出色的稳定性和可靠性赢得了市场的广泛认可,为Baneasa SA的发展奠定了坚实的基础。

康龙(CONCRAFT)公司的发展小趣事

随着公司实力的不断增强,康龙开始积极拓展国内外市场。公司先后在美国、欧洲等地设立了销售机构,与多家国际知名企业建立了长期稳定的合作关系。同时,康龙还积极参与国际展会和交流活动,提升品牌知名度和影响力。通过不懈的努力,康龙的产品已经成功打入国际市场,并赢得了客户的广泛赞誉。

问答坊 | AI 解惑

Ansoft发布新片本SIwave

SIwave是一个精确的整板级电磁场全波分析工具,它采用三维电磁场全波方法分析整板或整个封装的全波效应。对于真实复杂的PCB板或IC封装,包括多层、任意形状的电源和信号线,SIwave可仿真整个电源和地结构的谐振频率; 为了避免在完成整个设计时产 ...…

查看全部问答>

请教各位高手,关于职业选择的困惑

我是学计算机的,现在主要做的是手机功能测试这一块 虽说比较热门,但是感觉没啥技术含量,而且工资也不高 平时比较闲的话,我就学习C语言,而且基础还不错 其他像数据结构的基础也还可以 我想请教一下,如果做嵌入式开发的话(主要是基于unix ...…

查看全部问答>

用C# 在wince 中 如何发出声音,设置系统时间呢?

用C# 在wince 中 如何发出声音,设置系统时间呢?请高手指教!…

查看全部问答>

PWM

                                 请问STM32101的PWM最高输出频率是多少MHz?…

查看全部问答>

8962的中文显示原理

有没有人能够给我详细的介绍下8962中文显示的原理啊?求助大神,小弟拜谢!!!…

查看全部问答>

求助pic16f877a单片机ht-picc编程中一条语句的示意

ADValue=GetADValue(0);哪位大侠可以帮小弟解释一下其具体含义,感激不尽啊…

查看全部问答>

求证实MTK将下季度发售TD芯片“武松”,展讯的TD叫“Tiger”

本帖最后由 jameswangsynnex 于 2015-3-3 19:58 编辑 “聯發科明年首季將推出雙核心TD-ASCDMA智慧型手機晶片MT6572TD,名稱就為武松(Wu Song),很明顯是用來與展訊的「Tiger」晶片相抗衡. ,由於武松的四大優勢,包括:處理整合和成本優勢、武松為 ...…

查看全部问答>

C2000编译求助

#10099-D  program will not fit into available memory.  placement with alignment/blocking fails for section \".text\" size 0x98a page 0.  Available memory ranges:   不知道有没有人遇到同样的问 ...…

查看全部问答>