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