普通nRF5固件支持DFU升级要点

1)项目里加入2个宏定义:

 BL_SETTINGS_ACCESS_ONLY
 NRF_DFU_TRANSPORT_BLE=1

2)项目的Include路径内加入以下路径:

 ../../../../../../components/libraries/bootloader
 ../../../../../../components/libraries/bootloader/dfu
 ../../../../../../components/libraries/bootloader/ble_dfu

3)最重要也是最不自动化的操作,调整RAM_START地址:

nRF5 SDK支持BLE都是需要SoftDevice的,SD就是官方做好的协议栈,软件结果,二进制发布,像个硬件一样,所以才叫SoftDevice。在nRF5 SDK中,所有预先定义好的Service都是动态自己管理内存的,比如battery Service(BMS),比如血压心率bps Service等,都是官方做好的,可以直接引入使用,和SD没有关系。但是如果用户自己要加一个所谓的Vendor Specific Service,就需要告诉SD,预留出一个16字节的内存空间,来存储一个结构体,定义这个VS相关的信息(UUID etc.)。所以要在Linker设置中,调整RAM_START参数。

我们加的DFU服务,就是一个VS服务,所以,RAM_START要加0x10。

举个例子:

RAM_START=0x20002ae8

改为

RAM_START=0x20002af8

4)修改sdk_config.h

 #define BLE_DFU_ENABLED 1 // was 0
 #define NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY 1 // was 0
 #define NRF_SDH_BLE_VS_UUID_COUNT 2 // was 1
 #define NRF_SDH_BLE_SERVICE_CHANGED 1 // was 0

5)加入相关库文件

项目树加一个Group,命名为nRF_DFU,加入以下文件:

 SDK_DIR\components\ble\ble_services\ble_dfu

 ble_dfu.c
 ble_dfu_bonded.c
 ble_dfu_unbonded.c

 SDK_DIR\components\libraries\bootloader\dfu

 nrf_dfu_svci.c

6)修改main.c

首先加入头文件:

 #include "nrf_dfu_ble_svci_bond_sharing.h"
 #include "nrf_svci_async_function.h"
 #include "nrf_svci_async_handler.h"
 #include "ble_dfu.h"
 #include "nrf_bootloader_info.h"

可以修改BLE 广播名称为一个明显的名称:

 #define DEVICE_NAME "APP_DFU"

加入一个dfu事件处理函数:

 static void ble_dfu_buttonless_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\r\n");
         break;
      case BLE_DFU_EVT_BOOTLOADER_ENTER:
         NRF_LOG_INFO("Device will enter bootloader mode\r\n");
         break;
      case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
         NRF_LOG_ERROR("Device failed to enter bootloader mode\r\n");
         break;
      default:
         NRF_LOG_INFO("Unknown event from ble_dfu.\r\n");
         break;
    }
 }

加一个重启进bootloader去DFU前的关机函数:

 static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event)
 {
   switch (event)
   {
   case NRF_PWR_MGMT_EVT_PREPARE_DFU:
   NRF_LOG_INFO("Power management wants to reset to DFU mode\r\n");
   // Change this code to tailor to your reset strategy.
   // Returning false here means that the device is not ready
   // to jump to DFU mode yet.
   //
   // Here is an example using a variable to delay resetting the device:
   //
   /* if (!im_ready_for_reset)
   {
      return false;
   }
   */
   break;
   default:
   // Implement any of the other events available
   // from the power management module:
   // -NRF_PWR_MGMT_EVT_PREPARE_SYSOFF
   // -NRF_PWR_MGMT_EVT_PREPARE_WAKEUP
   // -NRF_PWR_MGMT_EVT_PREPARE_RESET
   return true;
   }
   NRF_LOG_INFO("Power management allowed to reset to DFU mode\r\n");
  return true;

 }
 NRF_PWR_MGMT_HANDLER_REGISTER(app_shutdown_handler, 0);

服务初始化函数增加内容:

 static void services_init(void)
 {

   ..............

   ble_dfu_buttonless_init_t dfus_init =
   {
      .evt_handler = ble_dfu_buttonless_evt_handler
   };
   err_code = ble_dfu_buttonless_init(&dfus_init);
   APP_ERROR_CHECK(err_code);

 }

做完以上几点,基本就可以测试了。测试的方法见文章:

nrf52832通过DFU升级的要点记录

编译通过,然后把生成的hex打包成.zip,测试有个简单方法,不用网上其它文章写的冗长的步骤,只需以下几步即可:

1)用nRFgo把flash全擦了;

2)烧SoftDevice;

3)烧bootloader;

4)把打好包的.zip传送到手机上;

5)打开手机的nRF Connect应用,找到“DFU targ”,连接之,发现DFU图标,点击,选择.zip并开始进行更新,更新完成,重新扫描即可以看到名称为“APP_DFU"的设备名称;

6)重新连接"APP_DFU",也能出现DFU图标,也可以进行buttonless升级了(可以无限升级);

以上步骤,如果哪一步出了问题,可以回到第一步,擦除全部flash重试。之所以步骤比较少,是因为在第5步的时候,很多工作,bootloader都替我们做了,比如写配置,改状态之类的。

 

 

 


欢迎转载,本文地址: https://blog.prodrich.com/detail/45/

带着使命来到世上的你,给他人提供价值,才有价值