Add DFU service developed by nrf52832

Foreword: Adding DFU service to Nordic's BLE program is much simpler than building DFU. Basically, following the process will enable your application to realize wireless DFU

1. Early preparations

1. Add the DFU source code
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_941_bK_94_96 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. Modify the sdk_config.h file
1) Enable the DFU module
#ifndef BLE_DFU_ENABLED
#define BLE_DFU_ENABLED 1
#endif

2) Modify the number of custom UUIDs used. Each additional one must modify the starting address and use size of the RAM in the project. The RAM size occupied by 1 UUID is 0x10
#ifndef NRF_SDH_BLE_VS_UUID_COUNT
#define NRF_SDH_BLE_VS_UUID_COUNT 2
#endif

Modify according to the number of custom UUIDs actually used

2. Modify the main program code

1. Include header files

#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. Initialize the DFU service in the initialization service function

//获取广播配置参数
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. Register the protocol stack status monitor

//协议栈状态发送改变时会调用此函数
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,
};

So far, the process of adding DFU service to the BLE program written by yourself has been introduced

Published 81 original articles · 21 praises · 30,000+ views

Guess you like

Origin blog.csdn.net/qq_33575901/article/details/102612429