恩智浦i.MX RT1060/1010上串行NOR Flash冗余程序启动设计

电子说

1.3w人已加入

描述

 

工业产品设计里经常会有冗余程序/备份程序设计的需求,因为在工业环境里要求设备能够持续稳定运行,不能轻易宕机,但现实环境中常常有各种意外发生,其中一个常见的意外就是设备主控MCU程序被破坏。

为了降低程序损坏这种意外带来的影响,一个很典型的做法就是增加MCU程序的份数,第一份被破坏,就启动第二份...,用程序数量的增加来降低启动失败率,这属于概率学手段范畴。

我们知道恩智浦i.MX RT系列MCU内部没有非易失性存储器,它需要搭配外部存储器来工作,可选存储器类型非常多:NOR Flash, NAND Flash, eMMC, SD卡都行。

其中对于NAND型存储器,冗余程序设计是必备的,因为NAND本身允许坏块现象存在,所以不得不做冗余设计。而对于NOR型存储器,冗余设计则不是必需的,偏偏串行NOR Flash是i.MX RT最常用的搭档,那该怎么办?别急,今天痞子衡介绍的就是i.MX RT1010/1060上串行NOR Flash冗余程序设计,恩智浦已经都给你考虑到了。

注:本文所涉及的串行NOR Flash冗余程序设计,不支持早期的i.MX RT1050/1020/1015型号。

一、初识冗余程序启动

在i.MX RT上可以挂载串行NOR Flash去启动程序的外设有两个,分别是FlexSPI和 LPSPI,如下图所示。

FlaSh

注:并不是所有 i.MXRT 型号都支持 LPSPI 外设挂载存储器去启动。

其中连接在FlexSPI 上的 Flash A 属于主启动设备,连接在LPSPI上的Flash B属于备份启动设备(关于备份设备启动详见痞子衡旧文《从Serial(1-bit SPI) EEPROM/NOR恢复启动》)。

用两片NOR Flash去完成冗余程序设计当然是没问题,但也相应增加了硬件成本,而本文今天要讨论得不是这种冗余程序设计,我们要聊的是在一片挂载在FlexSPI上的串行 NOR Flash里做冗余程序设计,就是图中的image 0和image 1。

冗余程序启动流程其实特别简单,上电永远先启动物理地址靠前的image 0,如果 image 0被破坏了,则启动image 1。原则上image 0和image 1应该是完全一样的(链接地址也一样,并且中途不需要搬移这两份image数据,这个是靠芯片里的一个黑科技做到的,下文会细讲),毕竟是冗余设计,不过你要执意放两份不完全一样的image,倒也没问题。

二、实测冗余程序启动

我们知道i.MX RT芯片上电总是先运行厂商固化好的BootROM,所以冗余程序启动设计是做在BootROM代码里的。之前有一篇旧文 《了解i.MXRT1060系列ROM中串行NOR Flash启动初始化流程优化点》中2.1 节其实已经简单地提到了冗余程序设计,其主要借助了芯片系统FlexSPI地址重映射(Remap)功能,这个功能是在恩智浦后期推出的 i.MX RT1060/1010 等型号上才有的,这也是上文所说的黑科技。关于这个黑科技,痞子衡也有旧文《利用i.MXRT1060,1010上新增的FlexSPI地址重映射(Remap)功能可安全OTA》。

有了FlexSPI Remap黑科技存在,我们就可以将同一份image binary放在Flash中两个不同位置,并且不用做擦除编程操作来交换其位置,就可以实现各自的启动执行。如果没有这个黑科技,我们只能老老实实做数据搬移,这会增加擦除次数从而影响Flash使用寿命。

原理搞清楚了,现在我们在板子上实测一下这个功能,看看如何正确地放两份image进Flash,哪些情况会导致image 0启动失败从而去启动image 1。

我们就以恩智浦官方MIMXRT1060-EVK开发板为例,这个板子FlexSPI1上挂了两片 Flash,默认连接的8MB QuadSPI Flash,还有一片64MB HyperFlash(需要做板子改动才能使能):

2.1 使能冗余程序启动

使能冗余程序启动特性很简单,就是将fuse 0x6E0[23:16] - FLEXSPI_NOR_SEC_IMAGE_OFFSET烧录为非0值即可,根据下面定义,第二份image 偏移地址最大可以设到Flash中0x3FC0000(63.75MB)处:

Remap功能的ADDR_START寄存器固定设为Flash 起始映射地址。

fuse 0x6e0[15:13] - xSPI_FLASH_IMAGE_SIZE,App的最大长度,标识了第一份App的结束地址,该值加上ADDR_START后被填入Remap功能的ADDR_END寄存器。

