大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT1xxx里SystemReset不复位的GPR寄存器的小妙用

  我们知道稍大规模的项目代码设计一般都是多人协作完成的,在项目开始阶段的总体设计时,项目组长通常会将代码按功能进行划分,每个功能块代码之间尽量做到耦合度低、互不依赖、互不影响,这样各功能可以独立进行单元测试,项目得以并行开发,后期通过事先定义好的接口/协议进行功能块集成即可。

  但上述方法在嵌入式软件项目里有时候会遇到功能块集成后互相干扰的问题,因为嵌入式项目很多时候并不是纯软件设计,也会跟片内外设资源打交道,而片内外设属于硬件范畴,硬件模块的工作是有前后状态依赖的(这点在片内时钟的配置上体现得尤其明显),出了问题传统方法是具体分析具体解决,来一个就解决一个,但任何代码的改动或者后期新特性的增加都可能会带来新的潜在干扰问题。

  那么对于上述困境,有没有一个一劳永逸的解决方法?其实是有的!那就是每个功能块在设计时都不要依赖芯片初始状态,按照进入时先清理系统环境,然后做功能设计,退出时做一下系统恢复。这种方法虽然保险,但是会引入集成后项目整体运行低效的问题。今天痞子衡要在具体项目实战中介绍一种利用i.MXRT芯片内System Reset后不复位的GPR寄存器来解决属性上互斥的功能代码块集成互相干扰问题的方法。

一、SBL项目中的痛点

  恩智浦MCU SE团队近期一直在加班加点赶一个大项目,这个项目是为客户产品OTA需求而生的。我们知道在线升级是每个智能产品都不可绕开的话题,恩智浦SE团队为了方便客户在基于i.MXRT/LPC的产品上做在线升级,特别推出OTA参考设计,下面是功能架构简图:项目分为SBL + SFW两部分,SBL负责ISP本地更新(UART/USB)以及App切换管理;SFW是一个示例App,其除了客户项目业务功能外,也集成了远程更新功能(WiFi、以太、U盘、SD卡四种升级方式)。

  在SBL代码设计里,主要有两大子功能模块:一个是ISP本地更新 (isp_boot_main),另一个是App切换管理(sbl_boot_main),其中ISP本地更新属于可选项,而App切换管理是必选。

  SBL的主流程是上电启动运行后,先执行ISP本地更新功能块,在超时时间内,如果有收到来自Host的ISP命令,则进入ISP命令处理,此后除非执行ISP复位命令或者有板级复位,否则不会退出ISP;

  如果在超时时间内没有收到ISP命令,则转到App切换管理功能块。在验证App时,如果发现Flash里有合法App,则跳转过去执行;如果没有发现合法的App,会重新返回ISP本地更新(此时是无限超时)。大概主逻辑代码如下:

#define COMPONENT_MCU_ISP
#define ISP_TIMEOUT (5) // in seconds int main(void)
{
#if (defined(COMPONENT_MCU_ISP))
// 先尝试isp本地更新(有5s超时)
bool isInfiniteIsp = false;
isp_boot_main(isInfiniteIsp);
#endif // 无本地升级则进入app跳转处理
sbl_boot_main();
} #if (defined(COMPONENT_MCU_ISP))
void isp_boot_main(bool isInfiniteIsp)
{
if (isInfiniteIsp || ISP_TIMEOUT)
{
// isp相关功能外设初始化
isp_boot_init();
// 在5s超时时间内/无限超时去等待isp命令
isp_boot_run(isInfiniteIsp);
}
}
#endif void sbl_boot_main(void)
{
// 判断Flash里是否存在合法的app
if (sbl_boot_go() != 0)
{
#if (defined(COMPONENT_MCU_ISP))
// 无合法app,重入isp本地更新(无限超时)
bool isInfiniteIsp = true;
isp_boot_main(isInfiniteIsp);
#endif
NVIC_SystemReset();
}
else
{
// 有合法app,跳转到app执行
sbl_do_boot();
} while (1);
}

  上述SBL设计里,你会发现ISP本地更新和App切换管理两个功能块在执行上是互斥的,是Flash里的App处理需求将它们联系在了一起。从软件集成角度来说,这两个功能本不该互相影响,但实际上它们之间产生了互相影响,因为各自在设计时没有遵循进入时清理系统、退出时恢复现场的准则,所以 isp_boot_main() 在超时结束后跳到 sbl_boot_main() 对其部分验签功能产生了影响,而 sbl_boot_main() 执行后没找到合法App跳回 isp_boot_main() 时又出现ISP功能不正常的情况,我们需要解决这个问题。

