nRF52832 secure DFU移植详细步骤

  • Post author:
  • Post category:其他



nRF52832 secure DFU


移植详细步骤


一. 测试的平台


参考博文:


https://blog.csdn.net/mygod2008ok/article/details/89715626


https://www.cnblogs.com/iini/p/9314246.html

本篇文章主要介绍将DFU功能移植到ble_app_hrs_pca10040_s132工程上。


整个测试平台如下




环境

:win10,64位,MDK集成开发环境.


SDK

:nRF5_SDK_15.2


协议栈

:s132_nrf52_6.1_softdevice.hex.


Bootloader


工程

:secure_dfu_ble_s132_pca10040.


DFU


参考工程

:ble_app_buttonless_dfu_pca10040_s132.


硬件平台

:pca10040开发板.


二. Application


移植

  1. 添加相关C文件

在工程中添加ble_dfu.c、ble_dfu_bonded.c、ble_dfu_unbonded.c、nrf_dfu_svci.c这四个文件

2. 添加头文件

https://img-blog.csdnimg.cn/20190502231418698.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L215Z29kMjAwOG9r,size_16,color_FFFFFF,t_70

3. 添加全局变量

在C/C++选项中添加2个NRF_DFU_TRANSPORT_BLE=1和BL_SETTINGS_ACCESS_ONLY宏定义

https://img-blog.csdnimg.cn/2019050223020774.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L215Z29kMjAwOG9r,size_16,color_FFFFFF,t_70

4. 加入DFU相关代码(可参考ble_app_buttonless_dfu_pca10040_s132)

(1)在main.c中的services_init函数中添加DFU服务初时化代码

ble_dfu_buttonless_init_t dfus_init = {0};

dfus_init.evt_handler = ble_dfu_evt_handler;

err_code = ble_dfu_buttonless_init(&dfus_init);

APP_ERROR_CHECK(err_code);

(2)在main.c中添加DFU事件处理函数

#include “ble_dfu.h”

#ifdef DFU_SUPPORT
static void advertising_config_get(ble_adv_modes_config_t * p_config)
{
    memset(p_config, 0, sizeof(ble_adv_modes_config_t));

    p_config->ble_adv_fast_enabled  = true;
    p_config->ble_adv_fast_interval = APP_ADV_INTERVAL;
    p_config->ble_adv_fast_timeout  = APP_ADV_DURATION;
}
static void disconnect(uint16_t conn_handle, void * p_context)
{
    UNUSED_PARAMETER(p_context);

    ret_code_t err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    if (err_code != NRF_SUCCESS)
    {
        NRF_LOG_WARNING("Failed to disconnect connection. Connection handle: %d Error: %d", conn_handle, err_code);
    }
    else
    {
        NRF_LOG_DEBUG("Disconnected connection handle %d", conn_handle);
    }
}
// YOUR_JOB: Update this code if you want to do anything given a DFU event (optional).
/**@brief Function for handling dfu events from the Buttonless Secure DFU service
 *
 * @param[in]   event   Event from the Buttonless Secure DFU service.
 */
static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
{
    switch (event)
    {
        case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
        {
            NRF_LOG_INFO("Device is preparing to enter bootloader mode.");

            // Prevent device from advertising on disconnect.
            ble_adv_modes_config_t config;
            advertising_config_get(&config);
            config.ble_adv_on_disconnect_disabled = true;
            ble_advertising_modes_config_set(&m_advertising, &config);

            // Disconnect all other bonded devices that currently are connected.
            // This is required to receive a service changed indication
            // on bootup after a successful (or aborted) Device Firmware Update.
            uint32_t conn_count = ble_conn_state_for_each_connected(disconnect, NULL);
            NRF_LOG_INFO("Disconnected %d links.", conn_count);
            break;
        }

        case BLE_DFU_EVT_BOOTLOADER_ENTER:
            // YOUR_JOB: Write app-specific unwritten data to FLASH, control finalization of this
            //           by delaying reset by reporting false in app_shutdown_handler
            NRF_LOG_INFO("Device will enter bootloader mode.");
            break;

        case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
            NRF_LOG_ERROR("Request to enter bootloader mode failed asynchroneously.");
            // YOUR_JOB: Take corrective measures to resolve the issue
            //           like calling APP_ERROR_CHECK to reset the device.
            break;

        case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
            NRF_LOG_ERROR("Request to send a response to client failed.");
            // YOUR_JOB: Take corrective measures to resolve the issue
            //           like calling APP_ERROR_CHECK to reset the device.
            APP_ERROR_CHECK(false);
            break;

        default:
            NRF_LOG_ERROR("Unknown event from ble_dfu_buttonless.");
            break;
    }
}
#endif

5. 修改sdk_config.h

使能DFU

#ifndef BLE_DFU_ENABLED
#define BLE_DFU_ENABLED 1
#endif

UUID_COUNT这里添加了一个DFU服务,所以加1;TAB_SIZE添加了200

