nrf52832开发之添加DFU服务

前言:在nordic的BLE程序中添加DFU服务比DFU的搭建要简单许多了,基本跟着流程走就能让自己的应用程序实现无线DFU

一、前期准备

1.在要添加DFU服务的工程中添加DFU源码
nRF5_SDK_15.2.0_9412b96\components\ble\ble_services\ble_dfu\ble_dfu.c
nRF5_SDK_15.2.0_9412b96\components\ble\ble_services\ble_dfu\ble_dfu_bonded.c
nRF5_SDK_15.2.0_9412b96\components\ble\ble_services\ble_dfu\ble_dfu_unbonded.c
nRF5_SDK_15.2.0_9412b96\components\libraries\bootloader\dfu\nrf_dfu_svci.c

2.添加头文件路径
..\Libraries\components\libraries\svc
..\Libraries\components\libraries\bootloader
..\Libraries\components\libraries\bootloader\dfu
..\Libraries\components\libraries\bootloader\ble_dfu
..\Libraries\components\ble\ble_services\ble_dfu
..\Libraries\components\softdevice\mbr\nrf52832\headers

3.添加宏
1)BLE_SETTINGS_ACCESS_ONLY 
2)NRF_DFU_SVCI_ENABLED 
3)NRF_DFU_TRANSPORT_BLE=1

4.修改sdk_config.h文件
1)使能DFU模块
#ifndef BLE_DFU_ENABLED
#define BLE_DFU_ENABLED 1
#endif

2)修改使用的自定义UUID数量,每添加一个都要修改工程中RAM的开始地址和使用大小,1个UUID占用的RAM大小为0x10
#ifndef NRF_SDH_BLE_VS_UUID_COUNT
#define NRF_SDH_BLE_VS_UUID_COUNT 2
#endif

根据实际使用的自定义UUID个数修改

二.修改主程序代码

1.包含头文件

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

2.在初始化服务函数里面初始化DFU服务

//获取广播配置参数
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);
    }
}

//DFU回调函数
static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
{
	ret_code_t err_code;
    switch (event)
    {	//在进入bootloader执行DFU前的准备工作
        case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
            NRF_LOG_INFO("Device is preparing to enter bootloader mode.");
			//防止设备断开连接时进行广播
            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);

            // 断开当前的所有连接
            uint32_t conn_count = ble_conn_state_for_each_connected(disconnect, NULL);
            NRF_LOG_INFO("Disconnected %d links.", conn_count);

        case BLE_DFU_EVT_BOOTLOADER_ENTER:
            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.");
            break;

        case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
            NRF_LOG_ERROR("Request to send a response to client failed.");
            APP_ERROR_CHECK(false);
            break;

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

static void dfu_s_init(void)
{
    uint32_t err_code;

	ble_dfu_buttonless_init_t dfus_init = {0};
	//注册DFU回调函数
	dfus_init.evt_handler = ble_dfu_evt_handler;
	//初始化DFU
	err_code = ble_dfu_buttonless_init(&dfus_init);
	APP_ERROR_CHECK(err_code);
}

static void services_init(void)
{
    //初始化DFU服务
    dfu_s_init();
}

3.注册协议栈状态监视者

//协议栈状态发送改变时会调用此函数
static void buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void * p_context)
{
    if (state == NRF_SDH_EVT_STATE_DISABLED)
    {
        //在复位之前禁用协议栈,并告知bootloader启动时跳过CRC
        nrf_power_gpregret2_set(BOOTLOADER_DFU_SKIP_CRC);
        //进入system off模式
        nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
    }
}

NRF_SDH_STATE_OBSERVER(m_buttonless_dfu_state_obs, 0) =
{
    .handler = buttonless_dfu_sdh_state_observer,
};

至此,实现在自己编写的BLE程序中添加DFU服务的流程介绍完毕

发布了81 篇原创文章 · 获赞 21 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_33575901/article/details/102612429
今日推荐