打开主菜单

谷雨文档中心 β

NRF52832DK-DFU固件升级教程

Erjin讨论 | 贡献2020年1月7日 (二) 16:48的版本 存储空间布局(Memory layout)

DFU是Device Firmware Update的缩写,翻译成中文是设备固件升级。设备固件升级是现在电子设备开发过程中不可规避的问题。下面将以谷雨物联的NRF52832DK评估板为硬件基础,详细介绍DFU的流程。

目录

1 Bootloader 与 DFU 模型

在Nordic提供的SDK中,bootloader 与DFU是其中的一部分。开发者可以在安装的SDK目录中找到。当然开发者也可以在它们的基础上,开发编译自己的bootloader。

一个基本的bootloader在运行后,将会启动指定空间的用户程序。当然可以在几个不同的用户程序间切换,或者在启动用户程序之前对设备进行初始化。但bootloader最重要的功能就是DFU。它主要有以下几个特性:

  • 更新application,SoftDevice和bootloader
  • 认证更新
  • 降级预防
  • 硬件兼容性验证
  • 多种传输方式:(BLE,UART,USBD)
  • 支持application 携带或不带SoftDevice
  • 支持用独立于SoftDevice的固件替换依赖于SoftDevice的固件
  • 支持使用依赖于SoftDevice的固件替换独立于SoftDevice的固件

注:开发者可以查看Nordic的官方原文文档说明。Bootloader and DFU modules章节。

下面是bootloader功能模块的结构框图:

 
bootloader modules

由上图可以看出它分为nrf_bootloader,nrf_crypto,nrf_dfu和nrf_dfu_transport功能模块。其中nrf_crypto实现安全特性,签名bootloader。在Nordic提供的SDK中,提供Secure Bootloader和Open Bootloader两种类型多种传输方式的bootloader。

注:关于nrf_bootloader,nrf_dfu,nrf_dfu_transport详细说明,可以查看Nordic的nRF5_SDK_15.2.0文档。

2 Bootloader详细说明

在DFU过程中,Bootloader占据作用的位置,这章节将详细说明DFU过程中,Bootloader所做的工用。

Bootloader主要负责的事项:

  • 引导应用程序
  • 激活新固件
  • 进入DFU 模式,激活DFU传输,并交付接收到的新固件
  • 喂狗看门狗定时器

在Nordic提供的SDK中,每个bootloader例子都包含一DFU传输方式。

2.1 Bootloader 设置页信息

这个设置页(settings page)存储在非易失性存储器(flash)中,用于保存bootloader与DFU相关的信息。这个设置页主要包含以下几方面的内容:

  • 当前固件大小,CRC-32校验值
  • 挂起固件大小,CRC-32校验值
  • 固件更新进度
  • 固件激活时度
  • 当前固件版本(应用程序与bootloader)
  • 一些特殊数据

2.2 固件激活(Fireware activation)

固件激活是固件更新最后一步。在启动期间,bootloader将会读取settings page里的相应信息,基于这些信息固件激活会被触发。固件激活涉及到新固件copy,以代替旧固件(如果应用程序是双块区域的,这个将在memory layout会用说明),同时会更改settings page信息,以请允许新固件启动。bootloader 要确保copy过程中断电安全。

2.3 DFU 模式(DFU mode)

在DFU模式,bootloader会打开DFU传输,以便设备接收新的固件。bootloader进入DFU模式,可以通过以下几个条件:

  • 没有有效的应用程序存在
  • SoftDevice与有效的应用程序都存在时,host请求bootloader进行应用程序更新
  • 进入DFU模式可以通过以下几个源触发:
    • Button(NRF_BL_DFU_ENTER_METHOD_BUTON)
    • Pin reset(NRF_BL_DFU_ENTER_METHOD_PINRESET))
    • GPREGRET寄存器设置特定的值(NRF_BL_DFU_ENTER_METHOD_GPREGRET)
    • 应用程序通过向settings page写入请求(NRF_BL_DFU_ENTER_METHOD_BUTTONLESS)