// <o> NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE - Attribute Table size in bytes. The size must be a multiple of 4. 
#ifndef NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE
#define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1608
#endif

// <o> NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs. 
#ifndef NRF_SDH_BLE_VS_UUID_COUNT
#define NRF_SDH_BLE_VS_UUID_COUNT 1
#endif

6. 修改RAM和ROM的设置

0x26000是协议栈s132_nrf52_6.1.0_softdevice.hex所占的ROM空间大小,即协议栈地址范围是0~0x26000

0x52000是用户程序可用ROM空间的大小

0x20002C60是协议栈s132_nrf52_6.1.0_softdevice.hex所占的RAM空间大小,范围是0x20000000~0x20002C60

0Xd3A0是用户程序可能RAM空间的大小


如果不确定协议栈所占RAM的空间大小,可以使用以下方法来确定

7. 在nrf_sdh_ble.c中定义变量startRam,ramSize;然后在nrf_sdh_ble_enable函数中添加2行代码后编译一下

8. 设置断点,仿真运行就能得到startRam,ramSize这两个参数的值了


三. Bootloarder


修改

BootLoader工程路径“nRF5_SDK_15.2.0_9412b96\examples\dfu\secure_bootloader\pca10040_ble”

  1. 添加秘钥

将生成的秘钥添加到dfu_public_key.c文件中

2. 修改sdk_config.h

修改进入DFU的模式, NRF_BL_DFU_ENTER_METHOD_BUTTONLESS 决定是否通过按键进入DFU模式。


四. 在做空中升级过程中可能遇到的问题

BootLoader错误:

  1. 缺少uECC.h文件.
  2. 缺少micro_ecc_lib_nrf52.lib文件.
  3. 出现报错:#error “Debug public key not valid for production. Please see https://github.com/NordicSemiconductor/pc-nrfutil/blob/master/README.md to generate it” .


五.


安装软件工具

安装编译micro-ecc所需的工具,micro-ecc文件路径“nRF5_SDK_15.2.0_9412b96\external\micro-ecc”

(1)gcc-arm-none-eabi-6-2017-q2-update-win32:(keil官方下载,编译工具)

https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads

根据提示安装 6-2017-q2-update版本的 GCC compiler toolchain for ARM

双击安装把路径,安装结束勾选添加到环境变量,如果没有就手动添加。


也可以安装更高级的编译工具链,安装完之后需要修改配置文件“nRF5_SDK_15.2.0_9412b96\components\toolchain\gcc\makefiles.windows”将红色框框修改成自己的路径就可以了

路径不对将会出现这个报错



(2)make工具:

(



MinGW







GNU Make







Xcode



三选一


)

build库工具


http://www.mingw.org/download/installer

(我选的这个)

选中Basic Setup中的 mingw32-base,和minggw32-gcc-g+

然后点菜单 installation -> Apply Changes

等待安装完成后,如下图:





打开 MinGW 的安装目录,打开 bin 文件夹,将 mingw32-make.exe 复制一个当前目录下,然后重命名为 make.exe

(3)python-2.7.12.amd64.msi(用来安装nrfutil的)


https://www.python.org/downloads/

双击python-2.7.12.amd64.msi安装 ,安装完毕后,把python的路径加入到环境变量中C:\Python27;C:\Python27\Scripts

进入命令行窗口,并到Python路径,输入python -m pip install nrfutil等待安装完成

nrfutil会被安装到C:\Python27\Scripts目录下,可以通过pip install nrfutil==3.5.0去安装指定版本的nrfutil,

切记不能用低级的版本,不然在生成秘钥的过程会遇到以下错误“Got unexpected extra argument (private.pem)”

(4)nRFgo Studio

主要提供nrfjprog.exe和mergehex.exe

这两个软件在nRFgo Studio的安装目录下找到

C:\Program Files (x86)\Nordic Semiconductor\nrf5x\bin

安装之后用cmd输入nrfjprog和mergehex,查看是否安装可用

(5)下载git

因为SDK15的mircro-ecc(椭圆加密算法,安全升级的加密签名算法) 需要的文件通过执行git自动下载的

https://www.git-scm.com/download/


六. 解决问题步骤

1.解决缺少uECC.h文件问题(SDK15比之前版本下载更方便)操作如下:

(1)在..\ nRF5_SDK_15.2.0_9412b96\external\micro-ecc文件夹中双击build_all.bat

就会通过git自动下载mircro-ecc相关的文件。

(2)打开micro-ecc目录可以看见uECC.h

2.解决缺少micro_ecc_lib_nrf52.lib的问题

(1)方法1:双击批处理文件nRF5_SDK_15.2.0_9412b96\external\micro-ecc\build_all.bat即可生成lib文件;

可以修改build_all.bat 最后增加pause指令,方便查看是否build成功,也可以删除不需要的条目。

(2)方法2:打开cmd,进入下面的到路径,nRF5_SDK_15.2.0_9412b96\external\micro-ecc\nrf52_keil\armgcc路径,输入make 生成lib文件。


