Bootloader是DFU的基础设施,DFU的基本流程就是在Bootloader中接收新固件数据并写入Flash,接收完毕后重启跳转并运行新固件。

本文介绍Bootloader的相关内容。

(1)编译micro-ecc

micro-ecc是一个面向嵌入式应用的椭圆曲线签名算法(ECDSA)库,Bootloader的加密模块调用了该库,第一次运行需要先编译micro-ecc的静态库文件。

先安装以下工具,并将程序路径加入系统环境变量。

进入文件夹<sdk>\external\micro-ecc,运行build_all.bat文件,将自动下载micro-ecc的源代码,并生成静态库文件。

使用其他版本的GNU Arm Embedded Toolchain,需要修改<sdk>\components\toolchain\gcc\Makefile.windows

(2)使用公钥

使用nrfutil命令行工具,分别生成私钥和公钥:

nrfutil keys generate private_key.pem

nrfutil keys display 
    --key pk 
    --format code private_key.pem 
    --out_file dfu_public_key.c

SDK中的Bootloader工程使用了一个临时公钥,我们需要将其替换成自己的公钥。

(3)工作流程

在DFU的架构中,Bootloader充当DFU Target,手机APP等充当DFU Controller。Controller发出指令(Request),Target给出响应(Response)。

Bootloader实现了一个BLE Server,其中关键Service为:

Attribute UUID Type Property
Secure DFU Service 0xFE59 Service
DFU Control Point 8EC90001-F315-4F60-9FB8-838830DAEA50 Characteristic Notify, Write
DFU Packet 8EC90002-F315-4F60-9FB8-838830DAEA50 Characteristic Notify, Write no Response

DFU Control Point特征用于接收命令(Write)和返回响应(Notify)。

DFU Packet特征用于接收固件数据,它采用Write without Response属性,以加快接收固件速率。同时使用CRC校验保证数据的可靠性。

DFU开始时,Bootloader先接收init packet,接收完后执行验证,验证通过再接收固件数据,接收完后执行验证,验证通过则将新固件复制到Bank 0,重启运行新固件。

(4)签名校验

生成升级包时使用了私钥,私钥利用固件的Hash值生成一个签名,这个签名保存在Init Packet中。

Bootloader工程中包含公钥,利用公钥和Init Packet中的签名可以获得一个Hash值,当固件数据接收完毕,也可以计算得到一个Hash值。这两个Hash值一致则表明固件合法。

(5)工程代码

打开Bootloader工程:<sdk>\examples\dfu\secure_bootloader\pca10040_ble

在绝大多数情况下,不需要修改Bootloader工程代码。少数时候需要使用CMSIS Configurator,编辑sdk_config.h文件:

查看Bootloader的main函数,发现其内容极其简单,核心代码只有两行:

mian() {
    nrf_bootloader_init();
    nrf_bootloader_app_start();
}

nrf_bootloader_init()用来接收新固件的数据,并写入Flash。该函数中有个死循环,在固件接收完之前,不会往后运行,即使断电重启,仍然回到该函数中运行。

nrf_bootloader_app_start()用来跳转进入应用程序。

(6)烧录

如果使用Keil/IAR开发Bootloader,不可以通过IDE直接下载,需要通过nrfjprog命令行工具来下载,命令为:

nrfjprog --program bootloader.hex

 

(完)

DFU(Device Firmware Update)指对设备进行固件更新,有的地方也叫OTA(Over The Air)。Nordic提供了非常完善的DFU方案,而且操作也很简单。

本文演示执行BLE DFU的过程。

(1)准备工作

平台:Windows,安卓手机

硬件:nRF52开发板(PCA10040)

软件:nrfjprog

SDK:SDK 15.0.0

APP:nRF ConnectTotal Commander

(2)应用场景

实际中可能有三种应用场景:

从Bootloader升级:先对裸片烧录Softdevice和Bootloader,然后在Bootloader中执行DFU升级。

