nrf51822/52832学习笔记之官方DFU过程梳理

  1. 定义一个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.添加服务到事件分配函数中

nrf51822/52832学习笔记之官方DFU过程梳理_第1张图片


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();  
}

你可能感兴趣的:(nrf51822蓝牙开发)