diff --git a/libraries/ms-bootloader/README.md b/libraries/ms-bootloader/README.md new file mode 100644 index 000000000..f02d96571 --- /dev/null +++ b/libraries/ms-bootloader/README.md @@ -0,0 +1,18 @@ + + +# ms-bootloader + +ms-bootloader currently contains the jump_to_bootloader project, which allows an application to jump back to the bootloader on command diff --git a/libraries/ms-bootloader/inc/jump.h b/libraries/ms-bootloader/inc/jump.h new file mode 100644 index 000000000..126d2a3e4 --- /dev/null +++ b/libraries/ms-bootloader/inc/jump.h @@ -0,0 +1,8 @@ +#pragma once +// This library allows client to jump to an arbitrary memory address +#include +#include +#include + +// Reset main stack pointer to main stack pointer, and jump to program counter +noreturn void perform_jump(uint32_t sp, uint32_t pc); diff --git a/libraries/ms-bootloader/inc/jump_to_bootloader.h b/libraries/ms-bootloader/inc/jump_to_bootloader.h new file mode 100644 index 000000000..91938239a --- /dev/null +++ b/libraries/ms-bootloader/inc/jump_to_bootloader.h @@ -0,0 +1,4 @@ +#pragma once + +// Jump to the bootloade at the beginning of flash memory +void jump_to_bootloader(void); diff --git a/projects/bootloader/inc/stm32f0xx/bootloader_mcu.h b/libraries/ms-bootloader/inc/stm32f0xx/bootloader_mcu.h similarity index 63% rename from projects/bootloader/inc/stm32f0xx/bootloader_mcu.h rename to libraries/ms-bootloader/inc/stm32f0xx/bootloader_mcu.h index 9db01a743..b10da6cc4 100644 --- a/projects/bootloader/inc/stm32f0xx/bootloader_mcu.h +++ b/libraries/ms-bootloader/inc/stm32f0xx/bootloader_mcu.h @@ -4,8 +4,7 @@ #include -// TODO(SOFT-416): Move this to ms-bootloader. - +#ifdef BOOTLOADER_APPLICATION // The addresses of these values are defined in the bootloader linker script (memory_spaces.ld). // If there's an undefined reference linker error from here, you're using the wrong linker script! extern uint32_t _config_page1_start; @@ -15,6 +14,8 @@ extern uint32_t _application_size; extern uint32_t _ram_start; extern uint32_t _ram_size; extern uint32_t _vector_table_size; +extern uint32_t _bootloader_start; +extern uint32_t _bootloader_size; #define BOOTLOADER_CONFIG_PAGE_1_START ((void *)&_config_page1_start) #define BOOTLOADER_CONFIG_PAGE_2_START ((void *)&_config_page2_start) @@ -23,3 +24,13 @@ extern uint32_t _vector_table_size; #define BOOTLOADER_RAM_START ((void *)&_ram_start) #define BOOTLOADER_RAM_SIZE ((size_t)&_ram_size) #define BOOTLOADER_VECTOR_TABLE_SIZE ((size_t)&_vector_table_size) +#define BOOTLOADER_START ((void *)&_bootloader_start) +#define BOOTLOADER_SIZE ((size_t)&_bootloader_size) +#else +// If we're not in the bootloader or the application, we shouldn't use this! +#define BOOTLOADER_CONFIG_PAGE_1_START ((void *)0) +#define BOOTLOADER_CONFIG_PAGE_2_START ((void *)0) +#define BOOTLOADER_APPLICATION_START ((void *)0) +#define BOOTLOADER_APPLICATION_SIZE (((size_t)0)) +#define BOOTLOADER_VECTOR_TABLE_SIZE ((size_t)0) +#endif diff --git a/projects/bootloader/inc/x86/bootloader_mcu.h b/libraries/ms-bootloader/inc/x86/bootloader_mcu.h similarity index 100% rename from projects/bootloader/inc/x86/bootloader_mcu.h rename to libraries/ms-bootloader/inc/x86/bootloader_mcu.h diff --git a/libraries/ms-bootloader/rules.mk b/libraries/ms-bootloader/rules.mk new file mode 100644 index 000000000..f4958023a --- /dev/null +++ b/libraries/ms-bootloader/rules.mk @@ -0,0 +1,9 @@ +# Defines $(T)_SRC, $(T)_INC, $(T)_DEPS, and $(T)_CFLAGS for the build makefile. +# Tests can be excluded by defining $(T)_EXCLUDE_TESTS. +# Pre-defined: +# $(T)_SRC_ROOT: $(T)_DIR/src +# $(T)_INC_DIRS: $(T)_DIR/inc{/$(PLATFORM)} +# $(T)_SRC: $(T)_DIR/src{/$(PLATFORM)}/*.{c,s} + +# Specify the libraries you want to include +$(T)_DEPS := diff --git a/libraries/ms-bootloader/src/jump.c b/libraries/ms-bootloader/src/jump.c new file mode 100644 index 000000000..1cdf3d144 --- /dev/null +++ b/libraries/ms-bootloader/src/jump.c @@ -0,0 +1,12 @@ +#include "jump.h" + +__attribute__((naked)) noreturn void prv_perform_jump(uint32_t sp, uint32_t pc) { + __asm( + "msr msp, %[sp] \n" // reset the main stack pointer (msp) to sp + "bx %[pc] \n" // jump to pc + + // this bizarre syntax associates the "sp" and "pc" in asm with the sp and pc parameters + // see http://www.ethernut.de/en/documents/arm-inline-asm.html + : + : [sp] "r"(sp), [pc] "r"(pc)); +} diff --git a/libraries/ms-bootloader/src/jump_to_bootloader.c b/libraries/ms-bootloader/src/jump_to_bootloader.c new file mode 100644 index 000000000..a56d708e8 --- /dev/null +++ b/libraries/ms-bootloader/src/jump_to_bootloader.c @@ -0,0 +1,32 @@ +#include "jump_to_bootloader.h" + +#include +#include +#include + +#include "bootloader_mcu.h" +#include "jump.h" +#include "stm32f0xx_misc.h" +#include "stm32f0xx_syscfg.h" + +void jump_to_bootloader(void) { +#ifdef BOOTLOADER_APPLICATION // don't do anything if we're not in the bootloader/application + // Disable all interrupts so their is no interference when working with vector tables + __disable_irq(); + + // Reset the vector table to bootloader's vector table + SYSCFG_MemoryRemapConfig( + SYSCFG_MemoryRemap_Flash); // change where the vector table is stored to beginning of flash + + // story memory location of bootloader starting point at the beginning of flash? + uint32_t *bootloader_in_flash = BOOTLOADER_START; + // setting the stack pointer to the bootloader location now + uint32_t initial_sp = bootloader_in_flash[0]; + uint32_t reset_handler_pc = bootloader_in_flash[1]; + + // re-enable interrupts + __enable_irq(); + // jump to bootloader + perform_jump(initial_sp, reset_handler_pc); +#endif // BOOTLOADER_APPLICATION +} diff --git a/libraries/ms-common/rules.mk b/libraries/ms-common/rules.mk index 7ed5600d9..b4564bafc 100644 --- a/libraries/ms-common/rules.mk +++ b/libraries/ms-common/rules.mk @@ -10,6 +10,8 @@ ifneq (,$(IS_MU)) $(T)_DEPS += mu-gen mu-store endif +$(T)_DEPS += ms-bootloader + ifeq (x86,$(PLATFORM)) $(T)_EXCLUDE_TESTS := pwm pwm_input $(T)_CFLAGS += -DX86 diff --git a/libraries/ms-common/src/can_fsm.c b/libraries/ms-common/src/can_fsm.c index 7eaec813c..b3c97c5f8 100644 --- a/libraries/ms-common/src/can_fsm.c +++ b/libraries/ms-common/src/can_fsm.c @@ -1,9 +1,11 @@ #include "can_fsm.h" + #include "bootloader_can.h" #include "can.h" #include "can_hw.h" #include "can_msg_defs.h" #include "can_rx.h" +#include "jump_to_bootloader.h" FSM_DECLARE_STATE(can_rx_fsm_handle); FSM_DECLARE_STATE(can_tx_fsm_handle); @@ -57,6 +59,10 @@ static void prv_handle_rx(Fsm *fsm, const Event *e, void *context) { // Process bootloader messages if (rx_msg.source_id == SYSTEM_CAN_DEVICE_BOOTLOADER) { +#ifdef BOOTLOADER_APPLICATION // *NOTE: jump to bootloader does not actually return + jump_to_bootloader(); + return; +#endif result = bootloader_can_receive(&rx_msg); return; } diff --git a/platform/stm32f0xx/platform.mk b/platform/stm32f0xx/platform.mk index 511c1478b..58c86097e 100644 --- a/platform/stm32f0xx/platform.mk +++ b/platform/stm32f0xx/platform.mk @@ -44,6 +44,7 @@ endif DEFAULT_LINKER_SCRIPT ?= stm32f0_default.ld ifeq ($(MAKECMDGOALS),temp-bootloader-write) DEFAULT_LINKER_SCRIPT := stm32f0_application.ld +CFLAGS += -DBOOTLOADER_APPLICATION endif # Device openocd config file diff --git a/projects/bootloader/rules.mk b/projects/bootloader/rules.mk index 67f6365be..175d18428 100644 --- a/projects/bootloader/rules.mk +++ b/projects/bootloader/rules.mk @@ -13,7 +13,7 @@ $(T)_SRC := $(wildcard $($(T)_SRC_ROOT)/src/*.c) \ $(T)_INC_DIRS += $($(T)_DIR)/protogen -$(T)_DEPS := ms-common ms-helper nanopb +$(T)_DEPS := ms-common ms-helper nanopb ms-bootloader $(T)_LINKER_SCRIPT := stm32f0_bootloader.ld $(T)_test_config_MOCKS := persist_init diff --git a/projects/bootloader/src/main.c b/projects/bootloader/src/main.c index 8cfb76cd6..72052f394 100644 --- a/projects/bootloader/src/main.c +++ b/projects/bootloader/src/main.c @@ -8,6 +8,7 @@ #include "flash.h" #include "interrupt.h" #include "jump_to_application.h" +#include "jump_to_bootloader.h" #include "log.h" #include "ping.h" #include "query.h"