nrf52810 DFU OTA学习记录



  • nrf528xx是Nordic的一个低功耗蓝牙(ble)芯片系列,在比它早期的芯片都是用Cortex-M0的内核,而这个系列用的是Cortex-M4,性能(尤其是浮点运算)提升了一大截。该芯片支持Bluetooth5,并且有mesh的SDK,资料丰富,感觉拿来学习ble非常棒。
    DFU OTA,Device Firmware Upgrade Over The Air,即无线固件升级,下面基于官方例程来在自己的app上实现DFU,其中升级包采用ECDSA算法签名,以保证文件源正确。
    下面是学习过程的一些记录:

    一. 环境搭建、跑SKD12例程

    1. 总结了一下,整套流程是这样走的,加上安全认证有些复杂,关键的问题是要实现bootloader

    0_1532189988140_1531818394085.png D:\xiaoan\MC3A\DFU\过程\1531818394085.png)

    1. 直接编译bootloader会出现两个错误:

      ​ 1) 缺少公钥

      ​ 2)缺少uecc.h(缺少ecc库)

    0_1532190042125_1531819474086.png
    0_1532190057311_1531819447259.png

    1. 安装mingw,Minimalist GNU For Windows 是一个编译套件,包括了C/C++ gcc编译工具

      1)下载:https://sourceforge.net/projects/mingw/files/

      2)下载好后到 【C:\MinGW\bin 】目录下将【mingw32-make.exe】 重命名为【make.exe】

      3)在【系统环境变量】 Path中添加:【C:\MinGW\bin】

    0_1532190100161_1531820096530.png

    4)测试:命令行下输入 【make -v】则会出现版本信息,如下:

    0_1532190121516_1531820232453.png

    1. 安装GCC compiler toolchain for ARM,用来为Cortex-M and Cortex-R family 编译程序的交叉编译工具链,结合mingw使用,为了编译micro-ecc

      ​ 1)下载:【https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads】

      ​ 2)安装:没什么说的,打开直接装就行

      ​ 3)用编辑器打开【\nRF5_SDK_12.3.0_d7731ad\components\toolchain\gcc\Makefile.windows】修改GNU_INSTALL_ROOT为刚才安装的路径,我这里是【C:/Program Files (x86)/GNU Tools Arm Embedded/7 2018-q2-update】,后面我们编译mico-ecc时候用的是

    2. 编译micro-ecc

      ​ 1)下载:【https://github.com/kmackay/micro-ecc】

      ​ 2)放到bootloader工程的指定路径:将【micro-ecc.zip】中的【micro-ecc-master】解压到【\nRF5_SDK_12.3.0_d7731ad\external\micro-ecc】目录下并修改文件夹名称为【micro-ecc】

    0_1532190177643_1531821344736.png

    ​ 3)在【\nRF5_SDK_12.3.0_d7731ad\external\micro-ecc\nrf52_keil\armgcc】目录下打开命令行,输入【make】,进行编译,生成【micro_ecc_lib_nrf52.lib】

    0_1532190209606_1531821571914.png

    1. 此时如果在keil中再编译bootloader,则会看到之前报的缺少uecc.h的error没了,下面解决另一个error

    2. 如果没有python环境,则先装好python(一定用2.x,我这里是3.6.3,后面会遇到问题),安装好后在命令行里运行【python --version】会打印版本信息

    3. 安装nrfutil.exe,这是nrf为dfu专门做的工具包,用来生成公钥/密钥和打包在线升级app

      ​ 1)在命令行里输入【pip install nrfutil】就行了,安装好后输入【nrfutil version】 ,会打印版本信息

    0_1532190257597_1531825416636.png

    ​ 2)下面要产生密钥,命令行输入【nrfutil.exe keys generate path\private.key】 这里的path随便找个位置,等下密钥会生成在这里。如果用3.x,会出现报错信息

    ​ 4)命令行输入 【nrfutil keys display --key pk --format code path\private.key --out_file path\public_key.c】生成公钥,将.c文件改名为【dfu_public_key.c】并替换掉【\examples\dfu\bootloader_secure】下的原文件

    1. 重新编译bootloader,终于通过了...

    2. 下一步要使用nrfutil.exe工具生成用于更新的zip文件,该文件要包括app和密钥,把application.hex和private.key放在同一个目录下,在次目录中打开命令行,运行:

      【nrfutil pkg generate --hw-version 52 --application-version 1 --application application.hex --sd-req0x8C --key-file private.key cc_Dfu12.2.zip】

    3. 先烧softdevice,,再烧bootloader,可以扫描到蓝牙【DfuTarg】最后把zip通过手机app更新,重启跑进新的app。

    二. SDK15 S132 boot例程移植到 S112,跑在NRF52810上

    1. S112是基于S132进行优化过的版本,nrf52832Flash大小512k,RAM64k,S132协议栈占用152kB,而S112只占了100kB,nrf52810的Flash大小是192k,RAM大小24k;我们的app有50k+,所以只能用S112
    2. 协议栈更新详细说明在【\components\softdevice\s112\doc\s112_nrf52_6.0.0_migration-document.pdf】里全都有,我们也是根据这个来移植boot
    3. 打开【\examples\dfu\secure_bootloader\pca10040_ble\arm5_no_packs】boot例程
    4. 首先修改工程头文件路径,改成112的

    0_1532190319442_1531963911975.png

    1. 全局宏定义NRF52832_XXAA 改为NRF52810_XXAA,器件类型也修改为NRF52810_XXAA

    0_1532190472674_1531964045156.png

    1. 打开nrf.h,默认NRF52是定义成NRF52832_XXAA了,这样就同时定义了32和10,会有问题。把定义修改如下:
      0_1532190489975_1531964334838.png

    2. 编译,因为S112和S132不完全兼容,会出现一些宏定义/结构体之类的问题,一个一个解决,可以参考s112_nrf52_6.0.0_migration-document.pdf

    3. FLASH结构设计如下:

    1532073986088

    ​ 这样预留给APP 60kB空间,其中最后4k用于存放用户配置、语音文件等。

    ​ 所以我们FLASH配置如下:

    项目 起始地址 大小
    SD112 0x00000 0x19000
    USER_APP 0x19000 0xE000
    USER_DATA 0x27000 0x1000
    BOOT_LOADER 0x28000 0x8000

    ​ 实际上,这些东西还能再细分的,具体可以参考【S112_SDS_v2.0.pdf】中sector12:

    0_1532190538407_1532075003536.png

    ​ RAM的话,sd和app的堆栈区是共享的,可以参考【S112_SDS_v2.0.pdf】中sector14,但是我没找到S112的SoftDevice RAM consumption具体是多少。实际测最少需要9k,BOOTLOADER实际上也算是一个APP,我们APP和BOOTLOADER的RAM配置都给sd留9k,其余自己用。

    0_1532190555698_1532075251997.png
    0_1532190565440_1532075263573.png

    ​ APP keil配置例如下:
    0_1532190592870_1532076372045.png

    三. 由APP返回boot

    1. 参考【\examples\ble_peripheral\ble_app_buttonless_dfu】例程序,只需要移植 ble_dfu_buttonless_bootloader_start_finalize(void) 和 nrf_dfu_svci_vector_table_set(void) 函数即可,可以从APP进入BOOT。

    2. 原理可以查看文档【S112_SDS_v2.0.pdf】中sector12.2 :

    0_1532190617327_1532077502817.png

    ​ 也就是说,如果有BOOTLOADER存在的话, UICR.NRFFW[0]中存放的就是BOOT的向量表(否则是0xFFFFFFFF),通过sd_softdevice_vector_table_base_set(uint32_t address)函数可以设置从哪个地址启动。

    1. 整个系统流程:

    0_1532190632857_1532078798439.png

    ​ 首先得知道,MBR = Master Boot Record,硬件中断只会到达这里,经过MBR的中断源,一部分在softdevice处理,一部分在app处理,这取决于sd占用了哪些资源,剩余的都到app中触发了。
    ​ 所以问题的关键在怎么切换MBR—app/boot的部分,我只知道用sd_softdevice_vector_table_base_set就行了,但是这个函数没有提供源码,没找到具体是怎么实现的

    0_1532190647616_1532079719965.png

    ​ 然后有个很有意思的东西,没弄明白,留在最后
    0_1532190704046_1532080459109.png
    0_1532190739336_1532080495648.png
    0_1532190757481_1532080507026.png


 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

Looks like your connection to Dian was lost, please wait while we try to reconnect.