DFU bootloader - my application code

Hi

using NRF5_SDK 17.0.2

I'm trying to better understand the DFU process, currently have a large number of questions. But mainly i would like to better understand the generation & handling of the bootloader file itself.

I keep seeing references to the booloader examples as a means to get a hold of a bootloader binarys, this seems a little weird, is there not a master location from which I can download a suitable bootloader binary?

it is unclear from the documentation if i have to manually compile some code to produce the bootloader binary? I keep seeing references to "build the bootloader example", surely the example code isn't required for bespoke applications?

I am confused by the source code for the DFU example, it seems to reference events generated by the bootloader which are handled through a registered observer, similar to how the softdevice observers operate, so what is the purpose of this example code? Is it purely to demonstrate the bootloader (the binary for which i must find elsewhere?) Or is it to actually generate a bootloader binary? - The example i'm looking at is below.

Where to do I modify the bootloader settings (such as altering the pins that are turned on (LED's) when the device enters DFU mode? Can this be done before runtime? Should I do this from my application code? If so this seems inconvenient as this requires me to implement code in my firmware for to handle first boot scenarios, or Repeating code on startup that need only be done once in the products life...

How do i generate the bootloader settings section of memory, is there a default version of this that I should flash to the chip along with the bootloader? Is there a published format for this?

There seems to be plenty of documentation about how to carry out a firmware update using the bootloader & DFU mode, but nothing overly detailed when it comes to the initial programming process for the device? How are initial values for HW & FW versions embedded? Where does the initial MBR come from? Do I have to generate these? Is there a zip file i can generate, comparable to the one used for DFU's that i can use for the initial flashing of a product?

/**@brief Function for application main entry. */
int main(void)
{
    uint32_t ret_val;

    // Must happen before flash protection is applied, since it edits a protected page.
    nrf_bootloader_mbr_addrs_populate();

    // Protect MBR and bootloader code from being overwritten.
    ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE);
    APP_ERROR_CHECK(ret_val);
    ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, BOOTLOADER_SIZE);
    APP_ERROR_CHECK(ret_val);

    (void) NRF_LOG_INIT(nrf_bootloader_dfu_timer_counter_get);
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("Inside main");

    ret_val = nrf_bootloader_init(dfu_observer);
    APP_ERROR_CHECK(ret_val);

    NRF_LOG_FLUSH();

    NRF_LOG_ERROR("After main, should never be reached.");
    NRF_LOG_FLUSH();

    APP_ERROR_CHECK_BOOL(false);
}

/**
 * @}
 */

I've read through all the available documentation I can find on the infocentre. Think i'm in need of a clearer explanation on where the bootloaders can be found/generated/packaged, whatever.

Thanks,

Sean

