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

DFU Bootloader feature requests for SDK 16

The changes to the dfu bootloader in sdk 15 are great, particularly the support for the wdt. After moving over to the new bootloader, here are some features that would be helpful in a future release:


1.

Erase the free flash area / cache that was used to temporarily store the new fw images. The scenario I have is I have a dfu bootloader, app, sd and an app data region present. The app data region is used for settings that are preserved across dfu updates as usual. There is a reasonable amount of free space left so its still possible to do dual bank app updates. But all that free space is also used to store sensor data, which is synced before a dfu, so that space can be used for dfu images. But when the dfu is done (sd, bootloader or app), that space is now trashed whereas for a new factory image its all erased and my app has no way of knowing its been trashed by a dfu. I can see two ways to fix this, one is for the app to get a reliable notification on startup that a dfu has occured (probably in the bootloader settings page that the bootloader sets and the app clears when its done with what it needs to do). Another way is for the bootloader to always just erase that area when a valid app starts up for the first time after a dfu of any type. (it still would be handy though for the app to get a reliable notification that a dfu has happened)

I have implemented the later by adding an 'is_clean' variable to the end of nrf_dfu_settings_t (so you dont interact badly with nrfutil and others) and set the value to zero at the end of nrf_utils::nrf_dfu_cache_prepare. I wrote a small function to erase the free area and reset the is_clean flag (guarded by a check when the flag is zero and a valid app image is in bank 0), and called it from nrf_bootloader_fw_activation::nrf_bootloader_fw_activate (placed before the return in the case statement, and also later on by 'if ret_val == NRF_SUCCESS')

2.

Debugging an app with the bootloader present. Right now, if you flash a bootloader and an app, then when you later try to compile and debug the app, a new image is downloaded, the board is reset and the bootloader will fail the crc check and you cant debug the app (you are now stuck in the bootloader). I just added a preprocessor directive to the bootloader project file and added it to nrf_bootloader::crc_on_valid_app_required so that it returns false when the flag is defined. Now I can have a dfu bootloader and develop and debug my app, and still have dfu working later if needed.

3.

Merge RTT output from the bootloader and app into one session. Previsouly discussed in this thread.
devzone.nordicsemi.com/.../easy-way-to-merge-bootloader-and-application-rtt-output

4.

Move APP_ADV_INTERVAL to sdk_config and not hard coded in nrf_dfu_ble.c

Parents
  • Hi,

    Thanks for the feedback. It has been delivered to the SDK team.

    The first suggestion will take some discussion, but I suspect it's not general enough that we would want to add this complexity to the already complex bootloader.

    The second suggestion is a known issue without any obvious correct answer. Customer and Nordic Employees generally do stuff like what you did or just develop the app without the bootloader present. We are a bit scared to add flags for overriding security features since experience tells us that someone will end up shipping with the flag enabled and having devices end up bricked somehow.

    The third suggestion is new to me, so I will have to look at it later on when I get around to it.

    The fourth suggestion is really good, and we should have done that from the start. Good catch.

    Best regards,
    Rune Holmgren

Reply
  • Hi,

    Thanks for the feedback. It has been delivered to the SDK team.

    The first suggestion will take some discussion, but I suspect it's not general enough that we would want to add this complexity to the already complex bootloader.

    The second suggestion is a known issue without any obvious correct answer. Customer and Nordic Employees generally do stuff like what you did or just develop the app without the bootloader present. We are a bit scared to add flags for overriding security features since experience tells us that someone will end up shipping with the flag enabled and having devices end up bricked somehow.

    The third suggestion is new to me, so I will have to look at it later on when I get around to it.

    The fourth suggestion is really good, and we should have done that from the start. Good catch.

    Best regards,
    Rune Holmgren

Children
  • Hello, I would like to make another request:

    Add an SVCI call to get the bootloader version (from DFU settings) from the main application. 

  • For development purposes, I usually have a feature in the app to update the bootloader settings to disable the crc check. Once the application disables the crc check, firmware can be flashed with the debugger without the bootloader causing a problem. 

  • To get the bootloader version from the main application, I added a little bit of data to the bootloader just after the vector table:

    // Put bootloader version information immediately following vector table.
    #pragma location=".intvec"
    const bootloader_rom_info_t bootloader_rom_info =
    {
      .magic = BOOTLOADER_INFO_MAGIC,
      .info = 
      {
        .version = (FIRMWARE_VERSION_MAJOR << 16) | (FIRMWARE_VERSION_MINOR << 8)
      }
    };
    

    That's for IAR, but similar should work for GCC or other toolchains. Then in my application I use:

      uint32_t bootloaderaddr;
      const bootloader_rom_info_t *bri;
      
      gd_bootloader_info.version = 0;
      
      bootloaderaddr = NRF_UICR->NRFFW[0];
      if ((bootloaderaddr == 0) || (bootloaderaddr >= 0x80000))
        return;
      
      bri = (bootloader_rom_info_t *)(bootloaderaddr + 0x200);
      if (bri->magic != BOOTLOADER_INFO_MAGIC)
        return;
    

    That gets me the firmware version I defined in the bootloader source code, which (if I screw up) could be different than the version number in the DFU package, but in general it's what I need.

Related