nRF52832 secure DFU移植详细步骤

    xiaoxiao2023-11-17  133

    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移植

    添加相关C文件

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

        2. 添加头文件

    3. 添加全局变量

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

    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”

    添加秘钥

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

       2. 修改sdk_config.h

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

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

    BootLoader错误:

    缺少uECC.h文件.缺少micro_ecc_lib_nrf52.lib文件.出现报错:#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扫描设备

      

    (2)连接设备

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

         

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

    (5)重新扫描

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

         

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

    sdk_config文件中  #define NRF_DFU_BLE_ADV_NAME "DfuTarg"

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

    最新回复(0)