详解蓝牙空中升级(BLE OTA)原理与步骤《二》

1,357 阅读14分钟

3. DFU升级步骤详解

3.1 安全式蓝牙空中升级步骤

如前所述,Nordic SDK已经提供了DFU例子,下面我们一步一步给大家讲解如何通过Nordic SDK来实现无按键式蓝牙空中升级。欲实现空中升级,设备需要同时下载softdevice,应用程序,BootLoader程序,以及BootLoader settings page。其中BootLoader代码位于目录:SDK根目录\examples\dfu\secure_bootloader,然后在该目录下选择你对应的板子和工程。Application对应的目录:SDK根目录\examples\ble_peripheral\ble_app_buttonless_dfu,而softdevice所在目录:SDK根目录\components\softdevice。

下面我们以nRF52832/PCA10040和S132/SDK16为例阐述无按键式蓝牙空中升级实现步骤,其他芯片/softdevice/SDK原理与之类似,这里就不再赘述。当然,不同芯片不同softdevice不同SDK,他们的实现脚本还是会有一些细微差别,所以强烈建议大家去百度网盘下载跟大家相匹配的脚本,百度网盘里面各个脚本的命名规则请参考3.2节

  1. 安装PC版nrfutil。nrfutil安装有两种方式,一种是直接下载exe文件,一种是以Python的方式进行安装。nrfutil.exe直接下载链接为:github.com/NordicSemic…记得把nrfutil.exe所在目录放在Windows****环境变量中。Python方式安装nrfutil步骤如下所示:
  • 安装Python2.7或者Python3.7,下载地址:www.python.org/downloads/,安装成功后请确保Windows环境变量包含Python目录
  • 通过pip安装最新版的nrfutil,即打开Windows命令行工具CMD,输入如下命令:pip install nrfutil,即可以完成nrfutil的安装。
  • 安装完成后,在Windows命令行工具输入:nrfutil version,如果可以正确显示版本信息,说明安装已经成功

对于Windows用户,nrfutil运行需要几个特殊的DLL库,而这几个库有些Windows机器是没有的,如此,可往:www.microsoft.com/en-us/downl…下载

  1. 通过nrfutil生成公私钥对。
  • 私钥生成命令:nrfutil keys generate priv.pem (priv.pem就是私钥)
  • 公钥生成命令:nrfutil keys display --key pk --format code priv.pem --out_file dfu_public_key.c (dfu_public_key.c就是公钥)
  • 大家务必要保存好私钥priv.pem,以后每次升级新固件时,都会通过这个私钥对它进行签名,一旦priv.pem丢失或者被暴露,DFU将无法进行或者变得不安全
  1. 请确保已按照“Nordic nRF51/nRF52开发环境搭建”把Nordic nRF5 SDK开发环境搭建成功

  2. 生成micro-ecc算法库。由于micro-ecc是第三方算法库,需要用户自己去安装(这个是版权的要求,没办法直接编译放在SDK中)。请先确保电脑已安装了git和GCC编译器,然后直接点击SDK如下目录的build_all脚本,就可以自动完成micro-ecc算法库的安装。为了方便一些开发者评估,我这里在自己电脑上生成了micro-ecc算法库,micro-ecc目录编排结构有两种:SDK14及以后版本是一种目录结构(百度云盘压缩包名称:micro_ecc_new.rar),SDK13和SDK12又是一种目录结构(百度云盘压缩包名称:micro_ecc_old.rar),这两个压缩包只是目录不一样,里面的算法库内容其实是一样的,这两个压缩包大家都可以在前面的百度云盘中找到,以供大家评估使用。大家下载下来后,直接覆盖同名目录即可。注意:百度云盘里面的micro-ecc库仅供大家评估使用,如要商用,请大家按照上面步骤去生成

  1. 编译bootloader代码。将刚才的dfu_public_key.c取代
SDK
根目录\examples\dfu

下的同名文件,然后使用Keil编译如下目录中的工程:

SDK根目录\examples\dfu\secure_bootloader\pca10040_ble\arm5_no_packs,或者nRF5SDK160098a08e2\examples\dfu\secure_bootloader\pca10040_s132_ble\arm5_no_packs

,将生成的hex文件改名为:bootloader.hex(注:本文所有项目都会采用Keil工程来讲解,如果你使用其他IDE**,请选择其对应的工程文件进行编译,不管是Keil还是其他IDE,除了编译时候选择的工程文件不一样,其余都大同小异,大家可以举一反三完成其他IDE****的相应工作**)

  1. 编译application代码。请编译工程:

