由于公司产品更新换代需要,接触RT1052已经快两年了,总想开公众号总结些心得体会分享给大家,但由于时间问题,申请的公众号落了一层灰。如今初心复燃,下面由浅入深整理些相关内容以方便同入此坑者查漏补缺,有问题可留言交流,一同进步。
1 BooT
提及Boot,首先应该联想到的是FLASH,通常Cortex-M微控制器芯片内部一般都会集成 FLASH(从FLASH分类上来看应该属于Parallel NOR FLASH),你的应用程序代码都是保存在FLASH里,每次上电CPU会自动从FLASH里获取应用程序代码并执行,这个行为就是Boot。
2 BootROM
BootROM其实是芯片在出厂前固化在ROM里的一段Bootloader 程序。这个Bootloader程序可以帮助你完成FLASH里的应用程序的更新,而不需要使用额外的外部编程/调试器(比如JLink),除了应用程序更新之外,BootROM也可以完成应用程序的启动。
3 Bootloader
Bootloader一般提供UART/SPI/I2C/USB接口与上位机进行通信,与Bootloader配套使用的还有一个上位机软件,当芯片从BootROM启动后,通过这个上位机软件与BootROM建立连接,然后可以将你的应用程序代码(bin/s19/hex格式)下载进芯片FLASH。
4 Boot Mode
当芯片既有ROM也有FLASH的时候,便会出现Boot位置选择问题,标准术语称为 Boot Mode。芯片上电CPU到底是先从FLASH启动还是先从ROM启动?关于这个问题,各芯片厂商的解决方案不一样。
5 内部SRAM启动
SRAM存在于任何一款MCU中,它除了可以保存应用程序数据变量外,当然也可以存放应用程序代码以供CPU执行。但是SRAM是易失性存储器,存放的数据断电会丢失,所以从SRAM启动跟从FLASH/ROM启动性质不一样。
从FLASH/ROM启动属于一级启动,不依赖除于BootMode选择之外的条件;而从SRAM启动属于二级启动,其需要借助裸芯片本身之外的外力引导一下才能完成。
外力引导的两种方式:
一是借助于外部调试器,直接将应用程序下载进SRAM并将PC指向应用程序开始执行,其实这就是所谓的在SRAM调试;
二是借助于事先存储在FLASH/ROM中的Bootloader程序,Bootloader会将存放在FLASH(或其他非易失性存储器,或者从上位机直接接收)中的应用程序先加载到SRAM里然后Jump过去执行。
从内部SRAM启动与从外部SDRAM的主要区别和联系:两者都是易丢失存储器,都无法直接启动;SRAM是挂在系统总线上,SDRAM是挂在SEMC控制器上,而且SDRAM需要Bootloader去初始化。
6 外部存储器
有些MCU并没有内部FLASH,所以会支持外接存储器,常见的外部存储器有QSPINOR/NAND,SD/eMMC,SDRAM,ParallelNOR/NAND,SPI/I2C EEPROM等,MCU内部集成相应的存储器接口控制器,通过接口控制器可以轻松访问这些外部存储器。一个没有内部FLASH的MCU肯定会有ROM(BootROM),因为必须要借助BootROM才能Boot存储在外部存储器的应用程序,所以从外部存储器启动也属于二级启动。
7 熔丝Fuse
Fuse是i.MXRT里一块特殊的存储区域,用于存放全部芯片配置信息,其中有一部分区域分配给Boot,产品定型后为安全性考虑可以用熔丝固化芯片内容。具体可参见手册第5章Fusemap及第41章OCOTP相关内容。eFuse这块特殊存储区域并不在ARM的4G系统地址空间里,需要用特殊的方式去访问(读/写)。
eFUSE本质上就是i.MXRT内嵌的一块OTP(OneTime Programmable)memory,仅可被烧写一次,但可以被多次读取。eFUSEmemory的烧写是按bit进行的,初始状态下所有eFUSEbit 均为0,通过特殊的烧写时序可以将bit从0改成1,一旦某bit被烧写成1后便再也无法被修改。
i.MXRT的eFUSE存储空间总地址空间有1.75KB(地址范围为0x000-0x6F0),但可读写操作的空间只有192bytes(位于0x400-0x6F0区域),分为6个BANK,每个BANK含8个字(1字 = 4字节)。
0x00- 0x2F是eFUSE的bank word索引地址(也叫index地址),其与eFUSE空间地址对应关系是:fuse_address= fuse_index * 0x10 + 0x400。
可读写的eFUSE存储空间除了OTP特性外,还有Lock控制特性,Lock控制是OTPmemory的标配,Lock控制有三层:
第一层是WP,即写保护,用于保护那些不需要被烧写成1的eFUSEbit;
第二层是OP,即覆盖保护,包含WP功能,并且被保护的eFUSE区域对应的shadowregister 也不能被重写;
第三层是RP(WP+OP+RP),即访问保护,被保护的eFUSE区域及其对应的shadowregister均不能被读写。
eFUSEmemory的烧写是通过OCOTP_CTRL模块来实现的,我们当然可以在应用程序中集成OCOTP_CTRL的驱动程序,然后在应用程序中调用OCOTP_CTRL的驱动程序完成eFUSE的烧写,但也可以通过Flashloader配套的blhost.exe上位机工具实现eFUSE的烧写。
8 串行下载模式
在这种模式下,BootROM通过指定的USB或者UART来接收来自Host(恩智浦提供的上位机工具sdphost.exe或者mfgtool)的应用程序数据,并将数据存储在SRAM中执行,这种模式其实就是从SRAM启动,但是如果用这种模式去引导应用程序缺点很明显,每次上电都需要将应用程序重新下载进SRAM,无法做到脱机自动引导,所以显然这种模式的主要目的并不是从SRAM启动应用程序。
其实串行下载模式主要是用来从SRAM中启动Flashloader,Flashloader程序可以用来将你的应用程序下载进i.MXRT支持的所有外部非易失性存储器中,为后续从外部存储器启动做准备。此外串行下载模式还可以用来查看Fuse值。
Host工具sdphost.exe与MfgTool2.exe的作用是与BootROM通信,BootROM支持两种外设USB-HID和UART。其中sdphost.exe可以用LPUART1或USB进行通信,MfgTool2.exe是sdphost.exe的一种图形化封装,功能有所减弱,仅支持USB方式通信。
MfgTool2.exe点击Start按钮后,GUI会使用sdphost.exe与BootROM建立通信,首先用write-file命令将ivt_flashloader.bin文件下载进SRAM(地址是固定的0x20000000),然后使用jump-address命令跳转到Flashloader程序中去执行Stage1(jump-address可以跳转到IVT头的映像处),GUI继续使用blhost.exe与Flashloader建立通信,先用get-property1命令测试连接,然后使用receive-sb-file命令接收boot_image.sb文件。Stage2通过Flashloader加载编程映像进外部存储器。
9 熔丝引导模式
此模式并不是从Fuse里加载应用程序启动的意思,而是根据Fuse里的一些引导配置值来决定从哪个外部存储器引导。Fuse是i.MXRT里一块特殊的存储区域,用于存放全部芯片配置信息,其中有一部分配置信息和引导相关。
在参考手册Fusemap章中,可以看到完整的FuseMap表,其中偏移0x460处的32bit配置数据的bit4是BT_FUSE_SEL,它决定了BootFrom Fuses模式的主要行为,具体表现如下:
BT_FUSE_SEL = 0:所有外部存储器中均没有应用程序,此时熔丝引导模式等同于串下载模式。
BT_FUSE_SEL = 1:有外部存储器中存在有效应用程序,此时BootROM会根据Fuse
中他引导配置信息进一步选择指定的外部存储器(引导设备)去引导。
10 内部引导模式
内部引导模式其实跟熔丝引导模式(BT_FUSE_SEL=1时)很类似,但在此模式下的BT_FUSE_SEL的意义有点不同,具体表现如下:
BT_FUSE_SEL = 0:BootROM根据BOOT_CFG[x:0]引脚和Fuse中引导配置综合决定引导设备,其中BOOT_CFG[x:0]引脚的配置会覆盖Fuse中意义相同的引导配置信息。
BT_FUSE_SEL = 1:BootROM完全根据Fuse中Boot 配置信息选择指定的引导设备引导。
我们可以通过更改BOOT_CFG[x:0]引脚输入状态来切换Boot配置,这部分Boot配置在Fuse里也同样存在,但是使用BOOT_CFG[x:0]来更改Boot配置显然比烧写Fuse更方便快捷(也可以认为BOOT_CFG[x:0]主要用于产品开发过程中,待产品开发结束后,应直接用Fuse来锁定Boot配置)。
11 Flash设备配置块FDCB
FDCB是映像的一个可选组成,目前只用于串行/并行的NOR FLASH,FDCB是从FLASH的起始地址处开始存放的,也是可引导映像最开始部分。FDCB最大4KB,其本身没有统一的与FLASH无关的结构,具体结构根据启动FLASH的接口类型(串行/并行)而定,其一般是用来存储当前连接的FLASH的具体特性参数,BootROM上电会使用通用且可靠的FLASH接口控制器配置(即BootROM中默认参数配置,一般是比较低速的配置)去访问外接FLASH并获取FDCB,然后根据FDCB存储的参数去重新配置FLASH接口控制器再去进一步访问FLASH。
12 映像向量表IVT
映像向量表IVT是ROM从引导设备提供的编程映像的数据组件去执行一次成功的引导读操作时所需要的一个数据结构,IVT处于偏移0x400处,大小固定为32字节。
IVT包含编程映像的入口点,一个指向设备配置数据DCD的指针,其他的指针用在ROM的引导进程中。ROM位于IVT的固定地址由连接到芯片的引导设备地址决定。IVT基址的偏移和每个引导设备类型的初始加载域大小见——解读RM1052的IVT结构详细介绍表。IVT的位置仅是ROM的固定需要。剩下的地址或映像内存映射是灵活的,并且被IVT的内容所决定。
IVT是一个统一的与FLASH无关的结构,IVT中记录了应用程序、DCD、BootData、CSF的位置信息,这些信息对BootROM加载启动至关重要。其在可引导映像中的偏移位置也是固定的(对于XIP FLASH而言偏移是0x1000,对于Non-XIP FLASH而言偏移是0x400)。因为BootROM必须要首先获取IVT才能进一步找到其他数据信息,而IVT本身的位置信息没有在其他地方被标明,所以只能在BootROM里用一个常量来记录。
13 引导数据BootData
BD也是一个统一的与FLASH无关的结构,BD中记录了可引导映像的起始地址与总长度、插件标志等。BD大小固定为16字节,BD信息虽然记录在了IVT中,但其在可引导映像中的偏移位置并不是任意的,BD是紧挨着IVT的,其偏移是0x420。
14 设备配置数据DCD
DCD是包含在应用程序映像中的外设配置信息,ROM使用其来配置片上的各种外设。复位时片上所有外设的寄存器自动置为默认值。在默认设置下所有外设均能被访问,但不足以达至理想的性能,因此需要在访问外设前配置其寄存器。
DCD是映像的一个可选组成部分,目前主要用于SDRAM接口控制器(SEMC)的配置。由于i.MXRT内部SRAM大小通常是够用的,且访问速度也很快,所以SDRAM并不一定要被使能,可引导映像常常不会包含DCD。
例如,在访问SDRAM之前需要设置一些SEMC寄存器。可将优化的寄存器设置放在DCD中,ROM可据此来优化SDRAM的访问性能。
DCD的命令是大端(高字节低地址,低字节高地址)的字节命令。DCD最大字节数是1768字节。
ROM根据IVT表得到DCD的绝对地址。DCD中是结构化的数据,格式以及更详细的信息见——解读RM1052中DCD的相关内容。
15 二进制形式的应用程序Binary
应用程序binary,当然是个必备组成,其在可引导映像中的偏移位置0x2000是固定的。要特别注意,i.MXRT的应用程序只读段(主要指ARM中断向量表)并不可以从任意地址开始链接,必须从选定的存储器地址空间偏移0x2000之后开始链接(如选中ITCM,则必须要链接在0x00002000之后;如选中DTCM,则必须链接在0x20002000之后),因为要预留至少8KB空间给IVT、BD、DCD等数据,这个限制是BootROM自身决定的,务必要注意。
16 命令序列文件CSF
CSF是映像的一个个特性组成部分,主要用于安全启动认证的相关特性配置。设置HAB库会用到CSF,当不使用安全引导时,要将CSF域设置为NULL。
17 KeyBlob
KeyBlob是个特性组成,主要用于安全启动的加密相关特性。
18 编程映像image
编程映像最多由7部分组成,有些是必备,有些是可选,有些是特性。而在实际应用中,主要是必备+特性的组合形成如下三种常用分类:
未标记映像:这是最简单的image类型,由IVT+BD+应用程序组成,主要用于产品开发阶段。
标记映像:这是较复杂的image类型,由IVT+BD+应用程序+CSF组成,一般用于产品发布阶段。
加密映像:这是最复杂的image类型,由IVT+BD+应用程序+CSF+KeyBlob组成,主要用于对安全要求较高的产品中。
从外部串行SPINor Flash启动时,待烧写映像整合映像组成部分的方法:
(1)在编译链接过程中直接把这几个元素和应用代码链接到一块,并将这几个元素指定好链接地址,最后通过IDE的Flashloader下载到SPIFlash里。
(2)通过辅助工具在编译链接好的裸应用代码前面手动的添加一个信息头(头里面包含这几个元素),然后通过单独的下载工具或MCU内部的ROM Bootloader ISP下载进去。
这两种各有优劣势:
前者,比较适合在前期调试的时候使用,这样在IDE里面编辑修改应用代码后做测试的时候可以直接在线下载和调试(比如单步,断点,查看寄存器和内存等),这也是目前大部分人迫切需要的,但是缺点是前期配置过程稍微复杂些且需要对引导过程和外部SPI Flash的特性有一定了解,当然这些配置是一劳永逸的,配置一次即可。
上面这种方式,在IDE环境里通过对工程的配置达到生成并下载调试完整 image的目的,实际上这种方法做下来不只方便了在线下载和调试,好处也不少,一是所有的这几个元素配置信息都以C语言的常量形式体现在应用工程文件里面,会加深我们对Boot的理解程度,这样如果更换外部SPIFlash也可以很方便的更改适配信息,二是这种方式形成的image文件会是通用的image格式(比如.Bin.hex和.S19),能兼容市面上大多数可以直接烧写SPI Flash的量产工具的批量烧写。
后者,则是客户不需要关心其他几个元素的配置只专注用户应用的开发,待开发完毕后通过辅助工具生成最终的Image用于小批测试或者量产,缺点是前期调试的话会比较麻烦,每次修改完重新编译生成image还需要用辅助工具手动添加信息头,然后再通过Bootloader下载进去验证,这种情况workaround只能是前期先在RAM里调试,待成熟了之后再走这个流程。
19 映像加载
BootROM是如何从外部存储器中加载可引导映像进SRAM内存的。以non-XIPimage 加载为例(image链接在ITCM里),下图显示了i.MXRT加载image的四个阶段:
Stage1(加载前):此时可引导映像完全存储在外部Flash中,SRAM中没有任何image数据;
Stage2(初始加载):BootROM首先会从外部Flash读取可引导映像前4KB数据进SRAM临时缓存区(OCRAM:0x20208000-0x20208FFF),我们知道这4KB数据里包含了IVT和BD,BootROM从IVT和BD里获取到可引导映像的目标地址BOOT_DATA_T.start以及总长度BOOT_DATA_T.size,此时便可以开始做进一步加载;
Stage3(内部转移):由于BootROM已经从外部Flash读取了4KB进SRAM临时缓存区,为了避免重复读取,BootROM会把这4KB数据先复制到可引导映像的目标地址ITCM。
Stage4(加载完成):BootROM会接着将剩下的可引导映像(BOOT_DATA_T.size- 4KB)从外部Flash中全部读取出来存到目标区域(ITCM)完成全部加载。
20 Flashloader
Flashloader程序作为工具来说,主要是用来将你的应用程序下载进i.MXRT支持的所有外部非易失性存储器中,为后续从外部存储器启动做准备。Flashloader最核心的就是下载更新应用程序功能。
Flashloader作为程序来说,是一段运行在SRAM中的应用程序,只要能有工具将Flashloader下载进SRAM,并将CPU的PC指针指向Flashloader的程序入口便可启动Flashloader。
21 高精度引导HAB
ROM的高精度引导HAB组件是用来保护可编程内存的代码或数据域被潜在的攻击修改,避免ROM以不正常的方式运行。HAB也阻止获得访问权限的尝试,这一设置不必是可用的。
整合了HAB特性的ROM代码能保证芯片可以探测到硬件安全块可能存在安全威胁或内存重要的域被修改的情况下不进入操作状态。HAB用RSA数字标记加强这一策略。
22 SPI Nor Flash启动流程
当RT105x的片上ROM在检测到启动模式为FlexSPI接口后,会根据Boot Pin的配置信息配置该模式下需要使用的FlexSPI接口管脚的复用模式,并将FlexSPI的时钟配置成默认的低速30MHz,然后会以0x6000_0000为首地址读取前512个字节作为外部Flash的配置信息。
配置信息即Flash Configuration Parameters,包括几线制的SPI Flash,SPI的时钟频率,LUT查找表,DDR/SDR模式以及片选CS管脚的Hold/Setup Time等信息。
用上述配置信息配置FlexSPI模块以满足外部Flash的特性,待配置完毕后,RT1052后期就会以AHB总线读取数据和指令的方式来读取接下来的跟用户Image相关的几个关键信息,即IVT(Image Vector Table),Boot Data和DCD(设备配置数据)。
虽然从外部来看仍然是FlexSPI接口,但是由于LUT查找表读取数据的指令已经配置好,CPU只是通过AHB总线发送读取指令即可触发LUT以操作外部Flash,也就是说在内部对CPU来讲已经屏蔽掉了FlexSPI的底层。
其中IVT需要放在外部Flash的固定偏移地址,对NorFlash来说其需要存储在基地址+4KB的偏移地址,比如0x60000000+4*1024,4096十六进制是0x1000)供ROM读取以便让系统知道用户Image的第一条可执行指令放在了哪里以及BootData和DCD的存放地址。
BootData则保存了完整Image的首地址和整个image所占的空间大小。
DCD则包含了一些配置命令以便在跳到用户程序入口之前供ROM调用配置内部外设以更好的匹配外部IC,一般如果系统外挂了SDRAM的情况则需要配置好DCD。因为有时需要主程序在跑起来之前,外部SDRAM就得处在ready状态,以供CPU把数据或代码拷备到SDRAM里时不会出错。
免责声明:本文内容来源于技术文档及网络,版权归原作者所有。如涉及侵权问题,请与我联系删除。