diff --git a/src/bootloader/bootloader.c b/src/bootloader/bootloader.c index 13e851c1c..06374013d 100644 --- a/src/bootloader/bootloader.c +++ b/src/bootloader/bootloader.c @@ -190,15 +190,18 @@ static void _render_bootloader_finished_marker(void) delay_ms(30); } -void _binExec(void* l_code_addr) __attribute__((noreturn)); +// See `exception_table` in `startup_samd51.c` for description of the content at `l_code_addr`. +void _binExec(void* l_code_addr) __attribute__((noreturn, noinline)); void _binExec(void* l_code_addr) { __asm__( - "mov r1, r0 \n" - "ldr r0, [r1, #4] \n" - "ldr sp, [r1] \n" - "blx r0"); - (void)l_code_addr; + "mov r1, %0 \n" // Copy l_code_addr to r1 + "ldr r0, [r1, #4] \n" // Load l_code_addr+4 (address of Reset Handler) to r0 + "ldr sp, [r1] \n" // Load l_code_addr (address of Initial Stack Pointer) to SP + "blx r0" // Jump to r0 + : /* no outputs */ + : "r"(l_code_addr) /* input: l_code_addr */ + : "r0", "r1", "sp") /* clobber: r0, r1, sp */; __builtin_unreachable(); } @@ -408,10 +411,8 @@ static size_t _api_write_chunk(const uint8_t* buf, uint8_t chunknum, uint8_t* ou // Erase is handled inside of flash_write if (flash_write( - &FLASH_0, - FLASH_APP_START + (chunknum * FIRMWARE_CHUNK_LEN), - (const uint8_t*)buf, - FIRMWARE_CHUNK_LEN) != ERR_NONE) { + &FLASH_0, FLASH_APP_START + (chunknum * FIRMWARE_CHUNK_LEN), buf, FIRMWARE_CHUNK_LEN) != + ERR_NONE) { return _report_status(OP_STATUS_ERR_WRITE, output); }