如何为BLE 设备添加OTA DFU 空中升级服务(下)?

本文详细介绍了如何为Nordic SDK工程添加BLE DFU Service,包括Buttonless DFU without bonds和with bonds两种情况。通过实例解析添加服务的步骤,涉及SoftDevice、BLE Services、Peer Manager等关键组件,以及如何处理配对绑定和内存配置问题。
摘要由CSDN通过智能技术生成

前篇博文详细介绍了BLE 设备实现OTA DFU 功能的工作原理,也借助Nordic SDK 提供的示例工程展示了执行Buttonless BLE DFU 的过程。重点是,我们如何为自己开发的BLE 工程添加BLE DFU Service 呢?

一、如何为Nordic 工程添加Service?

要想为Nordic SDK 工程添加服务或者应用逻辑,需要先了解SDK 的代码组织结构,我们选用Nordic 芯片通常用来开发BLE 芯片,都是带SoftDeice 协议栈的,带BLE Protocol Stack 的软件架构如下:
SoC application with the SoftDevice
从下到上,大致可以分为三层:

  • nRF5x Drivers:对于ARM 架构芯片须符合CMSIS(Cortex Microcontroller Software Interface Standard),用于驱动芯片硬件外设模块,比如UART、SPI、TWI (IIC)、SDIO 等;
  • SoftDevice / Libraries:SoftDevice 是BLE 协议栈的实现,Nordic 以hex 文件形式提供,对应用层提供了相应的Protocol API。Libraries 是为方便管理共享硬件资源开发的一个个资源管理模块,对上层应用提供相应nRF API,比如 Atomic、FIFO / Queue、SHA256 / CRC32、Crypto / ECC、App_timer 等;
  • BLE Services:根据业务需求开发的一个个应用服务BLE Services / Profiles,nRF SDK 也提供了很多常见的BLE Services,比如ble_dfu、ble_nus、ble_battery、ble_hrs、ble_proximity 等。

前篇博文介绍Nordic Memory layout 时谈到,Nordic SoftDevice 和 Application 是分别存储在两个flash 分区的,二者代码区相互独立,可以分别独立进行升级。SoftDevice 和 Application 运行时使用的RAM 地址空间也是相互独立的(Bootloader 和Application 不会同时运行,因此复用RAM 地址空间),SoftDevice 运行时使用的RAM start address 和RAM size 需要根据BLE Services 数量和Attribute table 大小进行调整。
Nordic Memory resource map
Application 和SoftDevice 分别存储运行在不同的Flash 和RAM 地址空间,二者之间如何通讯呢?SoftDevice 对上层应用提供了SoftDevice API,上层应用调用SoftDevice API 实际上是触发SV Call (Supervisor Call) interrupt,每个API 都有一个SVC numbers,SoftDevice 根据SVC numbers 执行相应的事件处理,待该事件处理完毕后,SoftDevice 会触发SWI (Software Interrupt),通知Application 请求事件已处理完毕,可以继续进行后续的数据处理或业务逻辑了。

二、如何为工程添加BLE DFU Service?

我们选择一个比较常用的工程ble_app_uart 为例,在该示例工程中添加DFU 服务,为了方便判断DFU 前后版本对比,可以在工程ble_app_uart 中添加读取当前软件版本的命令。

首先我们查看BLE DFU 服务的相关介绍:Buttonless Secure DFU Service,了解到其主要分为Buttonless DFU without bonds 和Buttonless DFU with bonds 两种情况,后者需要配对绑定过程,因此需要Peer Manager Libraries。二者还需要Power Management library,用于控制BLE 系统重置进入DFU mode 的时间,下面分别介绍如何向工程ble_app_uart 中添加Buttonless DFU without bonds 和Buttonless DFU with bonds 服务。

2.1 如何为工程添加Buttonless DFU without bonds service?

首先,往工程ble_app_uart 中添加DFU 需要的源文件和头文件路径如下(可以复制工程ble_app_uart 为ble_app_uart_dfu,并在工程ble_app_uart_dfu 基础上开发):
Segger 添加ble_dfu service
在services_init 函数中新增初始化DFU 服务、并注册相应的事件处理函数ble_dfu_evt_handler,再在sdk_config 中配置使能BLE_DFU 服务如下(从工程ble_app_buttonless_dfu 复制而来):

// .\nRF5_SDK_17.0.2_d674dde\examples\ble_peripheral\ble_app_uart_dfu\main.c
// Add DFU service
#include "ble_dfu.h"

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;
    }
}
......
/**@brief Function for initializing services that will be used by the application.
 */
static void services_init(void)
{
   
    .....
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流云IoT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值