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

Background DFU update problem on NRF52832

We are attempting to replicate the background DFU process presented in the example DFU over TFTP.
Reference SDK that we are using is 15.2

What we do:

- We are trying to update only application code (no bootloader, no SD)
- Our application retrieves the firmware and stores it in a free area of the FLASH
- After storing the firwmare, we start the DFU procedure in the application, which looks like:

 APP_SCHED_INIT(IPRO_COMM_BACKGROUND_DFU_SCHED_MAX_EVENT_DATA_SIZE,
                   IPRO_COMM_BACKGROUND_DFU_SCHED_QUEUE_SIZE);

nrf_dfu_settings_init(true);
nrf_dfu_req_handler_init(dfu_observer);

background_dfu_state_init(&dfu_context);

background_dfu_handle_event(&dfu_context,
		BACKGROUND_DFU_EVENT_TRANSFER_COMPLETE);

// PARSE config JSON file and retrieve triggers, not shown

memset(&trigger, 0, sizeof(trigger));
trigger.init_length     = uint32_big_decode((const uint8_t*) &init_length);
trigger.init_crc        = uint32_big_decode((const uint8_t*) &init_crc);
trigger.image_length    = uint32_big_decode((const uint8_t*) &image_length);
trigger.image_crc       = uint32_big_decode((const uint8_t*) &image_crc);

if (background_dfu_validate_trigger(&dfu_context,
                                     (uint8_t *)&trigger, sizeof(trigger))) {

    if (!background_dfu_process_trigger(&dfu_context,
                                        (uint8_t *)&trigger, sizeof(trigger))) {

        // ERROR

    }
        
    if (dfu_context.dfu_state == BACKGROUND_DFU_IDLE) {

        return;

    }

} else { // ERROR }

while (! // RECEIVED BACKGROUND_DFU_DOWNLOAD_INIT_CMD event){
    app_sched_execute();
}

// Read flash and send 1 init block
background_dfu_process_block(&dfu_context, &block);

while (! // RECEIVED BACKGROUND_DFU_DOWNLOAD_FIRMWARE event){
    app_sched_execute();
}

// Read flash and send N firmware blocks 
while (...) {
    background_dfu_process_block(&dfu_context, &block);
}

while (! // RECEIVED NRF_DFU_EVT_DFU_COMPLETED event){
    app_sched_execute();
}

// RESET and enter bootloader

The main issue is that, if we don't comment out the following lines in the NRF SDK, the process does not end, and a DFU_STATE_FAILED is raised almost immediately after reading the init triggers. File nrf_dfu_settings.c, lines approximately 297-302.

if (NRF_DFU_SETTINGS_IN_APP && !settings_forbidden_parts_equal_to_backup((uint8_t *)&s_dfu_settings))
{
    NRF_LOG_WARNING("Settings write aborted since it tries writing to forbidden settings.");
    // Assuming NRF_DFU_SETTINGS_ALLOW_UPDATE_FROM_APP is configured the same as in bootloader.
    return NRF_ERROR_FORBIDDEN;
}
}

I am not really sure why our code is not working without commenting the above.
I'd like to understand whether this is an issue with the SDK, or (most probably) with our implementation?

  • Edvin, I actually managed to debug the bootloader right after reset.

    In brief:

    1) Right at bootloader start, the content of the bootloader settings page (0x7f000) looks OK to me:
    This is what I see

    crc = 333798234    
    settings_version = 1    
    app_version = 2    
    bootloader_version = 0    
    bank_layout = 0    
    bank_current = 1    
    bank_0    {...}    
        image_size = 85720    
        image_crc = 3998993418    
        bank_code = 0    
    bank_1  {...}    
        image_size = 85720    
        image_crc = 598733133    
        bank_code = 1    

    2) The page is unfortunately overwritten before being activated, because the function nrf_dfu_settings_init in nrf_bootloader_init detects that settings_forbidden_parts_equal_to_backup returns false.
    From what I can see this is comparing the first 32 bytes (offset by 4 bytes) of the bootloader_settings (0x7f000) page and the backup settings page (0x7e000), finding a difference (below what I have in the backup settings at 0x7e000)

    crc  =  863167636    
    settings_version = 1    
    app_version = 1    
    bootloader_version = 0    
    bank_layout = 0    
    bank_current = 0    
    bank_0       {...}    
        image_size = 85720    
        image_crc = 3998993418    
        bank_code = 1    
    bank_1    nrf_dfu_bank_t    {...}    
        image_size = 0    
        image_crc = 0    
        bank_code = 0    

    which clearly differs from what at 0x7fff, causing the bootloader settings page to be overwritten, and the update ignored. A warning is thrown "Restoring settings from backup since the app has tampered with the off-limit parts of the settings page."

    Why this happens, is still unclear to me.

  • Hello,

    I just spoke with one of our developers, and he told me that they have had a few issues with the TFTP DFU in SDK15.2.0. He suggested that you tested with SDK15.3.0 instead. He told me that there were several bug fixes, so it would be easier to start with SDK15.3.0 rather than porting the TFTP part only to SDK15.3.0.

    BR,

    Edvin

Related