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

Custom bootloader guidance

Hi Nordic

I have some questions regarding a custom bootloader we are about to implement into our product.

Information:
- We use NRF52832
- We have a custom board for our product
- We use the S132 softdevice
- We need a bootloader
- We use ESB as our main communication protocol and need this for application update (file tranfering in bootloader)
- We don't need a secure bootloader with crypto
- We don't need to update through BLE, if this complicates things significantly
- We don't need to update our softdevice, if this complicates things significantly
- We don't need to update our bootloader

Wishes:
- We would like a seperate project containing MBR, Softdevice and our bootloader
- When this project is flashed into the device, it should start to execute the bootloader.
It will of course check if an application is present and jump to this application if present.

- We would like a seperate project with our application
- If Release -> Output .hex file with right flash placement. (compared to the bootloader).
- If Debug -> Output .hex file which are able to start by it's own without bootloader

- We would like just to write to flash application space directly from the bootloader.

- Finally we need for production to be able to merge the two outputs with all components: MBR, SD, Bootloader and current application version.

Hope this make sense.

I am of course not asking for you to implement this, but I feel we need some guidance.
I don't think to my knowledge that the DFU is the right path for us to go, mainly because it looks too complicated for our needs, and it doens't have any examples for ESB custom bootloading.

I know there is a lot of documentation about the MBR, Softdevice and also the DFU.
But I also find it hard to find the specific details I need to get it started, as there are a lot of information that I don't think is relevant for our situation.

The examples I find are also specific for DFU usage, where I find it hard to get inspiration.
I would e.g like to see the differences of the bootloader library vs. the DFU.
Can I use only the bootloader and not the DFU mode, and how.

This are until now my best documents:
infocenter.nordicsemi.com/index.jsp
infocenter.nordicsemi.com/index.jsp

Some specific questions:
- How to I setup a bootloader project in Segger, which are able to startup directly into the bootloader?
- How to setup a segger project with the correct flash placement for use with a bootloader?
- How to jump from bootloader to the application?
- Will the UICR values be kept between bootloader and application, when not using the DFU?
- How would we write to the application flash from our bootloader? Using the fstorage or other lib?

Hope you have some suggestions for us to move on :)

Best regards
Mikkel

Parents
  • Hi,

    I want to start by commenting on a misunderstanding: Bootloader and DFU are very much related. The only purpose of the bootloader in the nrF5 SDK is to facilitate DFU. In other words: if you want to support DFU, you need the bootloader. If you don't need DFU, there is no point in having a bootloader.

    It seems to me like what you want is the SDK bootloader, but with an ESB transport. We do not provide an ESB transport layer, but the bootloader is modular, so you can implement it yourself. If you want to save time and have available flash size, then perhaps you can stick with BLE for the bootloader even though you do not use it for the application. In that case you can use the example bootloader out of the box without any modifications. I believe much of these questions will be answered in a good way by reading bootloader documentation and experimenting with the DFU examples. DFU is quite complex so I strongly suggest you go with this approach, and use as much of the SDK examples as you can. If not, you risk spending a lot of time making something that does not work very well.

    - How to I setup a bootloader project in Segger, which are able to startup directly into the bootloader?

    I recommend you just start off with a example bootloader project. This will have everything in place. The boot up sequence will be the following (ignoring the special handling when here is a SoftDevice or Bootloader upgrade in progress):

    • MBR always runs first. MBR checks if there is a bootloader present (by checking the a reserved UICR register for a bootloader start address and/or a special word in the MBR).
    • If a bootloader is not detected, the MBR starts the SoftDevice if present, or the application (whatever is located at address 0x1000).
    • If a bootloader is detected, the MBR will forward execution to the bootloader.
    • The bootloader will check if it is supposed to enter DFU mode (via a number of configurable methods, such as GPIO pin asserted, retention register set, ...)
    • If DFU mode is not requested, the bootloader will check if a valid application is present and start it.
    • If DFU mode is requested or a valid application is not present, the bootloader will enter DFU mode.
    - How to setup a segger project with the correct flash placement for use with a bootloader?

    I assume you are asking about application in this case? As you can see from the memory layout, the bootloader is placed right in the end of the flash. Additionally, the linker will try to place tings in the beginning of the flash you have configured, therefor most applications does not need any modification at all. If you want, you can adjust the size of the application in the linker settings to make it clearer, but it should not have any practical consequences (other than that it will generate a linker error in case the application grows too large, so that it overlaps with the bootloader).

    - How to jump from bootloader to the application?

     Please refer to the bootloader implementation. You can see how it is done in nrf_bootloader_app_start() in SDK 15.3. (components\libraries\bootloader\nrf_bootloader_app_start.c), including the implementation of nrf_bootloader_app_start_final().

    - Will the UICR values be kept between bootloader and application, when not using the DFU?

    The UICR is a persistent (flash) register that typically never changes. Moreover, it cannot be deleted without erasing the full UICR page, which is typically something you never do in the field with an end product. 

    - How would we write to the application flash from our bootloader? Using the fstorage or other lib?

    Please refer to the example bootloader (which use fstorage). I would like to repeat the strong recommendation to use the example bootloader instead of implementing this yourself.

    Br,

    Einar