当进入DFU 模式,不活动定时器被启动。当定时器到期时,bootloader就会复位。任何DFU活动都会使不活动定时器重启。不活动定时器超时时间默认是NRF_BL_DFU_INACTIVITY_TIMEOUT_MS。如果SoftDevice激活后,设备进入DFU模式,不活动定时器超时时间被设置为NRF_BL_DFU_CONTINUATION_TIMEOUT_MS。

2.4 启动应用程序(Starting the application)

基于settings page的信息,bootloader可以确定是否有应用程序存在,处在什么位置。在启动应用程序之前,bootloader会检查程序的完整性。当然完整性检查也可以在特定的情况下跳过以减少启动时间(NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2,NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET)。只要以下之一条件发生,bootloader就会进入DFU模式:

  • 没有application安装
  • 完整性检查失败
  • 没有setttings page

2.5 看门狗定时器支持(Watchdog timer support)

bootloader 检测看门狗是否活动并喂它以阻止看门狗复位。

2.6 Bootloader 依赖(Bootloader dependencies)

Bootloader模块除在传输时,不依赖SoftDevice。只有在使用BLE DFU 传输方式才依赖SoftDevice。

Bootloader也支持系统中根本不存SoftDevice的情况。

2.7 烧录bootloader(Programming the bootloader)

在系统启动期间,如果bootloader已经安装,MBR(主引导记录,Master Boot Record)负责启动bootloader。为此MBR必须知道bootloader的开始地址。bootloader开始地址存放到UICR.BOOTLOADERADDR中,UICR.BOOTLOADERADDR被映射在0x10001014(NRF_UICR_BOOTLOADER_START_ADDRESS)。因此,在烧写bootloader之前必须正确的设置UICR.BOOTLOADERADDR的值(这个操作开发者不用担心,bootloader程序已经做了)。

烧写bootloader程序要求以下几个步骤:

  • 擦除设备
  • 烧写SoftDevice(使用nRFgo Studio工具)
  • 编译bootloader
  • 烧写bootloader

2.8 存储空间布局(Memory layout)

当添加bootloader到设备中时,你必须意识到不同的固件组件放到存储器哪里。

下表展示了不同器件与SoftDevice的存储空间分配:

组件 存储空间范围nRF52832(S132 v6.1.x) 存储空间范围nRF52840(S140 v6.1.x) 存储空间范围nRF52810(S112 v6.1.x)
Bootloader setttings 0x0007 F000 - 0x0008 0000 (4kB) 0x000F F000 - 0x0010 0000 (4 kB) 0x0002 F000 - 0x0003 0000 (4 kB)
MBR parameter storage 0x0007 E000 - 0x0007 F000 (4 kB) 0x000F E000 - 0x000F F000 (4 kB) 0x0002 E000 - 0x0002 F000 (4 kB)
Bootloader 0x0007 8000 - 0x0007 E000 (24 kB) 0x000F 8000 - 0x000F E000 (24 kB) 0x0002 8000 - 0x0002 E000 (24 kB)
Application area(incl. free space) 0x0002 6000 - 0x0007 8000 (328 kB) 0x0002 6000 - 0x000F 8000 (840 kB) 0x0001 9000 - 0x0002 8000 (60 kB)
SoftDevice 0x0000 1000 - 0x0002 6000 (148 kB) 0x0000 1000 - 0x0002 6000 (148 kB) 0x0000 1000 - 0x0001 9000 (96 kB)
Master Boot Record(MBR) 0x0000 0000 - 0x0000 1000 (4 kB) 0x0000 0000 - 0x0000 1000 (4 kB) 0x0000 0000 - 0x0000 1000 (4 kB)

下图展现了nRF52系列器件的默认空间分配。nRF52832有512kB flash大小,nRF52840有1024kB flash大小,nRF52810有192kB flash大小。

 
Memory layout for nRF52

