痞子衡嵌入式:利用i.MXRT1060,1010上新增的FlexSPI地址重映射(Remap)功能可安全OTA


  你们好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给你们介绍的是i.MXRT部分型号上新增的FlexSPI Remap功能html

  OTA升级设计几乎是每一个量产客户都绕不开的话题,产品发布后免不了要作固件(App)升级以修复bug或者增长新特性。升级App是个麻烦事,由于处理很差,App被破坏了致使启动不了,产品就容易变砖,变了砖即便能救回来,也很是影响用户体验。缓存

  现在基于i.MXRT的客户量产产品愈来愈多,关于OTA安全升级的客户支持也愈来愈多。早期的i.MXRT型号(好比i.MXRT1050/1020/1015)在作基于FlexSPI NOR Flash的OTA升级时,有一个最大痛点即App版本切换不便,所以后面的i.MXRT型号中(好比i.MXRT1064/1060/1010)新增了FlexSPI的Remap功能。今天痞子衡就来介绍一下这个Remap功能是如何用于安全OTA的。安全

1、OTA设计中的痛点

1.1 OTA通常设计

  在讲App版本切换不便痛点前,先给你们简单介绍一下OTA升级设计过程当中处理App版本的通常套路。下面是一个典型的OTA设计中NOR Flash里内容分布,最前面通常是L2 OTA Boot,负责更新升级或者启动App;接下来是主App区,就是真正实现产品功能的App;而后是Temp区,通常用做App更新临时缓冲区;最后是User Data区,存放一些固定不变的图片资源(若是有GUI的话),或者放一些动态保存的系统关键数据。微信

  这里面的Temp区设计是一个关键,若是没有Temp区,在OTA升级时只能原地覆盖主App区(App 1),升级过程当中一旦发生意外(好比断电),系统里就没有完整App可用了,会致使产品变砖。而有了Temp区做缓存,升级过程就会可靠多了,以下图所示,新版本App(App 2)首先会被放在Temp区,仅当App 2完整性校验经过以后,才会从Temp区搬移到主App区,搬移完成以后再擦除Temp区。这样的设计下,即便App 2下载到Temp区或者App 2往App 1搬移时发生意外,系统里都有完整App用于恢复。架构

  上面介绍的处理App版本的典型设计在实际应用中其实不算特别经常使用,由于系统中仅存在一份最新的App,其不支持版本回滚。有时候咱们的新版本App由于一些缘由(好比新增功能有bug)致使运行并不稳定,咱们但愿可以回退到上一个已经运行稳定的旧版本App,系统须要保留两份不一样版本App,因此就有了以下改进的OTA设计NOR Flash内容分布,在主App区(App 2)后面增长一个次App区(App 1)。app

  这时候升级过程稍微复杂一点,以下图所示,多了一步主App区(App 2)搬移到次App区(App 1)的过程(Step 2),这也是版本回滚的关键。不过万事都是有代价的,版本回滚的代价就是增长了OTA升级的时间,以及将Flash中App区从两段划分红三段,致使App最大长度减小了1/3。函数

1.2 App版本切换痛点

  前面介绍了OTA升级设计中管理App版本的两种方法,注意这里的App都是指在FlexSPI NOR Flash中原地执行(XIP)的App,代码连接在芯片内部SRAM或者外扩RAM的App不在讨论范畴(这种Non-XIP属性的App升级不存在版本切换的痛点)。如今聊XIP App版本切换的痛点:测试

  在上面的图中你会发现,新版本App最终都会被搬到主App区(就是紧接着L2 OTA Boot后面的第一个App位置),为何要这么作?这就涉及MCU中App连接相关知识了,由于MCU不一样于MPU,其没有MMU组件,不支持虚拟内存,因此App通常都是固定地址连接,App代码体二进制数据仅放在连接的位置才能够正常执行,将App拷贝到非连接位置是不能运行的。OTA升级中虽然App版本不一样,可是这些App都有一个共同的连接地址,即都是连接在主App区的。flex

  好比下图OTA系统中使用了一块8MB的Flash,在i.MXRT里的系统映射起始地址是0x60000000,L2 OTA Boot和User Data各占1MB,剩余6MB被均分红3段,那么App x/2/1都须要从0x60100000地址开始连接放中断向量表。ui

  可能你会说,咱们也能够设计不一样连接地址的App,这样就不须要将新版本App都往主App区搬移了,是的,原理上能够这么作,但实践中,须要管理不一样连接地址的App,致使OTA升级上位机端操做比较复杂,容易出错(当前待升级的App必须与上一次升级的App连接地址不一样),所以这种方法不推荐。

  因此最大的痛点就是App总要往主App区搬移,既增长了OTA升级时间,也由于搬移操做过多减少了Flash的寿命(总擦写次数是必定的)。

2、详解FlexSPI Remap功能

