Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

simplified Dual bank DFU

Hi,

I'm trying to do (customized / simplified) dual bank DFU on NRF52832 as simple as possible, without any complicated checks.

Assume I succeeded into storing the new firmware in a free Flash bank (bank1, e.g. @ 0x50000), I need to know which functions should be used to to move the new SW from bank1 to bank0, or directly boot from bank1.

Assuming my current application runs at address 0x23000 after SD132, If I try to use pstorage functions to move the image from bank1 to this address, the chip hangs as soon as I start with the clear flash page command (which is successfully executed after checking Flash contents with nrfjprog).

- Is that normal? I thought the application is running in RAM and not affected if application area is erased in flash without doing a reset. Is there any way to  solve this?

- If not (& I'm not using a DFU bootloader), is it possible to just set the application start address in UICR to the start address of bank1 (0x50000) to boot new SW?

from UICR dump I see the 0x00023000 is stored:

:020000041000EA
:1010000000300200FFFFFFFFFFFFFFFFFFFFFFFFBA

- If all this is not possible, is it possible to just use the code snippet in  nrf_dfu_postvalidate() in dfu_req_handling.c :

 switch (p_init->type)
        {
            case DFU_FW_TYPE_APPLICATION:
                p_bank->bank_code = NRF_DFU_BANK_VALID_APP;
                // If this update is in bank 1, invalidate bank 0 before starting copy routine.
                if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1)
                {
                    NRF_LOG_INFO("Invalidating old application in bank 0.");
                    s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_INVALID;
                }
                break;

p_bank->bank_code = NRF_DFU_BANK_INVALID;

        // Calculate CRC32 for image
        p_bank->image_crc = 0;
        p_bank->image_size = 0;

// Set the progress to zero and remove the last command
    memset(&s_dfu_settings.progress, 0, sizeof(dfu_progress_t));
    memset(s_dfu_settings.init_command, 0xFF, DFU_SIGNED_COMMAND_SIZE);
    s_dfu_settings.write_offset = 0;

    // Store the settings to flash and reset after that
    m_dfu_last_settings_write_started = true;
    if (nrf_dfu_settings_write(on_dfu_complete) != NRF_SUCCESS)
    {
        res_code = NRF_DFU_RES_CODE_OPERATION_FAILED;
    }

Thx & KR

Parents
  • Is that normal? I thought the application is running in RAM and not affected if application area is erased in flash without doing a reset. Is there any way to  solve this?

    You can run from RAM, but you typically don't. Most applications are running directly from flash. (Unless you have explicitly done something to ensure the application is running from RAM). I'll come back to how to solve it after all the questions.

    is it possible to just set the application start address in UICR to the start address of bank1 (0x50000) to boot new SW?

    No, running firmware is not allowed to update the UICR. Using a debugger is the only way to change it, which means that in production the UICR values will be final.

    If all this is not possible, is it possible to just use the code snippet in  nrf_dfu_postvalidate() in dfu_req_handling.c

    This snippet only updates the state stored in the DFU settings page. This is good, but your use case is so special it probably requires a new implementation.

    How to solve the issue of copying new firmware to the correct location in flash

    The first thing I would like you to do is to start considering your "application" to be more like a bootloader in the context of performing DFU. The DFU bootloader in the SDK can very easily update the application because the application is not running when the copy routines are performed. The DFU bootloader is also able to update itself, and this is really what you are trying to do. You should probably have a look at how this is done in "nrf_dfu_bl_continue" in nrf_dfu_utils in SDK 14.2.0. The bootloader does not perform the copy operation itself because its hard for the piece of firmware to alter itself. Instead, it uses the MBR. The MBR is a small section of code which will run right after the device is powered up, it supports a small set of powerful features. Some of them, like SD_MBR_COMMAND_COPY_BL, are too specific to the way the nRF5 SDK DFU bootloader works. Luckily there is SD_MBR_COMMAND_COPY_SD which is an MBR command telling the MBR to copy a number of words from one address to another. When you want your application to copy new firmware from bank 1 to bank 0 you should use the SD_MBR_COMMAND_COPY_SD MBR command with the bank1's address as source, bank0's address as destination, and the firmware's size in 32-bit words as size.

    Best regards,
    Rune Holmgren

Reply
  • Is that normal? I thought the application is running in RAM and not affected if application area is erased in flash without doing a reset. Is there any way to  solve this?

    You can run from RAM, but you typically don't. Most applications are running directly from flash. (Unless you have explicitly done something to ensure the application is running from RAM). I'll come back to how to solve it after all the questions.

    is it possible to just set the application start address in UICR to the start address of bank1 (0x50000) to boot new SW?

    No, running firmware is not allowed to update the UICR. Using a debugger is the only way to change it, which means that in production the UICR values will be final.

    If all this is not possible, is it possible to just use the code snippet in  nrf_dfu_postvalidate() in dfu_req_handling.c

    This snippet only updates the state stored in the DFU settings page. This is good, but your use case is so special it probably requires a new implementation.

    How to solve the issue of copying new firmware to the correct location in flash

    The first thing I would like you to do is to start considering your "application" to be more like a bootloader in the context of performing DFU. The DFU bootloader in the SDK can very easily update the application because the application is not running when the copy routines are performed. The DFU bootloader is also able to update itself, and this is really what you are trying to do. You should probably have a look at how this is done in "nrf_dfu_bl_continue" in nrf_dfu_utils in SDK 14.2.0. The bootloader does not perform the copy operation itself because its hard for the piece of firmware to alter itself. Instead, it uses the MBR. The MBR is a small section of code which will run right after the device is powered up, it supports a small set of powerful features. Some of them, like SD_MBR_COMMAND_COPY_BL, are too specific to the way the nRF5 SDK DFU bootloader works. Luckily there is SD_MBR_COMMAND_COPY_SD which is an MBR command telling the MBR to copy a number of words from one address to another. When you want your application to copy new firmware from bank 1 to bank 0 you should use the SD_MBR_COMMAND_COPY_SD MBR command with the bank1's address as source, bank0's address as destination, and the firmware's size in 32-bit words as size.

    Best regards,
    Rune Holmgren

Children
No Data
Related