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:
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.