二、寻找i.MXRT中理想的GPR寄存器

  第一小节里描述的问题,可以通过功能块退出时恢复现场来解决,但是每个模块代码量都比较大,使用代码去逐一恢复现场不太容易。痞子衡想到的一个好办法就是调用 NVIC_SystemReset() 函数来简单粗暴地将芯片系统复位,我们所需要做的就是寻找一个区域,能够临时存放标志位,并且这个区域内容不受系统软复位的影响,芯片复位回来之后在SBL里增加对标志位的判断处理,处理结束后再将标志位清掉。

  在寻找这个不受系统软复位影响的区域前,我们先对i.MXRT里面的电源管理架构作个基本了解。下图是i.MXRT1060的电源架构,除了USB和ADC模块特殊供电需求外,芯片一共有四种电源输入。在板级供电设计时,通常VDD_SNVS_IN需要单独一路外部输入(设计上应由电池供电),其他三路电源VDD_HIGH_IN / DCDC_IN / VDD_SOC_IN可共用一路外部输入(芯片POR_B引脚往往连在这个外部输入控制上)。

VDD_HIGH_IN:给芯片内部LDO供电
DCDC_IN:给芯片内部DCDC模块供电
VDD_SOC_IN:给芯片主系统(Core,SoC,Memory)供电 VDD_SNVS_IN:给芯片内部SNVS域相关模块供电

  从芯片系统复位等级上来分,一共有三类复位:第一类是借助Cortex-M7内核SCB模块的AIRCR寄存器中集成的SYSRESETREQ复位的支持、第二类是DCDC重新上电(POR_B复位)、第三类是整体重新上电。依据这三种不同程度的复位,痞子衡整理了i.MXRT上所有可存放标志位的区域受不同复位类型影响情况如下:

模块 \ 复位类型 NVIC_SystemReset() POR_B和DCDC重新上电 整体重新上电
TCM

OCRAM

IOMUXC_GPR

SRC_GPR
保持 复位 复位
IOMUXC_SNVS_GPR

SNVS_LPGPR
保持 保持 复位
Flash, eFuse 保持 保持 保持

  根据上表,我们先排除掉NVM属性的Flash和eFuse,它们不符合临时存放、轻松读写的需求。TCM / OCRAM可用,但需要在SBL工程里做特殊处理,分配一块.noinit区,并且要确定BootROM没有使用这个区域,用起来还是有点麻烦。IOMUXC_GPR / SRC_GPR用起来简单,但它们已被SoC / BootROM占用了,不能随便使用,对芯片产生的影响未知。IOMUXC_SNVS_GPR / SNVS_LPGPR这两个都不错,但后者在使能加密时有时会被用来存放用户密钥。所以 IOMUXC_SNVS_GPR 寄存器才是最佳选择,这也是真正意义上开放给用户自由使用的GPR寄存器。

三、在SBL项目中使用GPR寄存器

  现在我们找到了理想的 IOMUXC_SNVS_GPR 寄存器,那么可在SBL代码中增加两个函数 isp_cleanup_enter()、isp_cleanup_exit(),前者用于触发软复位前标记状态,后者用于软复位后读取标记的状态做相应处理。最终修改后的SBL主逻辑代码如下:

#define CLEANUP_ISP_TO_SBL (0x5A)
#define CLEANUP_SBL_TO_ISP (0xA5) bool isp_cleanup_exit(bool *isInfiniteIsp)
{
uint32_t flag = IOMUXC_SNVS_GPR->GPR0;
switch (flag)
{
// SBL_TO_ISP软复位情况下,进入无限超时isp
case CLEANUP_SBL_TO_ISP:
*isInfiniteIsp = true;
flag = 0x0;
break;
// 第一次上电或ISP_TO_SBL软复位情况下,直接退出isp
case CLEANUP_ISP_TO_SBL:
default:
break;
}
IOMUXC_SNVS_GPR->GPR0 = 0x0;
return flag;
} void isp_cleanup_enter(uint32_t flag)
{
IOMUXC_SNVS_GPR->GPR0 = flag;
NVIC_SystemReset();
} #if (defined(COMPONENT_MCU_ISP))
void isp_boot_main(bool isInfiniteIsp)
{
// 加一级对于Reset不复位flag的判断处理
if (!isp_cleanup_exit(&isInfiniteIsp))
{
if (isInfiniteIsp || ISP_TIMEOUT)
{
isp_boot_init();
isp_boot_run(isInfiniteIsp);
// 标记flag为ISP_TO_SBL,并触发软复位
isp_cleanup_enter(CLEANUP_ISP_TO_SBL);
}
}
}
#endif void sbl_boot_main(void)
{
if (sbl_boot_go() != 0)
{
#if (defined(COMPONENT_MCU_ISP))
// 标记flag为SBL_TO_ISP,并触发软复位
isp_cleanup_enter(CLEANUP_SBL_TO_ISP);
#endif
NVIC_SystemReset();
}
else
{
sbl_do_boot();
} while (1);
}

  至此,i.MXRT1xxx里SystemReset不复位的GPR寄存器的小妙用痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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

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

  1. 痞子衡嵌入式:关于i.MXRT中FlexSPI外设lookupTable里配置Normal read的一个小误区

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT中FlexSPI外设lookupTable里配置Normal read的一个小误区. 关于串行四线NOR Flash,当其作 ...

  2. 痞子衡嵌入式:聊聊系统看门狗WDOG1在i.MXRT1xxx系统启动中的应用及影响

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是系统看门狗WDOG1在i.MXRT1xxx系统启动中的应用及影响. 软件看门狗模块(WDOG)在 MCU 应用里可以说是非常基础的功能模 ...

  3. 痞子衡嵌入式:理解i.MXRT中FlexSPI外设lookupTable里配置访问行列混合寻址Memory的参数值

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT中FlexSPI外设lookupTable里配置访问行列混合寻址Memory的参数值. 关于 FlexSPI 外设的 loo ...

  4. 痞子衡嵌入式:从头开始认识i.MXRT启动头FDCB里的lookupTable

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT启动头FDCB里的lookupTable. 一个MCU内部通常有很多外设模块,这些外设模块是各MCU厂商做差异化产品的本质, ...

  5. 痞子衡嵌入式:系统时钟配置不当会导致i.MXRT1xxx系列下OTFAD加密启动失败

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是系统时钟配置不当会导致i.MXRT1xxx系列下OTFAD加密启动失败问题. 我们知道,i.MXRT1xxx家族早期型号(RT1050/ ...

  6. 痞子衡嵌入式:了解i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择. 关于 i.MXRT 系列 BootROM 中串行 NOR ...

  7. 痞子衡嵌入式:对比i.MXRT与LPC在RTC外设GPREG寄存器使用上的异同

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是对比i.MXRT与LPC在RTC外设GPREG寄存器使用上的异同. 本篇是 <在SBL项目实战中妙用i.MXRT1xxx里Syst ...

  8. 痞子衡嵌入式:i.MXRT1010, 1170型号上不一样的SNVS GPR寄存器读写控制设计

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1010, 1170型号上不一样的SNVS GPR寄存器读写控制设计. 痞子衡之前两篇文章 <在SBL项目实战中妙用i ...

  9. 痞子衡嵌入式:改动i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能会造成系统异常

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是改动i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能会造成系统异常. 痞子衡的嵌入式技术交流群里有一位非常活跃的朋友(网名:文 ...

随机推荐

  1. 浅入Kubernetes(10):控制节点的部署,选择器、亲和性、污点

    目录 标签和nodeSelector 标签选择 亲和性和反亲和性 污点和容忍度 系统默认污点 容忍度 DaemonSet 在前面的学习中,我们学到了 Deployment 部署,以及副本数(Repli ...

  2. IP Networks UVA - 1590

     Alex is administrator of IP networks. His clients have a bunch of individual IP addresses and he de ...

  3. 深入探索Android热修复技术原理读书笔记 —— 热修复技术介绍

    1.1 什么是热修复 对于广大的移动开发者而言,发版更新是最为寻常不过的事了.然而,如果你 发现刚发出去的包有紧急的BUG需要修复,那你就必须需要经过下面这样的流程: 这就是传统的更新流程,步骤十分繁 ...

  4. 多指灵巧手MoveIt!与Gazebo联合仿真框架搭建

    至于为什么叫框架,一是因为灵巧手的3维模型没有按照基本的设计要求画,正常来说,设计机器人机构之前应该设计好机构需要多少个自由度/DOF,每个自由度是旋转/revolute类型还是滑移/prismati ...

  5. Hook android系统调用的实践

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/71037182 一.环境条件 Ubuntukylin 14.04.5 x64bit ...

  6. 基于 RTF specification v1.7 的 RTF 文件解析及 OLE 对象提取(使用 Python 开发)

    0x01 Office RTF 文件介绍 RTF 文件也称富文本格式(Rich Text Format, 一般简称为 RTF),意为多文本格式是由微软公司开发的跨平台文档格式.大多数的文字处理软件都能 ...

  7. Portswigger web security academy:Server-side request forgery (SSRF)

    Portswigger web security academy:Server-side request forgery (SSRF) 目录 Portswigger web security acad ...

  8. NumPy中文文档搬砖(划掉)学习笔记(1)

    原文地址 前言 况下加速Python中的操作运行时.适用于快速数值运算的一个选项是NumPy,它当之无愧地将自己称为使用Python进行科学计算的基本软件包. 当然,很少有人将50微秒(百万分之五十秒 ...

  9. 【Git】5. 远程库(GitHub)相关操作

    之前也提到了,在整个协作的过程中,必不可少的就是远程库了.Github作为一个全球最大的同性交友网站,同样也是一个非常强大的远程库. 现在希望将本地的hello.txt文件也推到github上去,那首 ...

  10. java之I/O流

    I/O流的使用情况多种多样,首先它的数据源就可能是文件.控制台.服务器等,它的单位可能是按字节.按字符.按行等.为了涵盖所有的可能,java类库中创建了大量的类,如此多的类让我们在使用时感觉有点难以选 ...