fuse 0x6e0[23:16] - FLEXSPI_NOR_SEC_IMAGE_OFFSET,标识了第二份App的起始地址(在Flash中偏移位置),即填入Remap功能的ADDR_OFFSET寄存器的值。

FlaSh

本次测试,我们就将FLEXSPI_NOR_SEC_IMAGE_OFFSET烧录为0x10,xSPI_FLASH_IMAGE_SIZE保持默认0,即第二份image 偏移地址在Flash 0x400000(4MB)处,最大image长度也是4MB,可借助MCUBootUtility工具完成Fuse烧录:

FlaSh

2.2 下载两份无签名image进Flash

现在开始准备image,我们就直接用SDK_2.10.1_EVK-MIMXRT1060boardsevkmimxrt1060demo_appsled_blinky例程,简单直观。为了便于肉眼分辨效果,我们生成两个稍微不一样的image,闪灯间隔时间一个是200ms(image 0 - iled_blinky_delay200ms.bin),另一个是2s(image 1 - iled_blinky_delay2s.bin):

FlaSh

然后还是借助MCUBootUtility工具,先使用All-In-One操作将image 0下载进Flash,因为是bin文件,所以我们要填入正确的链接起始地址(对于i.MX RT1060就是 0x60000000;对于i.MX RT1010应该是0x60000400,具体查看工程链接文件便知)。

此外我们使用的是完整的可启动镜像文件(包含了全部所需启动头),也可以直接在软件通用编程器界面做下载。

FlaSh

image0下载进Flash后,继续下载image 1,这时候只能在软件通用编程器界面操作。这里主要是设置好下载起始地址,前面我们使能冗余程序启动时在Fuse里设置的偏移地址是0x400000,那么此时下载起始地址就应该是0x400000(对于i.MX RT1060是0x400000;对于i.MX RT1010应该是0x400400)。至此两份image下载就完成了。

FlaSh

2.3 快速验证两份image正确性

现在Flash里有了两份image,我们来做一个快速验证,看看image是不是放得符合冗余程序启动的要求。对于image 0,没什么好说的,芯片启动模式设为2'b10 后断电复位应该可以看到image 0在执行,最重要的是验证image 1是不是合法。

这里开始涉及到芯片冗余程序启动流程核心了,当image 0启动失败后,芯片BootROM不是立刻去执行image 1的,它用了一个取巧的方式,在一个软复位不置位的寄存器里(SRC_GPR10)标记了当前状态,然后调用NVIC_SystemReset()重新进入BootROM执行,第二次BootROM执行时才会去启动image 1。

FlaSh

所以这也给了我们快速验证image 1执行的可能性,我们在板子上挂上J-Link仿真器,然后打开J-Link Commander,直接将SRC_GPR10寄存器改写为0x40000000,再依次执行reset和go命令,这时你应该可以看到image 1正在执行了。

FlaSh

2.4 测试无签名 image 0 损坏条件

痞子衡之前在 《i.MXRT Bootable image格式》一文里介绍过一个可启动image包含哪些组成部分,其中最简单的无签名image应该至少包含FDCB, IVT, BD, App四部分,芯片BootROM也是按序读取这四部分数据完成程序启动的。

FlaSh

现在我们尝试分别破坏这几个组成部分来看看何种程度的image 0损坏能被BootROM识别出从而去启动image 1,下面是测试结果。从测试结果来看,除了Image 0 - App的损坏无法检测外,image 0其余启动头的损坏都可以被BootROM识别到。

FlaSh

2.5 能检测image 0 app损坏的方法

如果不能检测image app部分的损坏,那这个冗余程序启动功能就比较鸡肋了,毕竟app部分的数据才是整个image核心所在。如果要加上app损坏检测,需要使能i.MX RT 签名启动,还是可以借助MCUBootUtility工具完成全部流程,下载两份含签名的image进Flash的过程跟2.2节基本差不多,只是Secure Boot Type里需要选择 "HAB Signed Image Boot",含签名的image 0下载没什么好说的,All-In-One操作全搞定,含签名的image 1数据可以通过在通用编程器界面里将含签名的image 0数据全部读回得到,这个具体操作就不详细展开了。

含签名image 0相比无签名image 0多了HABdata(csf,cert,signature) 数据段,BootROM在跳转image之前会根据HAB data数据对image进行验签,验签通过才做跳转。

FlaSh

此时再做一次破坏实验,结果如下,显然加了签名的image 0其完整性就有保证了,这时的冗余程序启动设计才能发挥出最大效果。

FlaSh

来源:恩智浦MCU加油站(作者: 痞子衡)
 

  审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分