Hi, We have being producing ble items with nrf51822 QFAAG , S110 SD 7.0, SDK 6.1, Dual bank DFU. When updating the application throught Android, the bootloader hangs, because bootloader_app_is_valid returns true, but bank 0 is broken.
We did a little change in dfu_init, so as to set the application flag to BANK_INVALID_APP.
uint32_t dfu_init(void) {
uint32_t err_code;
bootloader_settings_t bootloader_settings;
dfu_update_status_t update_status;
pstorage_module_param_t storage_module_param = {.cb = pstorage_callback_handler};
// Clear swap area.
uint32_t * p_bank_start_address = (uint32_t *)DFU_BANK_1_REGION_START;
**// Erase Bank0
update_status.status_code = DFU_BANK_0_ERASED;
bootloader_dfu_update_process(update_status);**
....
}
static uint32_t dfu_activate_app(void) {
uint32_t err_code;
// Erase BANK 0.
err_code = pstorage_raw_clear(&m_storage_handle_app, m_start_packet.app_image_size);
APP_ERROR_CHECK(err_code);
err_code = pstorage_raw_store(&m_storage_handle_app,
(uint8_t *)m_storage_handle_swap.block_id,
m_start_packet.app_image_size,
0);
if (err_code == NRF_SUCCESS)
{
dfu_update_status_t update_status;
update_status.status_code = DFU_UPDATE_APP_COMPLETE;
update_status.app_crc = m_image_crc;
update_status.app_size = m_start_packet.app_image_size;
bootloader_dfu_update_process(update_status);
}
...
}
After interviewing the hex, we can confirm that:
- bootloader is not broken
- 0x3fc00 is 0x00000001(which means BANK_VALID_APP, and bootloader_settings_save has changed the app flag from INVALID to VALID)
- application is successfully downloaded to bank 1
- the upper part(maybe 10~99 percent) of bank 0 is the same with bank 1, but the remaining part is 0xff(which means pstorage_raw_clear works)
Now we can conclude that something goes wrong when copy from bank 1 to bank 0. According to the bug reports from our customer, 20% of 51822 failed in dfu_activate_app.
We can decrease the percentage of failure by adding a delay of 2 seconds before the Android code send "validate and reset" command.
void add_delay_before_validate_reset(void) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
writeOpCode(gatt, controlPointCharacteristic, OP_CODE_ACTIVATE_AND_RESET);
sendLogBroadcast(Level.APPLICATION, "Activate and Reset request sent");
}
That delay can decrease the failure to 5%, do you have any other way to oversome this issue. Please help.