- 定义一个DFU 服务
#ifdef BLE_DFU_APP_SUPPORT
/** @snippet [DFU BLE Service initialization] */
ble_dfu_init_t dfus_init;
// Initialize the Device Firmware Update Service.
memset(&dfus_init, 0, sizeof(dfus_init));
dfus_init.evt_handler = dfu_app_on_dfu_evt;
dfus_init.error_handler = NULL;
dfus_init.evt_handler = dfu_app_on_dfu_evt;
dfus_init.revision = DFU_REVISION;
err_code = ble_dfu_init(&m_dfus, &dfus_init);
APP_ERROR_CHECK(err_code);
dfu_app_reset_prepare_set(reset_prepare);
dfu_app_dm_appl_instance_set(m_app_handle);
/** @snippet [DFU BLE Service initialization] */
#endif // BLE_DFU_APP_SUPPORT
2.添加服务到事件分配函数中
3.添加服务初始化函数,以及事件处理函数
uint32_t ble_dfu_init(ble_dfu_t * p_dfu, ble_dfu_init_t * p_dfu_init) //初始化服务函数
{
if ((p_dfu == NULL) || (p_dfu_init == NULL) || (p_dfu_init->evt_handler == NULL))
{
return NRF_ERROR_NULL;
}
p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID;
ble_uuid_t service_uuid;
uint32_t err_code;
const ble_uuid128_t base_uuid128 =
{
{
0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00
}
};
service_uuid.uuid = BLE_DFU_SERVICE_UUID; //服务的UUID
err_code = sd_ble_uuid_vs_add(&base_uuid128, &(service_uuid.type));
VERIFY_SUCCESS(err_code);
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&service_uuid,
&(p_dfu->service_handle));
VERIFY_SUCCESS(err_code);
p_dfu->uuid_type = service_uuid.type;
err_code = dfu_pkt_char_add(p_dfu); // DFU Packet characteristic to the BLE Stack
VERIFY_SUCCESS(err_code);
err_code = dfu_ctrl_pt_add(p_dfu); //DFU Control Point characteristic to the BLE Stack.
VERIFY_SUCCESS(err_code);
err_code = dfu_rev_char_add(p_dfu, p_dfu_init); //adding DFU Revision characteristic to the BLE Stack
VERIFY_SUCCESS(err_code);
p_dfu->evt_handler = p_dfu_init->evt_handler;
if (p_dfu_init->error_handler != NULL)
{
p_dfu->error_handler = p_dfu_init->error_handler;
}
m_is_dfu_service_initialized = true;
return NRF_SUCCESS;
}
void dfu_app_on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) //事件处理函数
{
switch (p_evt->ble_dfu_evt_type)
{
case BLE_DFU_START:
//复位进入bootloader 转到bootload的主函数执行
// Starting the bootloader - will cause reset.
bootloader_start(p_dfu->conn_handle);
/*****************starting 主要程序有几个注意的 ********************
err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START); // 设置 BOOTLOADER_DFU_START=0xB1
err_code = sd_softdevice_vector_table_base_set(NRF_UICR->NRFFW[0]); //设置协议栈中断向量表
/**********************************************************************/
break;
default:
{
// Unsupported event received from DFU Service.
// Send back BLE_DFU_RESP_VAL_NOT_SUPPORTED message to peer.
uint32_t err_code = ble_dfu_response_send(p_dfu,
BLE_DFU_START_PROCEDURE,
BLE_DFU_RESP_VAL_NOT_SUPPORTED);
APP_ERROR_CHECK(err_code);
}
break;
}
}
4.程序由app->bootload
int main(void)
{
uint32_t err_code;
bool dfu_start = false;
bool app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START); //这个寄存器值由app设置 这里相同 所以APPSET=1
if (app_reset)
{
NRF_POWER->GPREGRET = 0; //清除,防止一直boot
}
leds_init();
// This check ensures that the defined fields in the bootloader corresponds with actual
// setting in the chip.
APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
APP_ERROR_CHECK_BOOL(NRF_FICR->CODEPAGESIZE == CODE_PAGE_SIZE);
// Initialize.
timers_init();
buttons_init();
(void)bootloader_init();
if (bootloader_dfu_sd_in_progress()) //协议栈更新,这里我们不更新 所以值为false直接进去else程序
{
nrf_gpio_pin_clear(UPDATE_IN_PROGRESS_LED);
err_code = bootloader_dfu_sd_update_continue();
APP_ERROR_CHECK(err_code);
ble_stack_init(!app_reset);
scheduler_init();
err_code = bootloader_dfu_sd_update_finalize();
APP_ERROR_CHECK(err_code);
nrf_gpio_pin_set(UPDATE_IN_PROGRESS_LED);
}
else
{
// If stack is present then continue initialization of bootloader.
ble_stack_init(!app_reset); //协议栈app_set==1
scheduler_init();
}
dfu_start = app_reset;
dfu_start |= ((nrf_gpio_pin_read(BOOTLOADER_BUTTON) == 0) ? true: false);
if (dfu_start || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START)))
{
nrf_gpio_pin_clear(UPDATE_IN_PROGRESS_LED);
// Initiate an update of the firmware.
err_code = bootloader_dfu_start();
/***********************************代码追溯***************************////
// bootloader_dfu_start()
---->>>>>>
dfu_transport_update_start()
---->>>>>{
....
gap_params_init();
services_init();
conn_params_init();
sec_params_init();
advertising_start(); //开启广播后 连接设备 ,进行数据传输。
......
}
/*************************************************************************///
APP_ERROR_CHECK(err_code);
nrf_gpio_pin_set(UPDATE_IN_PROGRESS_LED);
}
if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress()) //判断传输状态和地址是否正确
{
// Select a bank region to use as application region.
// @note: Only applications running from DFU_BANK_0_REGION_START is supported.
bootloader_app_start(DFU_BANK_0_REGION_START); // 重启开始 重启app中断向量表的reset 所以程序从app开始执行
}
NVIC_SystemReset();
}