从Application升级:芯片中已有一个应用程序,先跳转进入Bootloader,再执行DFU升级。利用Buttonless服务,无需触发按键,仅通过BLE控制实现自动跳转进入Bootloader。

烧录Application:这不算是一种DFU升级,通常会在工厂量产阶段,采用这种方式。

(3)从Bootloader升级

进入文件夹<sdk>\examples\dfu\secure_dfu_test_images\ble\nrf52832

操作中将要使用到以下文件:

  • softdevice_s132.hex
  • bootloader_secure_ble_debug_without_bonds_s132.hex
  • hrs_application_s132.zip

依次烧录前两个文件,使用下面命令行:

@echo off

nrfjprog -e
nrfjprog --program ./softdevice_s132.hex
nrfjprog --program ./bootloader_secure_ble_debug_without_bonds_s132.hex
nrfjprog --reset

pause

打开nrf connect,应该可以看到一个dfuTest的广播设备:

将hrs_application_s132.zip复制到安卓手机中,记下它的路径,稍后会使用。

连接dfuTest设备,点击右上角的DFU图标,将打开如下界面:

选择第一项:Distribution Packet(ZIP)。

假设手机上已经安装好了Total Commander软件,则能看到下图界面,选择Total Commander:

找到并选择hrs_application_s132.zip,即开始进行DFU:

DFU结束后,可以看到Nordic_HRM设备。

至此就完成了整个DFU工作,本文后面的内容都是基于这个流程做的延伸。

(4)从Application升级

如果用户设备中已经烧录了Application,我们需要从Application跳转进入Bootloader,然后再进行DFU,升级成新的Application。

操作中将要使用到以下文件:

  • sd_s132_bootloader_buttonless_with_setting_page_dfu_secure_ble_debug_without_bonds.hex
  • hrs_application_s132.zip

第一个hex文件包含了softdevice、bootloader和一个application。将它烧录到芯片中:

@echo off

nrfjprog -e
nrfjprog --program ./sd_s132_bootloader_buttonless_with_setting_page_dfu_secure_ble_debug_without_bonds.hex
nrfjprog --reset

pause

打开nrf connect,找到设备Nordic_Buttonless:

连接它,点击右上角的DFU图标,并重复上一节相同的步骤:

  • 选择Distribution Packet(ZIP)
  • 选择刚才从PC复制的hrs_application_s132.zip
  • 执行DFU

考虑整个流程, 我们并没有手动断开Application,然后跳转到Bootloader,这一切都由nrf connect自动完成。

(5)烧录Application

在量产阶段,我们需要将Application直接烧录到设备中。如果尝试依次烧录softdevice、bootloader和application,会发现设备一直跑在bootloader中,而没有进入application。

原因是bootloader会检测application的有效性,包括固件大小和CRC等信息。这些信息称为Bootloader Settings,保存在flash的bootloader_settings段中,如下:

Bootloader只有检测到有效信息,才会进入Application中。DFU过程中会自动生成和写入这些信息,而直接烧录则不会,于是Bootloader认为Flash中没有一个有效的Application,进而不做任何跳转动作。

通过application.hex可以生成bootloader_settings.hex,该hex中包含了全部的Bootloader Settings信息。烧录该hex,Bootloader就可以检测到有效性信息,完成跳转。

找到ble_app_buttonless_dfu_without_bonds_s132_with_setting_page.hex文件,该hex即application.hex与bootloader_settings.hex合并后的文件。

依次烧录softdevice、bootloader以及application_with_setting,使用如下命令:

@echo off

nrfjprog -e
nrfjprog --program ./softdevice_s132.hex
nrfjprog --program ./bootloader_secure_ble_debug_without_bonds_s132.hex
nrfjprog --program ./ble_app_buttonless_dfu_without_bonds_s132_with_setting_page.hex

pause

在nrf connect中,看到Nordic_Buttonless设备,即表示烧录成功。

 

(完)