2.1 FlexSPI NOR系统映射地址

  咱们知道FlexSPI链接的NOR Flash可以实现XIP,最主要的缘由是FlexSPI有对应系统映射空间且NOR Flash自身能够按Byte地址访问,这里的系统映射空间主要用于AHB方式读。CPU去从系统映射空间里读App指令码,FlexSPI模块会自动将AHB总线传来的地址数据请求转换成IPG命令方式去获取NOR Flash里的对应指令内容。更多原理可参看 《在串行NOR Flash XIP调试原理》

  i.MXRT1060中分配给FlexSPI的系统映射空间以下,两个FlexSPI一共分配了496MB。

  i.MXRT1010中分配给FlexSPI的系统映射空间以下,一个FlexSPI分配了504MB。

2.2 FlexSPI Remap功能设计

  i.MXRT中的Remap设计实际上是系统架构层面的,在AHB总线层面作一个地址重定向,并非在FlexSPI模块里实现的,这也是为何Remap相关控制在IOMUXC_GPR寄存器里(设置后Remap马上生效,但这些寄存器不是非易失性的,普通软复位就会置位)。下面是Remap控制寄存器(对于含两个FlexSPI的型号,Remap控制是同时做用的):

Remap功能 对应控制寄存器
i.MXRT106x i.MXRT1010
ADDR_START IOMUXC_GPR_GPR30 IOMUXC_GPR_GPR27
ADDR_END IOMUXC_GPR_GPR31 IOMUXC_GPR_GPR28
ADDR_OFFSET IOMUXC_GPR_GPR32 IOMUXC_GPR_GPR29

  Remap设计提及来其实特别简单,就是地址(addr)落在[ADDR_START, ADDR_END]里的AHB访问,其实际访问到的是addr + ADDR_OFFSET位置处的数据。(注意ADDR_START, ADDR_END, ADDR_OFFSET都是4KB对齐的)

  举例来看,根据ADDR_OFFSET的大小不一样,会有三种状况:第一种是ADDR_OFFSET = ADDR_END - ADDR_START,以下图所示。这也是OTA中最经常使用的状况,ADDR_START可设为主App区起始地址,ADDR_END可设为次App区起始地址。

  第二种是ADDR_OFFSET > ADDR_END - ADDR_START,以下图所示:

  第三种是ADDR_OFFSET < ADDR_END - ADDR_START,以下图所示。不过这种状况在实际应用中并不推荐。

2.3 Remap对擦写Flash的影响

  启用了Remap功能后,不少人会对调用FlexSPI NOR驱动函数去擦写Flash有点疑惑。其实彻底没必要要有这种疑惑,擦写Flash操做走的是FlexSPI IPG命令方式,属于FlexSPI模块内部的事情,彻底不受上层系统Remap功能影响,你能够就当Remap功能彻底不存在,原来怎么作仍是怎么作。

  下面这段测试代码是在MIMXRT1060-EVK上跑的,用ROM API驱动擦写0x60100000地址,擦写操做前加了一段Remap设置干扰,实测下来Remap设置对擦写没有任何影响,复位后去读Flash,操做的仍是原0x60100000地址。其实从测试代码也能看出端倪,API里传入是0x100000,这是Flash绝对偏移地址,跟系统映射不要紧。

flexspi_nor_config_t flashConfig;
serial_nor_config_option_t configOption;
configOption.option0.U = 0xc0000007;

uint32_t programBuffer[64];
for (uint32_t i = 0; i < sizeof(programBuffer); i++)
{
    *((uint8_t *)programBuffer + i) = (uint8_t)(i & 0xFF);
}

IOMUXC_GPR->GPR30 = 0x60100000;
IOMUXC_GPR->GPR31 = 0x60200000;
IOMUXC_GPR->GPR32 = 0x100000;

g_bootloaderTree->flexSpiNorDriver->get_config(0, &flashConfig, &configOption);
g_bootloaderTree->flexSpiNorDriver->init(0, &flashConfig);
g_bootloaderTree->flexSpiNorDriver->erase(0, &flashConfig, 0x100000, 0x100);
g_bootloaderTree->flexSpiNorDriver->program(0, &flashConfig, 0x100000, programBuffer);

3、FlexSPI Remap解决OTA痛点

  有了Remap功能,如今再回到OTA设计,此时咱们只须要两个App分区便可。新版本App(App 2)首先会被放在后Temp区,App 2更新完成且校验经过以后,直接使用Remap功能将App 2重映射到App 1位置,此举既不增长额外物理搬移操做,也同时保留了新旧两份App能够实现版本回滚,并且整个OTA过程仅有一次App擦写耗时也最短,完美解决痛点。

  当Remap功能已被使能,再有新版本App(App 3)更新需求时,其须要被下载到前Temp区,注意Flash擦写操做都是经过IPG方式实现,因此不受Remap功能干扰,仅需关注绝对物理地址偏移,App下载完成,取消Remap功能便可,如此往复。

  至此,i.MXRT部分型号上新增的FlexSPI Remap功能痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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