Custom bootloader stuck in nrf_dfu_mbr_init_sd()

Device: nRF52840
Softdevice: 140
SDK: 17.1.0

I'm trying to develop a custom bootloader that will determine which of two images (A or B) to jump to. The memory map that I'm aiming for is:

Flash Memory Map (256 pages of 4096 bytes = 1MByte):
MBR            0x00000000 - 0x00000FFF (0x1000)
Softdevice     0x00001000 - 0x00026FFF (0x26000)
Bootloader     0x00027000 - 0x00033FFF (0xD000)
Image A        0x00034000 - 0x00097FFF (0x64000)
Image B        0x00098000 - 0x000FBFFF (0x64000)
MBR store      0x000FD000 - 0x000FDFFF (0x1000)
Image A Config 0x000FE000 - 0x000FEFFF (0x1000)
Image B Config 0x000FF000 - 0x000FFFFF (0x1000)

I've been following the information from these similar posts:

https://devzone.nordicsemi.com/f/nordic-q-a/84917/porting-project-from-sdk12-3-to-sdk17-and-sd132-to-sd140-unable-to-start-custom-application-from-custom-bootloader-no-dfu-starting-after-sd-in-flash-storage/353891

https://devzone.nordicsemi.com/f/nordic-q-a/33610/can-t-jump-to-a-custom-app-location-using-nrf_bootloader_app_start-with-sdk-v15

Here is the custom bootloader code:

#include <stdint.h>
#include "boards.h"
#include "nrf_mbr.h"
#include "app_error.h"
#include "app_error_weak.h"
#include "nrf_dfu_mbr.h"
#include "nrf_delay.h"
#include "nrf_sdm.h"


void jump_to_addr2(uint32_t new_msp, uint32_t addr)
{
    __set_MSP(new_msp);
    ((void (*)(void))addr)();
}


void app_start2(uint32_t vector_table_addr)
{
    const uint32_t current_isr_num = (__get_IPSR() & IPSR_ISR_Msk);
    const uint32_t new_msp         = *((uint32_t *)(vector_table_addr));                    // The app's Stack Pointer is found as the first word of the vector table.
    const uint32_t reset_handler   = *((uint32_t *)(vector_table_addr + sizeof(uint32_t))); // The app's Reset Handler is found as the second word of the vector table.

    __set_CONTROL(0x00000000);   // Set CONTROL to its reset value 0.
    __set_PRIMASK(0x00000000);   // Set PRIMASK to its reset value 0.
    __set_BASEPRI(0x00000000);   // Set BASEPRI to its reset value 0.
    __set_FAULTMASK(0x00000000); // Set FAULTMASK to its reset value 0.

    ASSERT(current_isr_num == 0); // If this is triggered, the CPU is currently in an interrupt.

    // The CPU is in Thread mode (main context).
    jump_to_addr2(new_msp, reset_handler); // Jump directly to the App's Reset Handler.
}

void nrf_bootloader_app_start_old(uint32_t start_addr)
{
    printf("Running nrf_bootloader_app_start with address: 0x%08lx\r\n", start_addr);

    uint32_t err_code;

    //NRF_LOG_INFO("Initializing SD in mbr\r\n");
    err_code = nrf_dfu_mbr_init_sd();
    if(err_code != NRF_SUCCESS)
    {
        printf("Failed running nrf_dfu_mbr_init_sd\r\n");
        return;
    }

    // Disable interrupts
    printf("Disabling interrupts\r\n");

    NVIC->ICER[0]=0xFFFFFFFF;
#if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2
    NVIC->ICER[1]=0xFFFFFFFF;
#endif

    // Set the sd softdevice vector table base address
    printf("Setting SD vector table base: 0x%08lx\r\n", start_addr);
    err_code = sd_softdevice_vector_table_base_set(start_addr);
    if(err_code != NRF_SUCCESS)
    {
        printf("Failed running sd_softdevice_vector_table_base_set\r\n");
        return;
    }

    // Run application
    //nrf_bootloader_app_start_impl(start_addr);
	app_start2(start_addr);
}

int main(void)
{
	/* APP start flash address: 0x34000 */
	nrf_bootloader_app_start_old(0x34000);
}

The bootloader linker script has:

MEMORY
{
FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xd000
RAM (rwx) : ORIGIN = 0x20002BF0, LENGTH = 0x3D410
}

I'm setting the custom location for the MBR storage using these changes in nrf_mbr.h:
#define MBR_BOOTLOADER_ADDR (0xFDFF8) // MBR store: 0x000FD000 - 0x000FDFFF (0x1000)
#define MBR_PARAM_PAGE_ADDR (0xFDFFC) // MBR store: 0x000FD000 - 0x000FDFFF (0x1000)

When I run the bootloader it hangs in the call to nrf_dfu_mbr_init_sd(). I presume I'm missing something important in my bootloader code. Can someone explain what I've done wrong here?

Thanks.

Related