SDK根目录 \examples\ble_peripheral\ble_app_buttonless_dfu\pca10040\s132\arm5_no_packs,将生成的hex文件改名为:app.hex

  1. 生成BootLoader settings page。Bootloader settings page存储在Flash最后一个page,如前所述,BootLoader settings page有2个版本,他们的生成脚本命令如下所示:
  • 版本2生成命令:

    nrfutil settings generate --family NRF52 --application app.hex --application-version 1 --bootloader-version 1 --bl-settings-version 2 settings.hex
    
  • 版本1生成命令:

    nrfutil settings generate --family NRF52 --application app.hex --application-version 1 --bootloader-version 1 --bl-settings-version 1 settings.hex
    
  1. 烧写固件。将上文生成的3个hex文件和softdevice hex文件merge成一个文件,然后通过nrfjprog或者nRF Connect桌面版进行烧写,相关命令如下所示:
  • 合并hex文件命令:

    mergehex --merge bootloader.hex settings.hex --output bl_temp.hex 
    mergehex --merge bl_temp.hex app.hex s132_nrf52_7.0.1_softdevice.hex --output whole.hex
    
  • 烧写hex文件命令(以nrfjprog为例):

    nrfjprog --eraseall -f NRF52 
    nrfjprog --program whole.hex --verify -f NRF52 
    nrfjprog --reset -f NRF52
    
  1. 通过nrfutil生成新固件对应的zip包:new_app.zip。zip包包含新固件(**新固件广播名改为:**Nordic_New,其余跟老固件一模一样)和init包,zip包一般通过云端下发到手机app,手机app再通过蓝牙下载到设备中。生成zip包的命令如下所示:
nrfutil pkg generate --application app_new.hex --application-version 2 --hw-version 52 --sd-req 0xCB --key-file priv.pem SDK160_app_s132.zip

其中,--application表示新固件hex文件。--hw-version表示板子版本,只要BootLoader里面的hw version和这里的hw version对应起来,大家可以改成任何自己想要的值。--key-file 表示签名用的私钥文件。--sd-req表示老固件运行在哪个版本softdevice上,这个值一定要跟自己的softdevice相匹配,否则无法升级,各个softdevice版本ID信息可以通过命令“nrfutil pkg generate --help”获得,如下为当前所有softdevice ID列表:

  1. 将“new_app.zip”拷贝到手机上。安卓和苹果手机都可以通过微信的‘文件传输助手’拷过去,非常方便。请注意,手机nRF Connect和nRF Toolbox都支持DFU功能,苹果手机拷贝的时候可以随便选择其中一个app。

  2. 通过手机版nRF Connect或者nRF Toolbox进行蓝牙空中升级,这里以nRF Connect为例阐述升级详细步骤,nRF Toolbox与此类似,就不再赘述

    • 第8)步完成后,开发板就可以正常跑起来,并广播为Nordic_Buttonless

    • 连接该设备,使能CCCD(这一步可选),然后选择“DFU”,如下所示:

    • 选择“DFU”后,将跳出一个对话框,让你选择新固件对应的zip包。由于zip包放在了微信下面的download目录下,我们需要通过文件浏览器找到这个zip包,大家可以先用系统自带的文件浏览器打开这个zip包(如果打开失败,那么大家就要去下载一些第三方的文件浏览器了,比如es explorer),相关操作界面如下所示:

    • 一旦zip包打开成功,升级过程开始,界面如下所示:

    • 升级成功后,设备将运行新固件,即广播名字将变成:Nordic_New,如下所示:

如上以nRF52832/S132为例阐述了Nordic SDK实现无按键式签名式蓝牙空中升级的详细步骤,Nordic SDK有多个版本,从SDK13.0.0到现在SDK16.0.0,他们的升级步骤基本上一模一样,大家完全可以参考上述步骤来做。SDK12升级步骤也与上述步骤基本一样,唯一如下地方需要注意一下:

  • 编译application代码的时候,把如下语句注掉,否则会造成BootLoader和application两者的hex文件相冲突

3.2节会按照上述步骤,对一些经典的安全式BLE OTA例子进行测试,并生成可直接运行的脚本,以供大家参考。

3.2 各种安全式蓝牙空中升级例子

3.1节是以升级nRF52832 application为例,详细阐述了安全式BLE OTA步骤。除了升级application,有的人还需要升级softdevice和BootLoader;除了52832,有的人还会用52840/52833/52811/52810/51822等;除了SDK16.0.0,有的人还会用SDK15.3/15.2/14.2/12.3等。为此我选了一些经典组合,将他们DFU用得的所有脚本都做好了,并进行了实际测试,有需要的可以去百度网盘下载。这些脚本在百度网盘的命名规则为:安全模式_固件传输接口_升级哪一部分固件_SDK版本号_芯片型号.rar,比如secure_ble_S132_app_SDK160_nRF52832.rar表示采用安全签名,固件通过BLE传输,BLE使用S132协议栈,升级的时候只升级application而不升级BootLoader和SoftDevice,基于SDK16.0.0和nRF52832。

