nRF52832 secure DFU移植详细步骤

nRF52832 secure DFU移植详细步骤

一. 测试的平台
    参考博文:

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

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

http://www.sunyouqun.com/2017/05/nordic-dfu-study/?tdsourcetag=s_pcqq_aiomsg

 

本篇文章主要介绍将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://i-blog.csdnimg.cn/blog_migrate/b99f77e025eaaa6e17297e42990edae1.png

3. 添加全局变量

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

https://i-blog.csdnimg.cn/blog_migrate/f71506eadb0a618219452c848febd912.png

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工具:(MinGWGNU MakeXcode 三选一)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://i-blog.csdnimg.cn/blog_migrate/b4ee3bb98ef17e19761c84b5c4e5c981.png   

(2)连接设备

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

https://i-blog.csdnimg.cn/blog_migrate/a5260278960df8601667c236c5b5c5a6.png  https://i-blog.csdnimg.cn/blog_migrate/c1761bff0da7784c9314bcc1c8ac09cc.png    

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

(5)重新扫描

https://i-blog.csdnimg.cn/blog_migrate/9c9179fc0dcf2f07557162f6fcdb3c80.pnghttps://i-blog.csdnimg.cn/blog_migrate/f43027d6a96dfbaabef90790a942868c.png

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

https://i-blog.csdnimg.cn/blog_migrate/00abd27fa1a73316a4f801b6c55dc9b3.png      

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

sdk_config文件中  #define NRF_DFU_BLE_ADV_NAME "DfuTarg"

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

nRF52832串口DFU是指使用Nordic公司为其nRF52832芯片提供的串口(USART)接口进行固件升级的一种方法。串口DFU代表数据固件升级(Data Firmware Update),通过串口接口将新的固件传输到nRF52832芯片中,实现固件升级的功能。 nRF52832是一款低功耗、高集成度的蓝牙低功耗(BLE)系统级芯片,适用于物联网和低功耗应用。在开发过程中,固件升级是一个重要的环节,可以使产品保持最新的功能和性能,修复已知的漏洞和错误。 nRF52832串口DFU的工作原理是通过将新的固件文件传输到nRF52832芯片的内部存储器进行更新。首先,在计算机上安装nRF52832串口DFU工具,并连接串口线将计算机与nRF52832芯片连接起来。然后,选择要升级的固件文件,并发送到串口接口。nRF52832芯片会接收到固件文件并将其存储到内部存储器中。最后,芯片重启并加载新的固件,完成固件升级过程。 使用nRF52832串口DFU进行固件升级具有很多优点。首先,它可以通过串口线直接从计算机传输固件文件,无需额外的硬件设备。其次,升级过程简单方便,不需要拆卸设备或更换芯片。此外,nRF52832芯片的低功耗特性使得固件升级过程中能够保持设备的低功耗工作状态。 总的来说,nRF52832串口DFU是一种方便、高效的固件升级方法,可以帮助开发人员和制造商保持产品的最新性能和功能,并提供更好的用户体验。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值