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

Hook into MBR boot sequence to run custom code

I'm using S140 6.0.0 and associated MBR on an nRF52840 with a custom boot loader derived from the nRF5 SDK 15.0.0 examples.

I'd like to perform some custom actions as soon as possible after MCU reset such as setting some GPIO to a known value to control voltage regulators, similar to this post.

As described in the S140 specification, the MBR contains the reset vector and passes control to the boot loader if there is no in-system boot loader update in progress.  If there is no update in progress the boot loader main() is entered quickly after reset where I can add code to control the required GPIO signals.

When there is an in-system boot loader update in progress as a result of using SD_MBR_COMMAND_COPY_BL, the time between a processor reset and entering the boot loader can be multiple seconds.  This is because the first item the MBR executes is any pending boot loader copy.  The flash erase/program cycles for boot loader programming can easily take over a second, and sometimes multiple seconds if the boot loader is large.  Only after this operation is complete does the new boot loader main() run and we again have control to set GPIO values.  This delay is also not ideal sometimes from a user's perspective during an update as it would be nice to be able to indicate that an update is in progress on LED/screen during this time.  I don't think a workaround using SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET will work as this only takes effect after any in-system boot loader updates.

What are my options if I'd like to be able to run custom hook code before any time-consuming flash operations on boot?

Here are my suggestions.  If there's other ideas on this issue or the ideas below are not feasible, please let me know.

  1. Manually patch the existing MBR binary to inject hook code into the MBR hex file.  It may be possible to replace the existing MBR reset vector to point to the injected hook code (which could reside in the upper part of 0x0-0x1000 MBR page which appears to be unused).  The hook code would run any necessary operations the branch to the original reset vector location.  If the MBR contains a validated CRC, this will not work.  I don't like this option as it involves messy binary patching.
  2. Obtain the source code for MBR and compile in custom changes.  Is it possible to obtain MBR source code?
  3. Longer term solution.  Request a new MBR feature from Nordic to provide an early-boot hook.  This could be controlled through use of another UICR.NRFFW[n] register similar to BOOTADDR.  If the UICR.NRFFW[n] is set, treat this as a pointer to code which is expected to run and return on boot.  As hook code is called from a very low level, it would probably be treated similar to MBR page and never upgraded.
  • Hi Austin, 

    Yes, there will be a small window during the bootloader copy procedure where you will not have be able to control the GPIO pin states, the size of the window will depend on the size of the bootloader as you've pointed out. My comments to you suggestions are:

    1. Yes, I agree that you should avoid binary patching. 

    2. This would be the best option, but I am afraid that we do not distribute the MBR source code as this considered Nordic proprietary. However, I will forward your request for the MBR source to the Product Manager responsible for the SoftDevice.  It might be possible to share something under NDA, but I would not count on it. 

    3. As far as I know adding such a feature to the MBR is not a part of the SoftDevice roadmap and unless more of our customers request such a feature this will most likely not be added in a future SoftDevice release.  

    Best regards

    Bjørn 

  • Although binary patching the MBR is not necessarily a good option, I have tested this approach for a very simple case  which sets a GPIO pin before entry to the bootloader.

    The patch process uses the following steps:

    • Write a small bit of C code containing the required operations to perform as part of boot.  This should be very simply.
    • Generate a set of assembler instructions by compiling the C code against the nRF5 SDK with GCC.
    • Use the generated opcodes from the assembler as input to a patch process which will put the patch assembler instructions into upper MBR address memory.
    • Patch the MBR reset vector to point to the patch instructions.

    When the MCU boots, the reset vector will now run the patch code.  In the attached example, the patch sets GPIO P0.15 to a high level on boot.  The last instruction in the patch jumps back to the original reset vector location to allow normal MBR functionality to run.

    Use this approach with caution as the MBR is the only component which is never updated as part of any firmware upgrade process when using the Nordic DFU modules.

    See the attached files for additional instructions and an example of how the patching process could work.  The patch code and tools will require manual modification to support each specific application.  e.g.  Changes will be needed for processors other than nRF52840, S140.

    patch-mbr-tools.tgz

Related