BLE DFU:Bootloader


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

 

(完)


6 responses to “BLE DFU:Bootloader”

  1. nordic的升级在安全性上做的挺好的,其他家没看到有这个设置

    • 这些安全保障很有必要,只是用的签名算法、protobuf这些东西好占空间,Flash吃不消。

  2. 编译micro-ecc后生成的静态库文件要添加到bootloader工程吗? SDK中的bootloader工程好像不用添加就可以编译通过。不知道这个库文件应该如何使用?

  3. 大神,你好,问一下,我在发送.dat文件里面的数据的时候,由于数据长度大于20,所以我进行了分包发送,但是发现每发一次包,就会返回600603这类的码,这个表示什么意思?

    • 参考这个页面的两张消息时序图(http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.2.0/lib_dfu_transport_ble.html?cp=4_0_0_3_5_2_2)。图中没有60 06 03,但是有个60 06 01,如果是错误码的话,需要对照着代码去解析。固件代码在SDK中,主机的代码可以参考nrfutil的源代码。

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.