Replacing MBR with custom bootloader

Hi,

I'm developing a custom MBR/bootloader for NRF52811 which is used as a second/radio MCU on the board. The MCU will need to run applications with and without the softdevice, based on current usecase (ble and non-BLE protocols). The official uart bootloader takes way too much flash (25k + 8k of config space), even after removing crypto (still 15k+config), leaving us with only few kB of Flash for application logic.

So the current approach is to write a custom MBR which would contain a simple UART protocol to rewrite the flash, nothing fancy, just writing to flash and getting CRC of the data written, a data blob with app or app+softdevice would be written from 0x1000.

So, my question is how the official MBR actually works. Is it enough to change VTOR to 0x1000, jump to reset handler in vector table at that address and stop worrying (assuming the softdevice, if present, handles forwarding all interrupts to app)? Is there anything else, except the interrupt vectors redirection needed to support the softdevice?

Thank you

  • The MBR has an important role to play when replacing/upgrading the bootloader and the softdevice - its the code piece which does the actual swapping of flash pages. Not easy to replace/rewrite.

    if you run out of flash space, consider external flash or a bigger chip variant.

  • It might have an important role for upgrading bootloader and softdevice, but I don't really care in this case - the bootloader won't be present, or to be precise, the fw/softdevice upgrade logic would be placed in the MBR itself.

    I don't need updates over bluetooth, I don't mind corrupting softdevice/app if the upgrade is aborted in the middle - I can always reset MCU by reset pin and write the fw binary again - the NRF is a secondary MCU on a larger board and the main MCU is there to make sure the correct firmware is flashed and working correctly.

  • Hi,

    I see that if you use e.g. the S140 v7.3.0, not much Flash is left on the nRF52811 for other purposes. (S140 takes up 156 kiB, leaving 24 kiB for MBR, bootloader and application.)

    Is it enough to change VTOR to 0x1000, jump to reset handler in vector table at that address and stop worrying (assuming the softdevice, if present, handles forwarding all interrupts to app)?

    That should basically be it, yes. Then make sure not to do any MBR calls from the application.

    Please note that our bootloader in nRF5 SDK do rely somewhat on MBR functionality, so if you use that bootloader for inspiration, then you should be aware of the usage of MBR functionality there.

    Please also note that the SoftDevice must start at 0x1000, which may have some implications for your custom MBR/bootloader implementation. (The SoftDevice is built for being executed from that fixed location.)

    Regards,
    Terje

  • I've created a minimalistic MBR that only changes VTOR to softdevice, sets stack pointer and jumps to the reset vector, but it doesn't seem to do the trick (code below). The reset vector from the S112 seems to be at 0x18a59 (just at the end of the softdevice flash area), stack pointer set to 0x20000cd0, so this is probably valid.

    Flashing softdevice + app works (the device is advertising on BLE), rewriting flash below 0x1000 with my MBR implementation results hanging on address 0x189b8.

    As the softdevice is a binary blob, it's quite hard to debug this... Any ideas what I'm missing?

    #define APP_VECTOR_TABLE_ADDR 0x1000UL

    static void jump_to_app()
    {
        uint32_t *vector = (uint32_t *)APP_VECTOR_TABLE_ADDR;
        uint32_t new_sp = vector[0];
        uint32_t new_pc = vector[1];

        SCB->VTOR = APP_VECTOR_TABLE_ADDR;
        __DSB();
        __ISB();

        __set_MSP(new_sp);
        ((void (*)(void))new_pc)();
    }
  • Hi,

    Upon further inquiry, we see that more is indeed needed. Here's what is required:

    1. Set 0x20000000 to the application start address
    2. Run the reset vector of the SoftDevice (at address 0x1004)
    3. Set 0x20000000 to 0x1000 (which is the start address of the SoftDevice)
    4. Do a sd_softdevice_vector_table_base_set() with the application start address
    5. Set VTOR to the start address of the application
    6. From the application, whenever the SoftDevice is enabled, forward any RADIO, RTC, POWER_CLOCK, RNG and SWI5 IRQs to the SoftDevice

    Some of those steps may be unnecessary and might be omitted to save space, but a first step should be to do all of the above in order to have a known working starting point.

    Regards,
    Terje

Related