前面介绍了MCUboot的基础知识,您可通过上方链接回顾,本章将着重介绍其中的Overwrite模式,以及在FSP中如何配置、如Flash怎样划分、安全校验的方式等。本文以RA6M4 1M Code Flash产品为例,使用Flat mode(不启用TrustZone)说明Overwrite模式进行升级时的注意事项。
首先回顾一下Overwrite模式升级的流程。

从代码框架来看,整体划分为三部分,Bootloader,Primary Slot(保存了低版本的User Application v1.0)和Secondary Slot(保存了待更新的高版本User Application v2.0)。
初始状态下,芯片中烧录了Bootloader和Primary Slot,代码从Bootloader处启动,跳转至Primary Slot中的User Application v1.0。在User Application v1.0运行过程中,接收来自外部的更高版本Firmware v2.0,并烧写到Secondary Slot中,烧写完成后,执行软件复位Software reset,代码重新从Bootloader开始运行。此时Bootloader判断Secondary Slot中代码的版本(v2.0高于v1.0),检查其完整性等等,校验通过后,将Primary Slot擦除,并将Secondary Slot中的内容拷贝到Primary Slot中。之后跳转至Primary Slot中的新代码v2.0执行。比较升级操作的初始状态和终止状态,发现Primary Slot中运行的代码从低版本的v1.0变为高版本的v2.0。
在e² studio中进行开发时,Bootloader和User Application为相互独立的Project,但位于同一个Workspace中。先Build Bootloader Project,然后Build位于Primary Slot的User Application Project,由于Bootloader规定了对于整个存储空间的划分,同时包含了对User Application Image进行签名/验签所用的密钥,因此Application Project会依据Bootloader build输出的Bootloader Data File代替原有的Linker Script File(链接脚本文件)进行link,并利用Bootloader包含的密钥进行Image映像文件的处理。
1 新建Bootloader并配置MCUboot参数
由于Bootloader是整个系统的关键,因此我们第一步创建Bootloader Project并配置一些关键选项如Flash Layout和加密算法等。
对于Bootloader Project,可以在e² studio中新建并命名。在FSP的Stack选项卡下,点击New Stack → Bootloader → MCUboot,即可将该功能添加进来。

添加MCUboot之后,由于它依赖一些底层驱动,如Flash,Crypto等,因此会在初始界面提示错误,按照提示信息逐个修复即可,此处不详细展开。

将所有的错误修正后,配置MCUboot的关键属性。

展开Common选项下的General属性,对于几个可配置的关键选项,说明如下:
-
升级模式Upgrade Mode,可以从Overwrite、Swap和Direct XIP中选择,此次选择Overwrite Only。该选项是决定Bootloader大小的关键性因素,Overwrite模式最小,Swap模式最大。
-
Validate Primary Image,建议设定为Enabled,除非资源非常紧张,开启这部分功能带来的代码量增加不过几十字节而已。
-
Downgrade Prevention(Overwrite Only),假如设定为Disabled,则每次Secondary Slot中有新的Image,都会拷贝到Primary Slot中(安全校验通过的前提下)。假如设定为Enabled,则Bootloader会检查Secondary Slot中存储的Image版本,高于Primary Slot中Image版本的情况下才会拷贝。可根据实际需要选择。

展开Common选项下的Signing and Encryption Options属性,对于几个可配置的关键选项,说明如下:
-
签名类型Signature Type,规定了对于Application Image进行签名所用的方式,可从None,ECDSA P-256,RSA 2048,RSA 3072四项中任选其一。假如使能签名,则代码量最小的是ECDSA P-256
-
Encryption Scheme,根据对于Application Image是否加密进行设定。默认是Disabled,假如使能,则可以从ECIES-P256和RSA-OAEP (RSA 2048 only)中任选其一。Encryption Enabled情况下,Bootloader代码量会明显增加
接下来配置Flash Layout
对于Flash Layout来说,由于升级模式已锁定Overwrite,在此基础上决定Bootloader的大小因素就只剩下校验算法的选择了。
由于Bootloader占据从0地址开始的空间,而RA6M4在低地址上的8个block大小均为8KB,因此我们将Bootloader大小设定为64KB,即0x10000。由于高地址上的Block大小为32KB,因此对于1MB code flash的RA6M4来说,可以将剩下的30个(37-8+1)Block等分,Primary Slot和Secondary Slot各占15 Blocks(0x78000字节)。


