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?

Parents Reply
  • Ok. Can you see what part of settings_forbidden_parts_equal_to_backup that returns false? Look in nrf_dfu_settings.c from line 197. Try to debug through it to see why it fails. 

    Do you have any suspicion why this might fail? Are you using a public + private keyset? Are you trying to merge the BL settings page with your application before creating a DFU image with it?

    Best regards,

    Edvin

Children
  • NRF_DFU_SETTINGS_ALLOW_UPDATE_FROM_APP is set to true, therefore the first branch of settings_forbidden_parts_equal_to_backup is executed, leading to a call of settings_region_compare_to_backup() returning false, called with the following values:
    start_offset = 4
    end_offset = 36
    p_compare_addr = 0x2000c5d8 pointing to s_dfu_settings

    1) No idea why this fails
    2) Yes we use public / private keyset
    3) Not sure I understand your question.
    To generate the DFU image we do in sequence only the following:
    - compile the application and generate an .hex
    - Run nrfutil pkg generate on the .hex to generate a .zip file, providing the privatekey file
    - Run trigger_creator.py on the .zip file and the config.json file

  • Have you tried the non-background bootloader? Can you try it? Just to see whether you get the same issue there.

    Please follow this guide:

    https://devzone.nordicsemi.com/b/blog/posts/getting-started-with-nordics-secure-dfu-bootloader

    To be honest, I am not sure how the background bootloader works. I haven't tested it. But if you get a similar issue here, it would be easier to reproduce and pin point the issue.

    If the issue doesn't happen on the "normal" bootloader. Can you give me some hints on what you have done, so that I can try to reproduce it?

    BR,

    Edvin

  • Few further info out of debugging:


    In fact, even commenting out the lines I provided above, although the DFU process completes with a DFU_STATE_COMPLETED, the bootloader does not actually install the update.


    This is strange because:
    1) If we check the bootloader_settings information (at 0x7f000, reading the memory with the debugger (right after the DFU_STATE_COMPLETED and before the reset of the application to enter bootloader), the settings contain correctly an invalidated bank_0 code, and in bank_1 code a valid app code.
    2) At reset, this does not seem to be considered by the bootloader.

    For example, what we got right before reset:


    Bank 0
    image_size    uint32_t    93144   
    bank_code    uint32_t    0    

    Bank 1
    image_size    uint32_t    93148   
    bank_code    uint32_t    1   

    which looks fine for me, as indicates bank1 contains the new upgrade, however after reset, this is not installed, and actually in 0x7f000 we found only information on Bank0 (the original ones) and nothing in Bank1 info (all 0s)

  • Are you using the bootloader from the IoT SDK, or the BLE bootloader?

  • using the bootloader in components/libraries/bootloader/nrf_bootloader.c

Related