目前百度网盘上传了如下安全式BLE OTA示例脚本(注:这些脚本都经过我的测试,全都可以直接运行):

  • secure_ble_S132_app_SDK160_nRF52832.rar
  • secure_ble_S140_app_sd_bl_SDK160_nRF52840.rar
  • secure_ble_S132_app_SDK153_nRF52832.rar
  • secure_ble_S132_app_SDK152_nRF52832.rar
  • secure_ble_S132_app_SDK150_nRF52832.rar
  • secure_ble_S140_app_SDK150_nRF52840.rar
  • secure_ble_S132_app_SDK142_nRF52832.rar
  • secure_ble_S132_app_SDK123_nRF52832.rar
  • secure_ble_S130_app_SDK123_nRF51.rar

3.3 通过UART口进行安全式固件升级示例脚本

我们以nRF52810为例来阐述如何通过UART进行安全式固件升级步骤:

  1. 请参考3.1节第1)到第4)步,完成nrfutil安装,mico-ecc算法库生成,以及公私钥生成

  2. 编译bootloader代码。将刚才的dfu_public_key.c取代

SDK
根目录\examples\dfu

下的同名文件,确保sdk_config.h中的NRF_BL_DFU_ENTER_METHOD_BUTTON为1,然后使用Keil编译如下目录中的工程:

SDK根目录\ examples\dfu\secure_bootloader\pca10040e_uart\arm5_no_packs

,将生成的hex文件改名为:bootloader.hex

  1. 编译application代码。3.1节讲述OTA的时候,我们选择的例子是ble_app_buttonless_dfu,因为我们是通过蓝牙给设备发送一条命令,从而让设备进入DFU模式。通过串口升级固件,如何进入DFU模式,取决于你的应用设计,你可以采用通过发送蓝牙命令让其进入DFU模式,也可以通过上电检测按键是否按下以决定是否进入DFU模式。如果想采用ble_app_buttonless_dfu作为application,那么你需要把该工程中的main函数如下语句删掉(这些语句是为蓝牙版BootLoader设计的,我们现在是UART版BootLoader,不支持这些语句):
err_code = ble_dfu_buttonless_async_svci_init();
APP_ERROR_CHECK(err_code);

这里我们选择以上电检测按键的方式来决定是否进入DFU模式,并以ble_app_blinky作为应用例子,请直接编译如下工程:

SDK根目录\examples\ble_peripheral\ble_app_blinky\pca10040e\s112\arm5_no_packs,将生成的hex文件改名为:app.hex

  1. 生成BootLoader settings page并同时烧写老固件,双击“program.bat”即可完成,这个脚本是使用nrfjprog来完成固件烧写的。

  2. 生成新固件zip包并进行UART DFU,双击“dfu.bat”即可完成,这个脚本是使用nrfutil作为UART主机,并将新固件通过电脑COM口传给设备的。请记得一定要修改脚本中的UART对应的电脑COM口,否则升级无法完成。

注:所有bat脚本都可通过右键选择Notepad++打开,然后查看里面包含的具体命令,并按照自己的需求进行修改。如需进一步理解脚本中的命令,请参考3.1节的说明。

上述所有操作步骤已打包并上传到百度网盘,请去网盘下载文件:secure_uart_app_SDK160_nRF52810.rar,这个文件已经过我的测试,大家可以直接使用。

3.4 通过USB口进行安全式固件升级示例脚本

我们以nRF52840为例来讲述如何通过USB进行安全式固件升级,其实通过USB口升级固件步骤与3.3节的操作几乎一模一样,唯一不同的是,选择如下目录的BootLoader工程进行编译:

SDK根目录\ examples\dfu\secure_bootloader\pca10056_usb\arm5_no_packs

通过USB口进行安全式固件升级示例脚本已打包并上传到百度网盘,请去网盘下载文件:

secure_usb_app_SDK160_nRF52840.rar,这个文件已经过我的测试,大家可以直接使用。

3.5 通过USB口进行开放式固件升级示例脚本

我们还是以nRF52840为例来讲述如何通过USB进行开放式固件升级,其升级步骤与3.3节的操作几乎一模一样,唯一不同的是,选择如下目录的BootLoader工程进行编译:

SDK根目录\ examples\dfu\open_bootloader\pca10056_usb\arm5_no_packs

相关脚本已上传百度网盘,请下载:

open_usb_app_SDK160_nRF52840.rar,这个文件已经过我的测试,大家可以直接使用。