3 实验前准备

关与DFU流程(nrf_dfu)与DFU协议(nrf_dfu_transport)这里不在详细说明,有兴趣的开发者可以自行查看Nordic的官方文档,可以在谷雨NRF52832DK评估板的资料中下载Noridc的SDK离线文档(推荐,目前最新为nRF5_SDK_15.2.0_offline_doc)。

接下来的说明与操作都基于DFU的secure bootloader中以ble为传输方式的bootloader。其位于Nordic SDK安装路径下/nRF5_SDK_15.2.0_9412B96/examples/dfu/secure_bootloader/pca_10040_ble。开发者安装不同版本的SDK可能会有所差异。

在secure bootloader目录下有多个bootloader工程,这里我们使用pca10040_ble(S132),而pca_10056_ble是S140,RF52832器件不支持S140的SoftDevice。

3.1 辅助工具安装

SDK12以后,DUF功能对升级文件进行了ECDSA签名加密,防止误升级未授权的程序。而Nordic使用micro-ecc开源软件实现ECDSA。

开发者初次安装SDK时,在SDK中是没有micro-ecc源码的,需要开发者去github上下载。如果开发都没有下载micro_ecc源码,则在编译bootloader时,编译器会报各种错误。主要有两个方面的如下:

错误内容 原因
Fatal Error[Pe035]: #error directive: "Debug public key not valid for production.

Please see https://github.com/NordicSemiconductor/pc-nrfutil/blob/master/README.md to generate it"

没有有效的签名公钥
各种与micro-ecc的头文件:uECC.h等 没有micro-ecc源码
3.1.1 git安装

micro-ecc是外部开源软件,所以在Nordic的SDK中放到的协议栈目录下的external目录下。在external目录下,开发者会发现有一个micro-ecc目录。进入micro-ecc目录后,确定没有相应的源码,只有不同编译平台链接相关文件。

其中build_all.bat脚本文件(Windows),是用于编译micro-ecc源码的。在运行时会检查当前系统中是否安装了git。如果安装了,会进一步检查当前目录下是否有相应的源码,如果没有会用git去github上去下载。build_all.bat文件内容如下:

 1 @ECHO OFF
 2 
 3 :: This script will use git (must be in %PATH%) and arm-none-eabi tools in combination with GNU Make
 4 :: to both fetch and compile all variants of micro-ecc for the nRF5 families
 5 
 6 WHERE >nul 2>nul git
 7 IF %ERRORLEVEL% NEQ 0 (
 8     ECHO "git is not installed. Please install and append to PATH."
 9 )
10 
11 IF NOT EXIST micro-ecc/uECC.c (
12     ECHO "micro-ecc not found! Let's pull it from HEAD."
13     git clone https://github.com/kmackay/micro-ecc.git
14 )
15 
16 make -C nrf51_armgcc/armgcc
17 make -C nrf51_iar/armgcc
18 make -C nrf51_keil/armgcc
19 make -C nrf52hf_armgcc/armgcc
20 make -C nrf52hf_iar/armgcc
21 make -C nrf52hf_keil/armgcc
22 make -C nrf52nf_armgcc/armgcc
23 make -C nrf52nf_iar/armgcc
24 make -C nrf52nf_keil/armgcc

如果开发者的PC上没有安装git,则需要去网络找到git,并进行安装。此处安装过程不作说明。

安装git完成后,双击build_all.bat文件,此时git就会去下载micro-ecc源码。此时目录下多了一个micro-ecc文件夹,发现里面有相应的uECC.h与uECC.c等相关文件。

回到IAR工程,再次编译,发现没有报缺少micro_ecc相关的文件,只报了没有相应的公钥错。

3.1.2 安装nrfutil

为了解决没有公钥的错误,我们需要public key与priavte key一对密钥对,使用ECDSA_P256_SHA256算法对DFU程序进行签名并加密。