This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Using app_with_dfu jump to bootloader.

Hi all:

I use the softdevice 2.0.0 and compile bootloader example with "dual bank" on the nrf52 DK,

Running a system that can using DFU from app then jump to bootloader as example hrm did.

After I have a deep study it, I found out that:

  1. DFU will sign a value "BOOTLOADER_DFU_START" into "GPREGRET".

  2. it will restart using "bootloader_util_app_start(NRF_UICR->NRFFW[0]);" into bootloader.

  3. While into bootloader, the main function will check the sign on "GPREGRET"(bool app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START);)

  4. The DFU flow just as the picture below. image description

  5. And the problem is: it will stuck at dfu_ble_svc_peer_data_set(&m_peer_data); --> dfu_app_handler.c line 110

  6. the nrftool DFU on my iPhone will show: image description

  7. If I mark the step 5. line 110, and it will went to the function: "bootloader_util_app_start(NRF_UICR->NRFFW[0]);", but nrftool app on my iPhone still show "Enabling DFU Bootloader"

I think that did not really jump into bootloader, but why? What should I check?

Please correct me if I misunderstanding the DFU flow.

Thx for everyone willing to help me solve this problem.

Update 2016/06/27:

There're no return error code after that break point: err_code = dfu_ble_svc_peer_data_set(&m_peer_data); image description

and the variable m_peer_data is: image description image description image description

Parents
  • Hi Coldson,

    Good news, I found a bug. It was because we redirect the vector table to the bootloader too early in the bootloader_start() function. So if you cut the 2 lines :

    err_code = sd_softdevice_vector_table_base_set(NRF_UICR->NRFFW[0]);
    APP_ERROR_CHECK(err_code);
    

    In that function in dfu_app_handler.c.

    And paste them after the call to dm_peer_addr_get in the same file, in dfu_app_peer_data_set. It should be ok. It should look like this:

      err_code = dm_handle_get(conn_handle, &m_dm_handle);
        if (err_code == NRF_SUCCESS)
        {
            err_code = dm_distributed_keys_get(&m_dm_handle, &key_set);
            if (err_code == NRF_SUCCESS)
            {
                APP_ERROR_CHECK(err_code);
    
                m_peer_data.addr              = key_set.keys_central.p_id_key->id_addr_info;
                m_peer_data.irk               = key_set.keys_central.p_id_key->id_info;
                m_peer_data.enc_key.enc_info  = key_set.keys_periph.enc_key.p_enc_key->enc_info;
                m_peer_data.enc_key.master_id = key_set.keys_periph.enc_key.p_enc_key->master_id;
    
    
                app_context_data   = (DFU_APP_ATT_TABLE_CHANGED << DFU_APP_ATT_TABLE_POS);
                app_context.len    = sizeof(app_context_data);
                app_context.p_data = (uint8_t *)&app_context_data;
                app_context.flags  = 0;
    
                err_code = dm_application_context_set(&m_dm_handle, &app_context);
                APP_ERROR_CHECK(err_code);
    		err_code = sd_softdevice_vector_table_base_set(NRF_UICR->NRFFW[0]);
    		APP_ERROR_CHECK(err_code);
                err_code = dfu_ble_svc_peer_data_set(&m_peer_data);
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                // Keys were not available, thus we have a non-encrypted connection.
                err_code = dm_peer_addr_get(&m_dm_handle, &m_peer_data.addr);
                APP_ERROR_CHECK(err_code);
    		err_code = sd_softdevice_vector_table_base_set(NRF_UICR->NRFFW[0]);
    		APP_ERROR_CHECK(err_code);
    
                err_code = dfu_ble_svc_peer_data_set(&m_peer_data);
                APP_ERROR_CHECK(err_code);
            }
        }
    
Reply
  • Hi Coldson,

    Good news, I found a bug. It was because we redirect the vector table to the bootloader too early in the bootloader_start() function. So if you cut the 2 lines :

    err_code = sd_softdevice_vector_table_base_set(NRF_UICR->NRFFW[0]);
    APP_ERROR_CHECK(err_code);
    

    In that function in dfu_app_handler.c.

    And paste them after the call to dm_peer_addr_get in the same file, in dfu_app_peer_data_set. It should be ok. It should look like this:

      err_code = dm_handle_get(conn_handle, &m_dm_handle);
        if (err_code == NRF_SUCCESS)
        {
            err_code = dm_distributed_keys_get(&m_dm_handle, &key_set);
            if (err_code == NRF_SUCCESS)
            {
                APP_ERROR_CHECK(err_code);
    
                m_peer_data.addr              = key_set.keys_central.p_id_key->id_addr_info;
                m_peer_data.irk               = key_set.keys_central.p_id_key->id_info;
                m_peer_data.enc_key.enc_info  = key_set.keys_periph.enc_key.p_enc_key->enc_info;
                m_peer_data.enc_key.master_id = key_set.keys_periph.enc_key.p_enc_key->master_id;
    
    
                app_context_data   = (DFU_APP_ATT_TABLE_CHANGED << DFU_APP_ATT_TABLE_POS);
                app_context.len    = sizeof(app_context_data);
                app_context.p_data = (uint8_t *)&app_context_data;
                app_context.flags  = 0;
    
                err_code = dm_application_context_set(&m_dm_handle, &app_context);
                APP_ERROR_CHECK(err_code);
    		err_code = sd_softdevice_vector_table_base_set(NRF_UICR->NRFFW[0]);
    		APP_ERROR_CHECK(err_code);
                err_code = dfu_ble_svc_peer_data_set(&m_peer_data);
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                // Keys were not available, thus we have a non-encrypted connection.
                err_code = dm_peer_addr_get(&m_dm_handle, &m_peer_data.addr);
                APP_ERROR_CHECK(err_code);
    		err_code = sd_softdevice_vector_table_base_set(NRF_UICR->NRFFW[0]);
    		APP_ERROR_CHECK(err_code);
    
                err_code = dfu_ble_svc_peer_data_set(&m_peer_data);
                APP_ERROR_CHECK(err_code);
            }
        }
    
Children
No Data
Related