diff --git a/src/generic/armcm_link.lds.S b/src/generic/armcm_link.lds.S index 8014a490..eb3962ad 100644 --- a/src/generic/armcm_link.lds.S +++ b/src/generic/armcm_link.lds.S @@ -19,7 +19,9 @@ SECTIONS { .text : { . = ALIGN(4); + _text_vectortable_start = .; KEEP(*(.vector_table)) + _text_vectortable_end = .; *(.text .text.*) *(.rodata .rodata*) } > rom @@ -27,6 +29,14 @@ SECTIONS . = ALIGN(4); _data_flash = .; +#if CONFIG_ARMCM_RAM_VECTORTABLE + .ram_vectortable (NOLOAD) : { + _ram_vectortable_start = .; + . = . + ( _text_vectortable_end - _text_vectortable_start ) ; + _ram_vectortable_end = .; + } > ram +#endif + .data : AT (_data_flash) { . = ALIGN(4); diff --git a/src/stm32/Kconfig b/src/stm32/Kconfig index d641cdee..2b315672 100644 --- a/src/stm32/Kconfig +++ b/src/stm32/Kconfig @@ -93,9 +93,9 @@ config STACK_SIZE default 512 choice - prompt "Bootloader offset" if MACH_STM32F407 || MACH_STM32F103 + prompt "Bootloader offset" if MACH_STM32F407 || MACH_STM32F103 || MACH_STM32F070 config STM32_FLASH_START_2000 - bool "8KiB bootloader (stm32duino)" if MACH_STM32F103 + bool "8KiB bootloader (stm32duino)" if MACH_STM32F103 || MACH_STM32F070 config STM32_FLASH_START_7000 bool "28KiB bootloader" if MACH_STM32F103 config STM32_FLASH_START_8000 @@ -110,6 +110,11 @@ config FLASH_START default 0x8008000 if STM32_FLASH_START_8000 default 0x8000000 +config ARMCM_RAM_VECTORTABLE + bool + default y if MACH_STM32F0 && FLASH_START != 0x8000000 + default n + choice prompt "Clock Reference" if LOW_LEVEL_OPTIONS config STM32_CLOCK_REF_8M diff --git a/src/stm32/stm32f0.c b/src/stm32/stm32f0.c index 437747d8..4153f526 100644 --- a/src/stm32/stm32f0.c +++ b/src/stm32/stm32f0.c @@ -99,6 +99,22 @@ usb_request_bootloader(void) NVIC_SystemReset(); } +// Copy vector table and remap ram so new vector table is used +static void +enable_ram_vectortable(void) +{ + // Symbols created by armcm_link.lds.S linker script + extern uint32_t _ram_vectortable_start, _ram_vectortable_end; + extern uint32_t _text_vectortable_start; + + uint32_t count = (&_ram_vectortable_end - &_ram_vectortable_start) * 4; + __builtin_memcpy(&_ram_vectortable_start, &_text_vectortable_start, count); + barrier(); + + enable_pclock(SYSCFG_BASE); + SYSCFG->CFGR1 |= 3 << SYSCFG_CFGR1_MEM_MODE_Pos; +} + #if !CONFIG_STM32_CLOCK_REF_INTERNAL DECL_CONSTANT_STR("RESERVE_PINS_crystal", "PF0,PF1"); #endif @@ -188,6 +204,9 @@ armcm_main(void) SystemInit(); + if (CONFIG_ARMCM_RAM_VECTORTABLE) + enable_ram_vectortable(); + // Set flash latency FLASH->ACR = (1 << FLASH_ACR_LATENCY_Pos) | FLASH_ACR_PRFTBE;