Hi,
My application uses the nrf9160dk and I program 3 Zephyr images onto the 52840: (1) bootloader, (2) image1 and (3) image2. There is no SD or anything else on the device. The bootloader will boot either image1 or image2 based on the contents of the GPREGRET register upon boot. When one of the images is running and needs to reboot, it will set GPREGRET via sys_reboot(), if it matters.
The attached code works fine when using NCS v1.2, however when I build using NCS 1.4.1 it does not work. Working means that the subsequent image boots successfully. I have tried adding calls to the following, in various combinations, in launch_image():
- nrf_cleanup_peripheral() (copied from mcuboot's nrf_cleanup.c)
- cleanup_arm_nvic() (copied from mcuboot's arm_cleanup.c)
I also tried changing prj.conf which is:
// register addresses per the nrf52 documentation
#define POWER_REG_BASE 0x40000000
#define GPREGRET (POWER_REG_BASE + 0x51c) // retention register
#define RESETREAS (POWER_REG_BASE + 0x400) // reset reason
typedef void *ADDR;
#define IMAGE1 ((ADDR)IMAGE1_OFFSET) // 0x6000
#define IMAGE2 ((ADDR)IMAGE2_OFFSET) // 0x14000
static __inline
void jump_to_addr( ADDR new_msp, ADDR new_lr, ADDR addr )
{
__asm volatile ("MSR MSP, %[arg]" : : [arg] "r" (new_msp));
__asm volatile ("MOV LR, %[arg]" : : [arg] "r" (new_lr) : "lr");
__asm volatile ("BX %[arg]" : : [arg] "r" (addr));
}
void launch_image( ADDR *vector_table )
{
ADDR new_msp = vector_table[0]; // Stack Pointer
ADDR reset_handler = vector_table[1]; // Reset Handler
ADDR new_lr = (ADDR)0xFFFFFFFF;
printk( "new_msp %08x\n", new_msp );
printk( "new_lr %08x\n", new_lr );
printk( "reset_handler %08x\n", reset_handler );
jump_to_addr( new_msp, new_lr, reset_handler ); // Jump directly to the App's Reset Handler.
}
void main()
{
ADDR vector = NULL;
uint32_t *reg = (uint32_t *)GPREGRET;
if( *reg == 0 )
vector = IMAGE1;
else
vector = IMAGE2;
// reset the register
*reg = 0;
printk( "booting vector %p\n", vector );
launch_image( vector );
}