nrf52hf_keil


和nrf52nf_keil区别nrf52hf_keil是硬件浮点数运算,如果编译不行就用   nrf52nf_keil 替换nrf52hf_keil,实际编译设置环境有关。

以上两种方法都是用到了micro-ecc\nrf52_keil\armgcc\makefile



4. 解决编译报错问题(bootload)

……\dfu\secure_bootloader\pca10040_ble编译过程中会出现报错:

#error “Debug public key not valid for production. Please see https://github.com/NordicSemiconductor/pc-nrfutil/blob/master/README.md to generate it”,看报错就知道这是缺少秘钥造成的,这个报错,需要大家添加一个秘钥上去。

在windows任意目录下,做个BAT文件,输入下面两行命令,双击bat,在当前目录就会生成两个文件,或者按照下面操作步骤:

打开cmd命令行,键入以下指令

nrfutil.exe keys generate private.pem
nrfutil.exe keys display --key pk --format code private.pem --out_file public_key.c

这样生成的秘钥就保存在 public_key.c中,打开public_key.c。把数组pk复制到报错的位置。

以上工作全部做完就可以编译 bootloarder了,输出hex


七.  烧录协议栈、应用层、bootloader(全部写成bat文件了)

(1)先要生成bootloader setting, 这个文件包含了app version ,bootloader version , hw version, 等信息。

nrfutil.exe settings generate --family NRF52 --application nrf52832_xxaa.hex --application-version 3  --bootloader-version 2 --bl-settings-version 1 bootloader_settings.hex

(2)合并所有文件,注意自己的hex文件名。

合并BootLoader文件和softdevice文件:

mergehex.exe  --merge  nrf52832_xxaa_s132.hex 132_nrf52_6.1.0_softdevice.hex --output production_final1.hex

合并临时文件和用户程序:

mergehex.exe  --merge  production_final1.hex   nrf52832_xxaa.hex  --output production_final2.hex

合并临时文件和配置settings 文件:

mergehex.exe  --merge  production_final2.hex   bootloader_settings.hex  --output nrf52832_final.hex

(3)固件烧录

方法1:

将烧录器和板子还有电脑连接,在命令窗口中输入以下指令

nrfjprog -f NRF52 --eraseall
nrfjprog -f NRF52 --program " nrf52832_final.hex " --verify
nrfjprog -f NRF52 –reset

方法2:

将烧录器和板子还有电脑连接,打开nRFgo Studio

先选择“Erase all”擦除程序,然后选择nrf52832_final.hex直接烧录即可。

这时打开手机app nRF Connect即可看到程序中设置的蓝牙名称的设备了。

(4)生成DFU升级文件。

将nrf52832_xxaa.hex和private.pem复制到同一个目录下

s132_nrf52_6.0.0_softdevice.hex --application SDK15DFUtest.hex --application-version 0xFF --hw-version 52 --sd-req 0xa8 --key-file priv.pem sd132_v3_bl.zip

–sd-req 0xaf    协议栈版本,可通过以下指令查询“nrfutil pkg generate –help”




key-file private.pem “解决编译报错问题 “中生成的秘钥文件 ,给压缩包数字签名用的

(5)制作 bootloader 和 协议栈及应用 升级包(全部升级,一般不用)

命令:

nrfutil pkg generate --bootloader nrf52832_s132_boot.hex --bootloader-version 0xFF --softdevice 
s132_nrf52_6.0.0_softdevice.hex --application SDK15DFUtest.hex --application-version 0xFF --hw-version 52 --sd-req 0xa8 --key-file priv.pem sd132_v3_bl.zip

六. 手机空中升级的实现(nRF Connect工具操作升级)

(1)打开nRF Connect扫描设备

https://img-blog.csdnimg.cn/20190504104034950.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L215Z29kMjAwOG9r,size_16,color_FFFFFF,t_70

(2)连接设备

(3)打开DFU服务notify开关。

https://img-blog.csdnimg.cn/20190504104402543.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L215Z29kMjAwOG9r,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/20190504104719197.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L215Z29kMjAwOG9r,size_16,color_FFFFFF,t_70

(4)点击notify左边的按钮打开写数据界面,打send发送使设备进入bootloader 模式

(5)重新扫描

https://img-blog.csdnimg.cn/20190504105114302.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L215Z29kMjAwOG9r,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/20190504105437518.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L215Z29kMjAwOG9r,size_16,color_FFFFFF,t_70

(6)连接DfuTarg后打开notify开关

https://img-blog.csdnimg.cn/20190504110054346.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L215Z29kMjAwOG9r,size_16,color_FFFFFF,t_70

这个名字要改的话,请在bootload中修改


sdk_config


文件中  #define NRF_DFU_BLE_ADV_NAME “DfuTarg”

(7)点击右上角的DFU按钮打开加载升级文件页面,点击OK键去加载nrf52832_xxaa_app.zip升级包





版权声明:本文为Smile_Smilling原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。