From 9cfdf6e379809690dde08f45a1e9b45e4a2c80c3 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser <kaspar@schleiser.de> Date: Thu, 5 Oct 2017 17:13:11 +0200 Subject: [PATCH] cpu/cortexm_common: introduce cpu_jump_to_image() This new function allows to jump to another execution environment (VTOR) located at a certain (aligned) address. It's used to boot firmwares at another location than `CPU_FLASH_BASE`. The user needs to ensure that the CPU using this feature is able to be initialised at least twice while jumping to the RIOT `reset_handler_default` function, since it initialises the CPU again (calls cpu_init()). Co-authored-by: Kaspar Schleiser <kaspar@schleiser.de> --- cpu/cortexm_common/include/cpu.h | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/cpu/cortexm_common/include/cpu.h b/cpu/cortexm_common/include/cpu.h index 50ba3b3e12..aa1364c492 100644 --- a/cpu/cortexm_common/include/cpu.h +++ b/cpu/cortexm_common/include/cpu.h @@ -189,6 +189,44 @@ static inline void cortexm_isr_end(void) } } +/** + * @brief Jumps to another image in flash + * + * This function is supposed to be called by a bootloader application. + * + * @param[in] image_address address in flash of other image + */ +static inline void cpu_jump_to_image(uint32_t image_address) +{ + /* Disable IRQ */ + __disable_irq(); + + /* set MSP */ + __set_MSP(*(uint32_t*)image_address); + + /* skip stack pointer */ + image_address += 4; + + /* load the images reset_vector address */ + uint32_t destination_address = *(uint32_t*)image_address; + + /* Make sure the Thumb State bit is set. */ + destination_address |= 0x1; + + /* Branch execution */ + __asm("BX %0" :: "r" (destination_address)); +} + +/* The following register is only present for Cortex-M0+, -M3, -M4 and -M7 CPUs */ +#if defined(CPU_ARCH_CORTEX_M0PLUS) || defined(CPU_ARCH_CORTEX_M3) || \ + defined(CPU_ARCH_CORTEX_M4) || defined(CPU_ARCH_CORTEX_M4F) || \ + defined(CPU_ARCH_CORTEX_M7) +static inline uint32_t cpu_get_image_baseaddr(void) +{ + return SCB->VTOR; +} +#endif + #ifdef __cplusplus } #endif -- GitLab