Bootloader Flash Area Size (Bytes):
设定为0x10000即可
Image 1 Header Size (Bytes):
前面的划分Primary Slot和Secondary Slot包含Header,对于Cortex-M33内核的产品,有中断向量表对齐的要求,因此我们建议将Header size统一设定为0x200,以支持Application的所有中断。
Image 1 Flash Area Size (Bytes):
根据前面的计算结果,填入0x78000 (15个32K block)
由于Scratch Area仅针对Swap模式有效,因此在Overwrite模式下设定为0即可。
接下来我们需要在hal_entry.c中增加对函数mcuboot_quick_setup()的调用。在e² studio界面下,Project Explorer中找到Developer Assistance找到Call Quick Setup,鼠标左键点选,保持左键按下的状态,拖动到hal_entry.c文件的hal_entry()函数定义之前。

然后在hal_entry()入口处增加对函数mcuboot_quick_setup的调用。

Build Project可以顺利完成,提示“0 errors, 0 warnings”。在Debug文件夹下确认包含同名的***.bld文件,用文本编辑器打开,检查内容。

.bld文件是XML格式的,主要包含两部分:
第一部分是symbol,主要包含Bootloader对Flash Layout的设定,FLASH_IMAGE_START值为0x00010200,即位于Primary Slot的Application Project实际Link(链接)地址。FLASH_IMAGE_LENGTH值为0x00077E00,即Primary Slot大小(0x78000)减掉Header Size(0x200)。
第二部分是对Application Image进行签名所用到的Python命令,对于该命令来说,输入是Application Project Build生成的原始Binary(二进制)文件,输出是同名的签名后的文件,后缀是.bin.signed。同时传入的参数还有文件版本,签名所用的密钥等。由于RA6M4搭载了支持TrustZone的Cortex-M33内核,因此文件的结构包含了对TrustZone的支持。对于不启用TrustZone的应用场景,我们仅需关注Python命令的第一部分。
2 将Application Project和Bootloader关联起来
接下来,我们要利用该Bootloader调试目标Application Project,如何才能将Bootloader和Application关联起来呢?就需要借助刚才提到的Bootloader Project Build所生成的***.bld文件。
除了新建Project,也可以将任意一个现有的Project跟Bootloader关联起来,此时,该Project编译的地址为Primary Slot起始地址加上Header大小。
Application Project会利用.bld中的内容替代原始的链接脚本文件(linker script file)。编译的起始地址来自标号FLASH_IMAGE_START,中的值为0x00010200,可以看到,Header大小0x200已经包含进来。
另外,由于需要使用Python对Application Image进行处理,因此需要在本地安装Python以及相关插件的支持。该操作仅需执行一次。
具体的步骤如下,在Project Tree界面下找到ra\mcu-tools\MCUboot\scripts,鼠标点击右键,Command Window,则会在打开命令行界面,并进入scripts文件夹。键入如下命令,安装Python所需的lib。
pip3 install --user -r scripts/requirements.txt

Python安装所需Lib的提示信息
Python命令中包含e² studio中的Placeholder,针对某个具体的Project,在执行的时候会解析为Workspace下的Project路径以及Project名称。
通过环境变量将Application Project关联起来
打开Application Project的属性界面,在C/C++ Build → Build Variables下添加.bld文件。

同时,对Application Project Image进行签名操作所需的公钥放在Bootloader中,因此也需要将该文件链接到Application Project中,具体的实现方式如下:

注意,此时Public Key for Sign依然位于Bootloader Project所在路径,该配置只是引入该文件的地址,使得在Application Project中调用Python脚本对Image进行签名操作时找到该Public Key。
另外,Image文件的版本信息可以通过添加Environment variable实现,配置方式如下:

最终生成的版本信息会以4字节添加到Header中。
为保证每次Environment variables有变化或者Bootloader生成的***.bld发生改变时,Application Project都可以重新编译,需在Pre-build中增加以下内容:

完成了以上的所有基础配置后,可以编译Application Project。在Console界面查看Build Log,可以发现编译完成后,增加了对Image文件的处理。

此时生成的***.bin.signed文件包含了Header,TLV和Trailer等内容,可以被Bootloader识别并运行。利用工具打开该文件,可以发现它不同于原始的Application Image文件:

开始的0x200字节是Header信息,在e² studio中通过Environment variable传入的版本信息1.0.0在0x14地址偏移上。关于其他部分的细节,感兴趣的朋友可自行查阅。
Application Image开始的0x200处,第二个4字节即当前的中断向量表起始地址,可以看到是小端格式的0x00012215,在Primary Slot地址空间(0x00010000~0x87FFF)内。
3 调试Application Project
由于芯片上电后需要从0地址(具体地说是0004h地址处)的中断向量开始运行,因此,调试Application Project时需要下载Bootloader 文件,我们在Application Project的Debug Configuration中添加相关部分。

增加对于Bootloader的加载,类型选项设定为Image and Symbols,这样调试状态下可以跟踪Bootloader中代码运行的状态。
同时,将Application Project对应的***.elf → Load type设定为Symbols only,仅下载标号。由于加载了Application Project对应的symbol,因此我们可以调试时检查代码的运行状态。但实际下载到code flash的内容是经过了Python脚本处理,增加了Header,TLV和Trailer等信息的***.bin.signed文件,因此可以通过Bootloader的安全校验。
按下Debug按钮,启动调试,PC指针会停在Bootloader的Reset向量处,从地址0xa534(低于0x10000)可以判断当前位于Bootloader地址空间范围内。

点击Load Ancillary按钮
,将Application Project Debug文件夹下的***.bin.signed下载到芯片上,注意选择地址为Primary Slot起始地址0x10000。

在memory窗口检查当前Primary Slot中的内容,可以看到Image版本为1.0.0。

点击Resume,可以发现PC指针停在Primary Slot的Application Project Reset向量处,此时PC指针地址0x00012264位于Primary Slot地址空间范围(0x10000~0x87FFF)。如下所示:

再次点击resume,则可以观察到代码运行在Primary Slot的Application Project中。
4 升级并验证
由于升级方式是基于应用层面的实现,因此依赖客户的设计。如果需要展示,则建议参考下方链接Application Note中的内容,对应的示例代码包含了遵循XModem协议利用UART传输Image。
RA6 MCU Advanced Secure Bootloader Design using MCUboot and Code Flash Dualbank Mode:https://www.renesas.com/us/en/document/apn/ra6-mcu-advanced-secure-bootloader-design-using-mcuboot-and-code-flash-dualbank-mode
在调试状态下,可以通过将待更新的Image文件下载到Secondary Slot中,重启即可使得升级生效。
在Application Project上稍作修改,比如原始的Project在EK-RA6M4上使三个LED(红绿蓝)一起闪烁,而我们将代码更新为只有一个LED(蓝色)闪烁。同时,将Image Version从1.0.0更改为1.1.0,重新Build Project,确认Debug文件夹下的.bin.signed重新生成了。
现在将1.1.0版本的Image烧录到Secondary Slot中,点击Load Ancillary,选中***.bin.signed,目标地址选择0x88000。

下载成功后查看Memory中的内容,可以确认Secondary Slot存储了1.1.0版本的Image。

按下Reset按钮
,使得Bootloader运行,启动代码升级。
可以看到EK-RA6M4从三颗LED闪烁变为仅有一颗蓝色LED闪烁,表明升级成功。
升级完成后查看Secondary Slot对应的Flash已经擦除,Primary Slot中保存了1.1.0版本的Image文件,如下所示。