3.6 开放式蓝牙空中升级(Legacy DFU)步骤

所谓开放式OTA,是指OTA过程中,不需要检验新固件的签名,也就是说BootLoader代码里面不包含公钥及相关密码算法库,升级的时候,只校验版本信息,版本校验通过,就可以开始升级流程。Nordic SDK目前支持两套开放式OTA方案,一套是SDK15和SDK16提供的,一套是SDK9/SDK10/SDK11提供的。SDK15/16提供的开放式OTA工作原理和流程,与安全式OTA基本上一样,只不过删掉了签名验签部分。SDK9/SDK10/SDK11提供的开放式OTA也叫legacy OTA DFU,它的工作流程与SDK15/16略有不同,下面将以nRF52832/S132为例,阐述如何在SDK11中实现无按键式开放式蓝牙空中升级,详细步骤如下所示:

  1. 编译bootloader代码,请使用Keil编译目录“nRF5_SDK_11.0.0_89a8197\examples\dfu\bootloader\pca10040**dual_bank_ble_s132**\arm5_no_packs”中的工程,将生成的hex文件改名为bootloader.hex

  2. 编译application代码,请编译目录“nRF5_SDK_11.0.0_89a8197\examples\ble_peripheral*ble_app_hrs**\pca10040*s132_with_dfu**\arm5_no_packs”中的工程,将生成的hex文件改名为app.hex

  3. 将softdevice,bootloader和app三个hex文件合成一个文件,命令如下所示:

mergehex --merge s132_nrf52_2.0.1_softdevice.hex app.hex bootloader.hex –output whole.hex
  1. 烧写固件到设备中,大家可以用nRF Connect桌面版烧写,也可以通过nrfjprog烧写,nrfjprog烧写命令如下所示:
nrfjprog.exe --eraseall -f NRF52
nrfjprog --program whole.hex --verify -f NRF52
  1. 另外我们还需要在Flash中写一个application有效标志位,从而上电后程序直接跑到application中去执行,而不是停留在bootloader中不出来,其对应的命令如下所示:
nrfjprog --memwr 0x0007F000 --val 0x01 --verify -f NRF52
  1. 用老版本的nrfutil生成新固件对应的zip包。该zip包除了包含新固件image,还包含一些配置信息。升级时,zip包会通过云端下发到手机端app,手机端app再把zip包传给蓝牙设备以进行固件升级。请使用老版本nrfutil(版本号0.3.0**)来生成该zip****包**,老版本nrfutil跟随nRFgo studio一起安装的,只要你安装了nRFgo studio,老版本nrfutil就会自动安装好,并放在目录“C:\Program Files (x86)\Nordic Semiconductor\nRFgo Studio”中。生成zip包对应的命令如下所示:
nrfutil dfu genpkg --application app_new.hex --application-version 1 SDK110_app_s132.zip
  1. 把上述的‘SDK110_app_s132.zip’拷到手机中,安卓和苹果手机都可以通过微信的‘文件传输助手’拷过去,非常方便。注:手机nRF Connect和nRF Toolbox都支持DFU功能,苹果手机拷贝的时候可以随便选择其中一个app。

  2. 使用nRF Connect或者nRF Toolbox来完成DFU过程。这里以nRF Connect为例来阐述整个升级过程。

  • 成功执行完第5)步后,如果开发板运行正常,那么它将进行广播,广播名字为:Nordic_HRM

  • 连接该设备,并使能CCCD,然后选择“DFU”

  • 选择“DFU”后,将跳出一个对话框,让你选择新固件对应的zip包。由于zip包放在了微信下面的download目录下,我们需要通过文件浏览器找到这个zip包,大家可以先用系统自带的文件浏览器打开这个zip包(如果打开失败,那么大家就要去下载一些第三方的文件浏览器了,比如es explorer),相关操作界面如下所示:

  • 一旦zip包打开成功,升级过程开始,界面如下所示:

  • 升级成功,设备将自动启动,此时你会看到新固件已经在运行,广播名字也变成了:Nordic_HRM_new,如下所示:

目前百度网盘上传了如下开放式BLE OTA示例脚本(注:这些脚本都经过我的测试,全都可以直接运行):

  • open_ble_S132_app_SDK110_nRF52832.rar
  • open_ble_S130_app_SDK110_nRF51.rar

如果你的应用是基于SDK11开发的,并且需要集成DFU功能,请参考上述例子ble_app_hrs来移植DFU功能,主要工作包括两部分:一把BLE_DFU_APP_SUPPORT这个宏包括的所有代码拷到你的工程中,二如果你的设备支持bonding的话,还需把Device manager相关代码也拷到你的工程中,如此即可完成DFU功能的移植。