vesperW · 6月20日

MCUboot Overwrite模式升级流程及应用

前面给大家讲述了【MCUboot的几种模式】,今天讲述其中的Overwrite 模式升级流程,以及在FSP中如何配置、如Flash怎样划分、安全校验的方式等应用。

本文以单片机RA6M4 1M Code Flash为例,使用Flat mode(不启用TrustZone)说明Overwrite模式进行升级时的注意事项。

首先回顾一下Overwrite模式升级的流程。

image.png

从代码框架来看,整体划分为三部分,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,即可将该功能添加进来。

image.png

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

image.png

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

image.png

展开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版本的情况下才会拷贝。可根据实际需要选择。

image.png

展开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字节)。

image.png

image.png

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即可。

至此,对于Bootloader的配置已经完成了。

接下来我们需要在hal\_entry.c中增加对函数mcuboot\_quick\_setup()的调用。在e² studio界面下,Project Explorer中找到Developer Assistance找到Call Quick Setup,鼠标左键点选,保持左键按下的状态,拖动到hal\_entry.c文件的hal\_entry()函数定义之前。

image.png

然后在hal\_entry()入口处增加对函数mcuboot\_quick\_setup的调用。

image.png

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

image.png

.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

image.png

Python命令中包含e² studio中的Placeholder,针对某个具体的Project,在执行的时候会解析为Workspace下的Project路径以及Project名称。

通过环境变量将Application Project关联起来

打开Application Project的属性界面,在C/C++ Build → Build Variables下添加.bld文件。

image.png

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

image.png

注意,此时Public Key for Sign依然位于Bootloader Project所在路径,该配置只是引入该文件的地址,使得在Application Project中调用Python脚本对Image进行签名操作时找到该Public Key。

另外,Image文件的版本信息可以通过添加Environment variable实现,配置方式如下:

image.png

最终生成的版本信息会以4字节添加到Header中。

为保证每次Environment variables有变化或者Bootloader生成的***.bld发生改变时,Application Project都可以重新编译,需在Pre-build中增加以下内容:

rm -f ${ProjName}.elf

image.png

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

image.png

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

image.png

开始的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中添加相关部分。

image.png

增加对于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地址空间范围内。

image.png

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

image.png

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

image.png

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

image.png

再次点击resume,则可以观察到代码运行在Primary Slot的Application Project中。

4 升级并验证

由于升级方式是基于应用层面的实现,因此依赖客户的设计。如果需要展示,则建议参考下方链接Application Note中的内容,对应的示例代码包含了遵循XModem协议利用UART传输Image。

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。

image.png

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

image.png

按下Reset按钮image.png,使得Bootloader运行,启动代码升级。

可以看到EK-RA6M4从三颗LED闪烁变为仅有一颗蓝色LED闪烁,表明升级成功。

升级完成后查看Secondary Slot对应的Flash已经擦除,Primary Slot中保存了1.1.0版本的Image文件,如下所示。

image.png

END

作者:瑞萨嵌入式小百科,王瑾
来源:strongerHuang

推荐阅读

欢迎大家点赞留言,更多Arm技术文章动态请关注极术社区嵌入式客栈专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。

推荐阅读
关注数
2878
内容数
246
分享一些在嵌入式应用开发方面的浅见,广交朋友
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息