Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

How reliable is buttonless DFU, as well as can't go into dfu bootloader with button?

I've implemented a buttonless DFU with bonds, as well as a button-based DFU. These are in separate branches, but ultimately for my project, I want both ways integrated. However I can't go into the bootloader with both methods in my project. I have some questions below:

My questions are:

  • How reliable is the buttonless DFU?
    On the tutorial "nRF5 SDK v17.1.0 Secure DFU Hands-on Tutorial",
    it mentions at the bottom "It is important if at all possible, to provide a fail-safe for the DFU process if the buttonless process becomes inoperative, usually via a programming mistake in the application code. A coding mistake that breaks the buttonless process will render the device unable to be updated".
    nRF5 SDK v17.1.0 Secure DFU Hands-on Tutorial

    The reason for having both a button-based approach and a buttonless approach is based on this statement, which makes sense if the device can't do a DFU then it can be useless. I assume this mainly comes from a lack of testing, before doing a DFU out to all devices in the field. But providing that the tests pass, what are the chances that the service itself stops working?
  • It makes sense to have both methods, with the button-based way as a backup. The problem is, this way isn't encrypted. I've seen a few posts about how to add encryption manually, but it's a bit more work that I don't have time to do. I've already tested buttonless DFU with bonds, and this works with encrypting the DFU process as the bond is kept. How can I keep bonds when going into the bootloader to do a DFU with a button-based approach?
  • I've tried to merge both my branches that contain a button-based DFU and a buttonless DFU. The buttonless DFU works, but I can't go into the bootloader with the button-based method. I've had this problem before when I didn't want the do a DFU with buttonless, by clearing NRF_SDH_BLE_SERVICE_CHANGED and NRF_DFU_BLE_REQUIRES_BONDS in the bootloader SDK_Config. I'm not sure why this doesn't work, as my device resets, but just doesn't go into the bootloader. To go into DFU I manually do it by writing to the GPREGRET.

    void enter_dfu_mode(void) {
      static uint32_t gpregret_reg;
    
      ret_code_t err_code;
    
      err_code = sd_power_gpregret_get(0, &gpregret_reg);
      VERIFY_SUCCESS(err_code);
    
      gpregret_reg |= BOOTLOADER_DFU_START;
      err_code = sd_power_gpregret_set(0, gpregret_reg);
      VERIFY_SUCCESS(err_code);
    
      err_code = sd_power_gpregret_get(0, &gpregret_reg);
      VERIFY_SUCCESS(err_code);
    
      sd_nvic_SystemReset();
    }

 

Ultimately what I would want is to have both methods, but keep the bonds despite either method. By keeping the bonds, I'd assume that both methods would encrypt the DFU process.

Parents
  • Hi Jerome,

    How reliable is the buttonless DFU?
    On the tutorial "nRF5 SDK v17.1.0 Secure DFU Hands-on Tutorial",
    it mentions at the bottom "It is important if at all possible, to provide a fail-safe for the DFU process if the buttonless process becomes inoperative, usually via a programming mistake in the application code. A coding mistake that breaks the buttonless process will render the device unable to be updated".
    nRF5 SDK v17.1.0 Secure DFU Hands-on Tutorial

    The reason for having both a button-based approach and a buttonless approach is based on this statement, which makes sense if the device can't do a DFU then it can be useless. I assume this mainly comes from a lack of testing, before doing a DFU out to all devices in the field. But providing that the tests pass, what are the chances that the service itself stops working?

    DFU over BLE is quite reliable. We rarely see report of devices being bricked due to a DFU reason. Among the ones I have seen, the situations could have been prevented with enough test cases. But then again, a fallback recovery method would have saved a lot of effort and cost in such cases, so it's always a good idea to have it. But all of this are things you have already thought of.


    How can I keep bonds when going into the bootloader to do a DFU with a button-based approach?

    As you can see in L1157-L1170 of nrf_dfu_ble.c, the bonds will be loaded if NRF_DFU_BLE_REQUIRES_BONDS.

    Have you tried with this configuration enabled?

    Hieu

  • Yes, this is enabled in the bootloader code as it's not greyed out.


    As well as in the SDK_CONFIG file it's enabled

  • Hi Jerome,

    I just want to let you know that I am still around. As a next step, I think I will have to try setting up a project myself, and with us being understaffed, it has been a little difficult to schedule a big block of time for that.

    I appreciate your patience thus far. I will try to get to it as soon as I can.

    Hieu

Reply Children
  • Ok, great. I'm going to keep testing on my end, but I am running out of reasons why. I've created a new project based on the gls example, and used the nRF52840 DK instead of my custom PCB which has an nRF52833. Even with this, and a fresh install of the SDK I am running into the same problem. Although when I try to debug I can't see debug data from the bootloader code. The normal application runs, and I'm in debug mode. I trigger the DFU process, by pressing a button. It calls the enter_dfu_mode(), I created in the first post. But I can't see where in the DFU process it's failing from the bootloader code. But I assume it's the same issue.

  • I don't actually use the bootloader with bonds, but the way I understood it, the buttonless DFU will only forward the peer data of the peer that actually initiated the (buttonless) DFU.

    I'm thinking if there is a way that I can call one of the underlying DFU service functions that will set the peer data up, before rebooting into the bootloader,

    I think the function you need is nrf_dfu_set_peer_data(). If you look up in ble_dfu_bonded.c the functions retrieve_peer_data() and enter_bootloader() I think those are the ones you'd need to replicate.

  • I think  is right! From Buttonless Secure DFU Service documentation:

    When the Buttonless Secure DFU Service enters the bootloader, the Buttonless Secure DFU Service forwards the current peer data from the Peer Manager data storage to the Secure DFU bootloader. This data is stored in flash, and is activated when the device enters DFU mode.

    Thanks a lot, mrono! You stopped me from heading into an incorrect approach.

    This means that if we want the button-triggered DFU operation to have access to the peer data, then we will need to setup the Peer Manager on the bootloader as well.

    This leads me to rethink about this DFU setup from a different angle.

    The point of the bond requirement for performing DFU is to protect against unauthorized update.

    With the button-trigger method, the person already has access to the device. For many use cases, this often also means that the person can have the authority to update.

    Is that the case with your product, Jerome?

  • This means that if we want the button-triggered DFU operation to have access to the peer data, then we will need to setup the Peer Manager on the bootloader as well.

    If you have several peers then yes, something like that probably needs to be done. But if there is only one bonded peer, then I think it should be sufficient to simply always forward that data when entering the bootloader.

  • So with my product, I have standard users that operate on a "user service", which is in just works mode (pairing/no bonding). Master users who can access the "master service", need to pair and bond (passkey/mitm protected). There can be up to 10 masters/bonds. Only the masters/bonds can trigger the firmware update, as it should be encrypted.

    The button triggering the DFU process is not a physical button, but a UART command from another processor, that only will be sent on the master service, which in turn calls the enter_dfu_mode() function.

Related