Application firmware shifted wrt the end of the softdevice space

Hello,

In my application I use BT DFU to update a Nordic 52840. The new fw is flashed starting from 0x26000 (i.e. the end of the softdevice) and after the update the application starts correctly.

I would like now to leave a space between the end of the softdevice and the start of the application fw, where I can copy some custom data. Let's say I want to start the application fw from 0x27000. I can correctly manipulate the hex files to obtain this, and I can verify that after the DFU the application fw starts from 0x27000 by reading the MCU content with a j-link. However the application won't start cause the bootloader (which is the official Nordic DFU bootloader) has not been informed that it should not point at the end of the softdevice space when starting the application, but it should rather add 0x1000 to that value.

Looking on the internet, I found that until sdk 14.2 the application address was explicitly passed to the nrf_bootloader_app_start, but in later sdk's (I am using sdk 16.0.0, which cannot be upgraded) a nrf_bootloader_app_start call points to the softdevice, which in turn takes care of starting the application by addressing the space immediately after the softdevice space:  NRF52 S132 and application with custom address 

My question is: how can I execute an application shifted by n*0x1000 (with n strictly greater than 0 :) ) with respect to the end of the softdevice in sdk's > 14.2, thus leaving some space for custom data? These data cannot be at the end of the application fw, cause I want to access them from the fw itself (and so with a future larger fw their address would be different) while at the same time keeping the application fw size as small as possible (so I don't want to put them, say, at the end of the flash space).

Thank you.

Regards,

Stefano

  • Dear Einar,

    Thank you for your quick answer. If I understood well, if I want to use a bootloader (which is the case, since our fw must be updated on-field using Bluetooth DFU) and be able to boot an application residing at a different location than just at the end of the SD, the only chance is to use an old (i.e. belonging to a SDK <= 14.2) bootloader?

    If this is true, in which other way can I save a few bytes (8 could be enough) in such a way that: a) the information is at a fixed, known address b) the information is updated each time I perform a DFU c) the information is not lost when I switch power off. I considered UICR user registers, but apparently I cannot update them in a DFU process by writing directly at their address.
    Regards,

    Stefano

  • Also, the address should ideally be such not to make the application fw unnecessarily large. I can of course place this information at the end of the flash, but this would imply transferring the whole size of the flash through DFU. On the other side placing this data too close to the application firmware within the flash would result in having to change its location if future updates will increase its size

  • Hi,

    I understand, and that is a good point (and I guess the reason why this case is not obvious from the start).

    ste2108 said:
    the only chance is to use an old (i.e. belonging to a SDK <= 14.2) bootloader?

    No you do not need to use an old bootloader. But you need to modify the way the bootloader start the application, and use a similar approach that is used in the example bootloader from SDK 14.2 (where the bootloader jumps to the application start address, instead of 0x1000 (which is always the start of the SoftDevice).

    ste2108 said:
    If this is true, in which other way can I save a few bytes (8 could be enough) in such a way that: a) the information is at a fixed, known address b) the information is updated each time I perform a DFU c) the information is not lost when I switch power off. I considered UICR user registers, but apparently I cannot update them in a DFU process by writing directly at their address.

    I have some questions and comments:

    • First, what is the "real" requirement? What is it you want to achieve from a higher level? Knowing this may make it possible to suggest other approaches. And why does the address need to be fixed?
    • Now you don't write about the application needing to modify this data runtime, is that a requirement? If not, why not simply put the data as a constant variable/array/something within the application? You could make sure the linker places that at your fixed location so that it always remain at the same place (see components/libraries/bootloader/nrf_bootloader_info.c for an example of how that can be done, here placing the bootloader start address at a fixed memory location so that it can be read by the MBR).
    • If the data needs to be updatable by DFU and modifiable by the user, you could allocate a variable at a page boundary and make sure it covers the whole page using the approach from above, and you could write to it and erase the page also from the app if you need to update it. This could even be in the middle of the application, that would not matter as the linker would ensure it is the only thing on that page. Or perhaps better, simpler and safer if you use FDS, what about including the "default" value for a FW release in the application (as just a constant you read form you rapp), and if that needs to be modified, do so in FDS? Then have some logic that checks if the constant has a newer version than what was used for the data in FDS, replace them. If not, use the data you have in FDS.

    These are just some comments and speculations that may be irrelevant as I don't have the full picture, but I think it worth examining if you can achieve your end goal in other ways.

    If not, and you really need to use the approach you described initially, then modifying the bootloader is probably the way to go.

  • Dear Einar,

    Thank you for your answer, please find details on my application below.

    The application I upload through DFU is made of two firmwares: one is the Nordic application and the other belongs to another MCU (a ST) with which the Nordic is physically connected through a serial link. The ST application is appended after the Nordic one in the hex (using srec_cat), presently starting from a fixed address, in such a way that with the present size it bothers neither the nordic application nor the bootloader/Softdevice space. Once the DFU is over, the Nordic wakes up, realizes there was a DFU (I use a bit of the gpregret register set by the bootloader for this), set the ST in bootloader mode through spceific gpios and starts uploading the ST firmware through the serial connection. At the moment, since both the size of the Nordic and of the ST firmwares are not known by the Nordic application when it wakes up, the ST firmware is appended at a fixed address and all the remaining flash from that address on is serially uploaded. If instead I write the size of the two firmwares somewhere in the flash when I generate the zip packet for the DFU, I can a) append the ST firmware immediately after the Nordic firmware (with a 1k alignment at the most) b) Send only the flash portion related to the ST firmware through the serial link, without sending the empty part between the end of the ST firmware and the end of the flash. Keep in mind that the sizes of both firmwares may vary in time, as the system requires the possibility of updates and  on-field release during its life cycle. I might of course write the two sizes at the very end of the flash space available for update instead of the beginning, but I believe this would make the DFU zip pointlessly large.

    Given the nature of the application, do you advise any alternative to what I had in mind (i.e. writing the two sizes at the beginning of the application flash space)? Thanks!

    Kind regards,

    Stefano

Related