大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是改动i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能会造成系统异常

  痞子衡的嵌入式技术交流群里有一位非常活跃的朋友(网名:文,痞子衡已经指定他为副群主)近日向痞子衡反映了一个在i.MXRT1062应用程序里动态调整FlexRAM导致WDOG模块工作异常的问题,经过一番排查,痞子衡发现了i.MXRT芯片系统设计里的一个小秘密,这个秘密警示我们在MCU里应尽量遵循谨慎的外设寄存器赋值法,这个寄存器谨慎赋值法是什么,痞子衡先卖个关子,文末会揭秘。痞子衡今天就将这个问题解决过程还原一下,希望对大家有所启发:

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

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

int main(void)
{
wdog_config_t config;
BOARD_ConfigMPU();
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole(); PRINTF("\r\n******** System Start ********\r\n"); // 使能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---\r\n"); while (1)
{
// 故意不喂狗,让WDOG超时复位系统
//WDOG_Refresh(DEMO_WDOG_BASE);
PRINTF(" \r\nWDOG 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("\r\n******** System Start ********\r\n"); 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

三、谨慎的外设寄存器赋值法

  现在痞子衡揭秘文章开头卖的关子,到底什么是谨慎的外设寄存器赋值法。其实可以从芯片头文件定义里去学,假设我们有一个模块叫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寄存器保留位可能会造成系统异常痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

文章会同时发布到我的 博客园主页CSDN主页知乎主页微信公众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:改动i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能会造成系统异常的更多相关文章

  1. 痞子衡嵌入式:IAR在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致(J-Link / CMSIS-DAP)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致. 做Cortex-M内核MCU嵌入式软件开发,可用的集成开发环境( ...

  2. 痞子衡嵌入式:Keil在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致(J-Link/DAPLink)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是Keil在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致. 本篇是 <IAR EWARM复位类型>.<M ...

  3. 痞子衡嵌入式:我入选了2021年度与非网(eefocus)星选创作者Top10

    本周二「与非网」一个美女运营小姐姐加痞子衡微信,告知痞子衡评上了一个奖,让痞子衡把收件地址告诉她,她把证书寄过来. 昨天痞子衡收到了快递,拆开一看,原来是被评上了 与非网 2021 年度创作者,这个证 ...

  4. 痞子衡嵌入式:在SBL项目实战中妙用i.MXRT1xxx里SystemReset不复位的GPR寄存器

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1xxx里SystemReset不复位的GPR寄存器的小妙用. 我们知道稍大规模的项目代码设计一般都是多人协作完成的,在项目 ...

  5. 痞子衡嵌入式:IVT里的不同entry设置可能会造成i.MXRT1xxx系列启动App后发生异常跑飞

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IVT里的不同entry设置可能会造成i.MXRT1xxx系列启动App后发生异常跑飞问题的分析解决经验. 事情缘起恩智浦官方论坛上的一 ...

  6. 痞子衡嵌入式:原来i.MXRT1xxx系列里也暗藏了Product ID寄存器

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1xxx系列里暗藏的Product ID寄存器. MCU 厂商在定义一个产品系列时,通常是会预先规划产品发展路线的(即会有一 ...

  7. 痞子衡嵌入式:嵌入式里堆栈原理及其纯C实现

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式里堆栈原理及其纯C实现. 今天给大家分享的这篇还是2016年之前痞子衡写的技术文档,花了点时间重新编排了一下格式.栈这种结构在嵌入式 ...

  8. 痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT系列ROM中的FlexSPI驱动API实现IAP. 痞子衡的技术交流群里经常有群友提问: i.MXRT中的FlexSPI驱动 ...

  9. 痞子衡嵌入式:了解i.MXRTxxx系列ROM API及其与i.MXRT1xxx系列的差异

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRTxxx系列ROM API设计细节. 痞子衡之前写过两篇文章 <利用i.MXRT1xxx系列ROM提供的FlexSPI ...

随机推荐

  1. 前后端分离中的无痛刷新token机制

    今天我们来说一说前后端分离中的无痛刷新token机制 博主先来分享一波福利,最近挖到的宝藏,刚开始学Java的同学看 https://www.bilibili.com/video/BV1Rx41187 ...

  2. hdu4400 BFS+STL

    题意:        煤矿爆炸,每个煤矿有自己的x,y,d,d是他爆炸后会是d距离内的爆炸,每次输入一个爆炸的煤矿,问你这个煤矿爆炸会有多少个煤矿爆炸. 思路:       爆炸的过程就是搜索的过程, ...

  3. hdu3336 KMP + DP 前缀数组出现的次数

    题意:       给你一个串,问你他的所有前缀子串在本串中的出现次数,注释:abc的前缀子串是 a ab abc; 思路:      还是利用了next数组,先对子串求出next数组,再开一个数组d ...

  4. hdu 5063 不错的小想法题(逆向处理操作)

    题意:       刚开始的时候给你一个序列,长度为n,分别为a[1]=1,a[2]=2,a[3]=3,a[4]=4...a[n]=n,然后有4种操作如下: Type1: O 1 call fun1( ...

  5. DexHunter在Dalvik虚拟机模式下的脱壳原理分析

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78494671 在前面的博客<DexHunter的原理分析和使用说明(一)&g ...

  6. LA3135简单多路归并(优先队列)

    题意:       有N个任务,每个任务都有自己的时间间隔(就是每t秒请求执行一次)和任务id,这n个任务公用一个cpu,每次我们都执行时间靠前的,如果相同时间内有多个任务,就执行任务id小的,要求模 ...

  7. Jenkins反序列化漏洞复现

    Jenkins Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. Jenkins功能包括: 持 ...

  8. drbd虚拟机宕机恢复方法

    问题现象 云南计算节点YN-ec-compute-19因系统盘损坏宕机且操作系统无法恢复,其上本地虚拟机无法疏散且无法迁移 拟采用drbd备份的数据对compute19上的虚拟机进行恢复 恢复方法 1 ...

  9. restful 与 webapi 详解

    restful 什么是API API全称Aplication Programming Itererface即应用程序编程接口, 我们在开发应用程序时经常用到.API作为接口,用来"连接&qu ...

  10. MzzTxx——团队贡献分分配方案

    项目 内容 这个作业属于哪个课程 2021春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 团队贡献分分配规则制定 我在这个课程的目标是 进一步提升工程化开发能力,积累团队协作经验,熟悉全栈 ...