Reply
  • Hi,

    I want to start by commenting on a misunderstanding: Bootloader and DFU are very much related. The only purpose of the bootloader in the nrF5 SDK is to facilitate DFU. In other words: if you want to support DFU, you need the bootloader. If you don't need DFU, there is no point in having a bootloader.

    It seems to me like what you want is the SDK bootloader, but with an ESB transport. We do not provide an ESB transport layer, but the bootloader is modular, so you can implement it yourself. If you want to save time and have available flash size, then perhaps you can stick with BLE for the bootloader even though you do not use it for the application. In that case you can use the example bootloader out of the box without any modifications. I believe much of these questions will be answered in a good way by reading bootloader documentation and experimenting with the DFU examples. DFU is quite complex so I strongly suggest you go with this approach, and use as much of the SDK examples as you can. If not, you risk spending a lot of time making something that does not work very well.

    - How to I setup a bootloader project in Segger, which are able to startup directly into the bootloader?

    I recommend you just start off with a example bootloader project. This will have everything in place. The boot up sequence will be the following (ignoring the special handling when here is a SoftDevice or Bootloader upgrade in progress):

    • MBR always runs first. MBR checks if there is a bootloader present (by checking the a reserved UICR register for a bootloader start address and/or a special word in the MBR).
    • If a bootloader is not detected, the MBR starts the SoftDevice if present, or the application (whatever is located at address 0x1000).
    • If a bootloader is detected, the MBR will forward execution to the bootloader.
    • The bootloader will check if it is supposed to enter DFU mode (via a number of configurable methods, such as GPIO pin asserted, retention register set, ...)
    • If DFU mode is not requested, the bootloader will check if a valid application is present and start it.
    • If DFU mode is requested or a valid application is not present, the bootloader will enter DFU mode.
    - How to setup a segger project with the correct flash placement for use with a bootloader?

    I assume you are asking about application in this case? As you can see from the memory layout, the bootloader is placed right in the end of the flash. Additionally, the linker will try to place tings in the beginning of the flash you have configured, therefor most applications does not need any modification at all. If you want, you can adjust the size of the application in the linker settings to make it clearer, but it should not have any practical consequences (other than that it will generate a linker error in case the application grows too large, so that it overlaps with the bootloader).

    - How to jump from bootloader to the application?

     Please refer to the bootloader implementation. You can see how it is done in nrf_bootloader_app_start() in SDK 15.3. (components\libraries\bootloader\nrf_bootloader_app_start.c), including the implementation of nrf_bootloader_app_start_final().

    - Will the UICR values be kept between bootloader and application, when not using the DFU?

    The UICR is a persistent (flash) register that typically never changes. Moreover, it cannot be deleted without erasing the full UICR page, which is typically something you never do in the field with an end product. 

    - How would we write to the application flash from our bootloader? Using the fstorage or other lib?

    Please refer to the example bootloader (which use fstorage). I would like to repeat the strong recommendation to use the example bootloader instead of implementing this yourself.

    Br,

    Einar

Children
  • Hi Einar

    Thank you for the detailed answer, and the clearification of the DFU and bootloader relation.
    I think I will stick to your suggestion and use the examples as a starting point, and then implement the ESB transport layer myself.

    The first practical questions that comes to mind, and the last I think I need to understand before I can complete the implementation is:

    - I would have two projects right? One for bootloader/DFU implementation and one for our application?

    - As for production, we need both of these modules in one hex file to program the device before entering the field.

    - Afterwards we need to generate application only hex files, which can be transfered to the DFU through ESB.

    What I am not able to understand is the relations of how the different project outputs will be correct, regarding addresses, starting addresses etc?

  • Hi,

    MStampe said:
    - I would have two projects right? One for bootloader/DFU implementation and one for our application?

    Yes, that is correct.

    MStampe said:
    - As for production, we need both of these modules in one hex file to program the device before entering the field.

    Yes, and you also need the MBR or SoftDevice hex (which depend on if you need BLE transport or not), and you need a valid DFU settings page. Everything can be merged into a single hex file used for production programming.

    MStampe said:
    - Afterwards we need to generate application only hex files, which can be transfered to the DFU through ESB.

    Yes.

    MStampe said:
    What I am not able to understand is the relations of how the different project outputs will be correct, regarding addresses, starting addresses etc?

    Please refer to the bootloader documentation, particularly the Memory layout.

  • I have a 1 query here, If I use DFU Bootloader of Nordic, how can I update the F/W from the same app which we are also developing for our application. we needs to maintain 1 separate app for the f/w update and also we don't have any pins in device for going in bootloader mode again.is my understanding correct?

    we are designing the Product and for that mobile application is also there. weather this will be good approach or we needs to develop our own custom bootloader? 

Related