Parents
  • Hello Sean,

    The SDK bootloader is meant to be built from source, which I think makes sense for this bootloader as there are several things you either must, or may want to change that are specific to your device. The settings page could probably have been expanded to include bootloader configuration settings in addition to the status info currently contained in the page (nrf_dfu_settings_t), but I don't think it would have been possible to cover everything with it.

    There are pre-compiled binaries available in the SDK, but these are meant for testing purposes as indicated in the example documentation: DFU bootloader examples.

    I am confused by the source code for the DFU example, it seems to reference events generated by the bootloader which are handled through a registered observer, similar to how the softdevice observers operate, so what is the purpose of this example code? Is it purely to demonstrate the bootloader (the binary for which i must find elsewhere?) Or is it to actually generate a bootloader binary? - The example i'm looking at is below.

    The examples show the actual bootloader implementation with various board and transport configurations. Some enable the BLE DFU transport layer to support over-the-air DFU while others use USB or UART for serial DFU. If you for instance want to do support DFU over BLE, it is often sufficient to only change out the public key and change the pin assignments (Using the SDK with other boards).

    The observer events are signaled from the registered transport layer(s) when the bootloader enters DFU mode.

    Where to do I modify the bootloader settings (such as altering the pins that are turned on (LED's) when the device enters DFU mode? Can this be done before runtime? Should I do this from my application code? If so this seems inconvenient as this requires me to implement code in my firmware for to handle first boot scenarios, or Repeating code on startup that need only be done once in the products life...

    The pin assignments are changed by building the bootloader with a custom board file. Please see Using the SDK with other boards for details.

    How do i generate the bootloader settings section of memory, is there a default version of this that I should flash to the chip along with the bootloader? Is there a published format for this?

    Yes, the bootloader project will define this section in its linker script. Here is what the default memory layout looks like: Memory layout.

    There seems to be plenty of documentation about how to carry out a firmware update using the bootloader & DFU mode, but nothing overly detailed when it comes to the initial programming process for the device? How are initial values for HW & FW versions embedded? Where does the initial MBR come from? Do I have to generate these?

    For production or initial programming, you will typically prepare a single hex file by merging the Softdevice(or mbr) hex file with the application, bootloader, and bootloader settings page where the settings page is generated with the nrfutil tool: Generating and displaying bootloader settings.

    Let me know if you have additional questions or comments.

    Best regards,

    Vidar

  • Hi Vidar,

    Thanks a lot for coming back to me.

    This does clear up some of my earlier confusion, although if i'm honest i'm still somewhat in a dark about a great deal of how the bootloader operates, as most of the documentation seems to be example based.

    You say the bootloader must be compiled from source, where is this source code? Is this the main.c file i quoted from in my original post?

    The settings page could probably have been expanded to include bootloader configuration settings in addition to the status info currently contained in the page

    Are you saying this because presumably some of the configuration for the bootloader is altered/configured in the source, which is then compiled into a custom/bespoke bootloader?

    Yes, the bootloader project will define this section in its linker script. Here is what the default memory layout looks like: Memory layout.

    I think you've misunderstood here: I'm asking specifically for a published format of the bootloader settings. This firmware is to be used on a commercially available product, meaning bespoke production systems are being developed. Meaning we may wish to generate our own bootloader settings page, using our own tools? Is there a published format for this section of memory? I want to know how the nrfutil generates this section of memory. Previous CPU's i've worked with have a properly published format for sections of memory like this, so that users can manually interact with the memory & modify it themselves. Instead of having to use the CPU manufacturers tools.

    Thanks,

    Sean

  • You say the bootloader must be compiled from source, where is this source code? Is this the main.c file i quoted from in my original post?

    It is the secure bootloader example that you referred to in the opening post. The main.c looks like it is from that example. It it called "example", but really that is the supported bootloader.

    If you open the example project you'll find that there is a file called sdk_config.h that has lots of configuration options. Use that file to configure the bootloader according to your needs.

    Generally start with the example and its documentation. That should give you a clearer overview of what should be configured and how.

    Oh, and the "bootloader settings" -thing is a slightly different matter. It is a struct in flash that the bootloader itself uses to determine things like the version, size and crc of the currently installed application. You only need to generate a compatible settings page once, for the initial flashing of the device in production. You should not need to customise the bootloader settings page.

  • Hi mrono

    Thanks for the reply, the "example" naming, definitely added an element of confusion, it seemed odd that the bootloader itself would be in the examples folder. Thanks for clearing that up.

    With regards to the bootloader settings pages. I've seen references uggesting that i can store data within the bootloader settings to be retained through firmware updates. (such as a serial number etc).

    I know the settings page only needs flashing once in production, but i'm still going to ask, is there not a published format for this somewhere? An exact, byte for byte, published format of the structure that is writen into flash?

    As i mentioned previously, we may decide to make bespoke tools in future for in-house use, for example, we may wish to generate our own merged binary, which would entail embedding version details etc into a bootloader settings page. Yes, i am well aware i can use the nrfutil to do this.... But i'm still asking regardless. :)

  • is there not a published format for this somewhere?

    It took a bit of digging, but the format is documented here

    I've seen references uggesting that i can store data within the bootloader settings to be retained through firmware updates. (such as a serial number etc).

    Hmm, I guess you could. But I'm not sure if that is the best location. For a small amount of data the UICR could be used. Or you could reserve a separate page of flash for this data. One configuration option for the bootloader is specifically to tell it to keep away from certain flash pages.

  • Hi Sean,

    SeanHowsonTB said:
    about a great deal of how the bootloader operates, as most of the documentation seems to be example based.

    I am not sure if you have seen it already, but details about how the bootloader operates should be covered by the "Bootloader and DFU modules" chapter of the documentation.

    Are you wondering what responsibilities the bootloader has, or is it more that you want to better understand specific operations, like how it validates and boots the main application, or handles firmware updates?

    SeanHowsonTB said:
    You say the bootloader must be compiled from source, where is this source code? Is this the main.c file i quoted from in my original post?

    The quoted main.c file is the common entry point for our bootloader projects, but the bootloader comes with many more dependencies which will be defined by the project files (Or the Makefiles if you are not using one of the IDEs).  

    As an example, lets say you use Segger embedded Studio (SES) and want to build a bootloader for the nRF52840 DK with support for DFU over BLE. Then you can select either the secure_bootloader_ble_s140_pca10056.emProject or the secure_bootloader_ble_s140_pca10056_debug.emProject project in /nRF5_SDK_17.1.0_ddde560/examples/dfu/secure_bootloader to use as a starting point. The main difference between the two is that the latter has logging over RTT enabled default and slightly more relaxed security requirements when it comes to DFU (you can skip version validation) to make testing during development easier.

    SeanHowsonTB said:
    Are you saying this because presumably some of the configuration for the bootloader is altered/configured in the source, which is then compiled into a custom/bespoke bootloader?

    Configuration settings have to be configured in the sdk_config.h header or directly in the source files before building the bootloader.

    SeanHowsonTB said:
    I think you've misunderstood here: I'm asking specifically for a published format of the bootloader settings.

    "bootloader settings" is a full flash page reserved to the bootloader to keep status information about installed FW images (version number, checksum, etc) and DFU states. And it is not meant to be used for anything else. The format of this page is defined by the nrf_dfu_settings_t struct.

    Manufacturer and other device specific configurations should be stored elsewhere in flash. You can allocate a new flash page for this purpose, or use the app data region shown in the memory layout a pointed to earlier. You also have the UICR section that is suitable for non-volatile storage of one-time configurations such as serial numbers, etc. 

    SeanHowsonTB said:
    Previous CPU's i've worked with have a properly published format for sections of memory like this, so that users can manually interact with the memory & modify it themselves

    Could you maybe describe your use-case? I'm not sure I understand exactly what information you are looking for. The sections are defined by the linker scripts you use in your builds and you are free to edit those and define new sections to be placed in flash.

    Best regards,

    Vidar

Reply
  • Hi Sean,

    SeanHowsonTB said:
    about a great deal of how the bootloader operates, as most of the documentation seems to be example based.

    I am not sure if you have seen it already, but details about how the bootloader operates should be covered by the "Bootloader and DFU modules" chapter of the documentation.

    Are you wondering what responsibilities the bootloader has, or is it more that you want to better understand specific operations, like how it validates and boots the main application, or handles firmware updates?

    SeanHowsonTB said:
    You say the bootloader must be compiled from source, where is this source code? Is this the main.c file i quoted from in my original post?

    The quoted main.c file is the common entry point for our bootloader projects, but the bootloader comes with many more dependencies which will be defined by the project files (Or the Makefiles if you are not using one of the IDEs).  

    As an example, lets say you use Segger embedded Studio (SES) and want to build a bootloader for the nRF52840 DK with support for DFU over BLE. Then you can select either the secure_bootloader_ble_s140_pca10056.emProject or the secure_bootloader_ble_s140_pca10056_debug.emProject project in /nRF5_SDK_17.1.0_ddde560/examples/dfu/secure_bootloader to use as a starting point. The main difference between the two is that the latter has logging over RTT enabled default and slightly more relaxed security requirements when it comes to DFU (you can skip version validation) to make testing during development easier.

    SeanHowsonTB said:
    Are you saying this because presumably some of the configuration for the bootloader is altered/configured in the source, which is then compiled into a custom/bespoke bootloader?

    Configuration settings have to be configured in the sdk_config.h header or directly in the source files before building the bootloader.

    SeanHowsonTB said:
    I think you've misunderstood here: I'm asking specifically for a published format of the bootloader settings.

    "bootloader settings" is a full flash page reserved to the bootloader to keep status information about installed FW images (version number, checksum, etc) and DFU states. And it is not meant to be used for anything else. The format of this page is defined by the nrf_dfu_settings_t struct.

    Manufacturer and other device specific configurations should be stored elsewhere in flash. You can allocate a new flash page for this purpose, or use the app data region shown in the memory layout a pointed to earlier. You also have the UICR section that is suitable for non-volatile storage of one-time configurations such as serial numbers, etc. 

    SeanHowsonTB said:
    Previous CPU's i've worked with have a properly published format for sections of memory like this, so that users can manually interact with the memory & modify it themselves

    Could you maybe describe your use-case? I'm not sure I understand exactly what information you are looking for. The sections are defined by the linker scripts you use in your builds and you are free to edit those and define new sections to be placed in flash.

    Best regards,

    Vidar

Children
No Data
Related