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

DFU Between NRF's

Hi, 

I have central based on the 840 and a Peripheral on the 833 , I Need to ability to upgrade the peripheral version from the central. 

I know that there is no example for doing DFU between NRF's.

My Idea is : 

1. Use NUS to transfer the file from 840 to 833

2. Store the image on QSPI flash on 833

3. From 833, run DFU from QSPI ( based on the SDK example ). 

I'd like to get your thought and\or other options 

Ran

Parents
  • Hello,

    We don't have anything doing exactly this, but there are a few approaches to this issue, but first, some few pointers on how the DFU and bootloader in the SDK works:

    The bootloader is a passive bootloader, which means that after you go to DFU mode, it will passively wait for something to send the DFU packets to it, either via BLE or Serial. Depending on whether it is a single or dual bootloader, it will delete the current application, and only use the bootloader project to receive this image. What you describe sounds like an active bootloader, because you would have to actively fetch the new application image from QSPI from the bootloader (lets assume that the image is already transferred over BLE (NUS), and stored in the QSPI). That would require you to add this to your bootloader project.

    If you have room for two applications in flash, so that you can store the new application image in flash, and run the update from the bootloader. This almost only requires a call to a single function from the bootloader.

    I assume your 840 can't just run the nRF Connect for Desktop firmware, which you can use to update the 833?

    BR,

    Edvin

  • Edvin Thanks. 

    I came across an example called "DFUMaster_SPI" and I thought it was doing just that : load an image from QSPI\SPI and perform update - BUT now I understand that this is for the "Sending" side ? 

    As for : 

    "If you have room for two applications in flash, so that you can store the new application image in flash.."

    You are suggesting to use "Dual Boot" ? I will program the new image to Peripheral Flash ( received over NUS ) and then launch my boot loader that will activate this image ?  

    If so - I'd like to look deeper into this option if you would 

    And no..can't use any desktop or mobile to update the peripheral. the "real" usage is a "Central" connected to 10 "peripherals" , similar to the aggregator example.

Reply
  • Edvin Thanks. 

    I came across an example called "DFUMaster_SPI" and I thought it was doing just that : load an image from QSPI\SPI and perform update - BUT now I understand that this is for the "Sending" side ? 

    As for : 

    "If you have room for two applications in flash, so that you can store the new application image in flash.."

    You are suggesting to use "Dual Boot" ? I will program the new image to Peripheral Flash ( received over NUS ) and then launch my boot loader that will activate this image ?  

    If so - I'd like to look deeper into this option if you would 

    And no..can't use any desktop or mobile to update the peripheral. the "real" usage is a "Central" connected to 10 "peripherals" , similar to the aggregator example.

Children
  • ran said:
    And no..can't use any desktop or mobile to update the peripheral. the "real" usage is a "Central" connected to 10 "peripherals" , similar to the aggregator example.

     I see. I just wanted to check. I assume you have thought of this, but you need some way to upload the firmware image to the central as well. But if it has to do other things than only the DFU, then nRF Connect will probably not work in this case.

     

    ran said:
    I came across an example called "DFUMaster_SPI" and I thought it was doing just that : load an image from QSPI\SPI and perform update - BUT now I understand that this is for the "Sending" side ? 

     That is correct. The DFU_Master_SPI is the sender side of the DFU, when the "slave" would run an unmodified bootloader, just waiting for the packets to be transmitted over serial.

    ran said:
    If so - I'd like to look deeper into this option if you would 

     Yes. This is one approach of background DFU. What you would have to do is to generate the image (the zip file) using nrfutil, and then transfer it via your applications, and give it a signal when it is complete. What you want to do then is to tell the DFU target to reset (in order to run the bootloader), and tell it that it has something to do, other than just starting the current application.

    For this, you should look around in the bootloader project and get familiar with how it works out of the box.

    I'll refer the serial bootloader found in SDK16.0.0\examples\dfu\secure_bootloader\pca10100_s140_ble:

    The common way to tell the bootloader to stay in DFU mode is to hold a button on startup. The flow is:

    main() -> nrf_bootloader_init() -> dfu_enter_check() -> 

    if (NRF_BL_DFU_ENTER_METHOD_BUTTON &&
           (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0))
        {
            NRF_LOG_DEBUG("DFU mode requested via button.");
            return true;
        }

    Where NRF_BL_DFU_ENTER_METHOD_BUTTON and NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN are defined in sdk_config.h.

    If you want to enter DFU without physical interaction, you should use the:

        if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
           (nrf_power_gpregret_get() & BOOTLOADER_DFU_START))
        {
            NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
            return true;
        }

    So you must write BOOTLOADER_DFU_START (=0xB1) to the gpregret register from your application before you reset.

    A typical mistake when doing this is calling:

    nrf_power_gpregret_set(0xB1);
    NVIC_SystemReset();

    but this may not have time to actually write to the register before resetting. Also, if you use this register for something you may want to read the value, and adding 0xB1 to that:

    uint32_t value = nrf_power_gpregret_get();
    value = value & 0xB1;
    nrf_power_gpregret_set(value);
    while ((nrf_power_gpregret_get() & 0xB1) == 0)
    {
        // Wait.
    }
    NVIC_SystemReset();

    Now, after you have been able to tell the bootloader that it has some work to do, let's look into how the bootloader usually works:

    Usually, if dfu_enter (from dfu_enter_check()) is true, it will initialize the transport layer(s) in nrf_dfu_init() (in nrf_dfu.c) -> nrf_dfu_transports_init().

    When an image is transferred, the serial/ble protocol for the bootloader says that the master/sender should send the execute command, which will trigger the event NRF_DFU_OP_OBJECT_EXECUTE in nrf_dfu_req_handler.c -> nrf_dfu_data_req().

    What this will do is to validate the signature of the packet, and do some bootloader settings stuff, before it will reset the bootloader project once more. This time it will enter:

    main() -> nrf_bootloader_init() -> nrf_bootloader_fw_activate(), which will start the normal procedure, moving the new application to the correct place, signing the application, and reset, so that the new application will start.

    I suggest you start experimenting with this information. There is something called NRF_BL_DFU_ALLOW_UPDATE_FROM_APP. I haven't used it before, but that may also be something that you can use directly to update to an application received from the current application.

    BR,

    Edvin

Related