This is not a question, but a solution to a problem that took me forever to solve. This may be evident to many, but it was not to me, soI hope this will save others (and my future self) a lot of time...
I was trying to implement a custom bootloader, where I could not even get the minimal implementation working: a slowly blinking LED when doing nothing and staying in the bootloader, or a quickly blinking LED when jumping to a different application.
The issue is that this is tricky for the STM32F030/070 on which I am developing, because it does not have a VTOR register and the few code examples I found did not work, or did jump, but interrupts stopped working.
The bootloader only needs to jump to the new reset vector:
#define APP_ADDRESS 0x08004000U void JumpToApplication(void) { __disable_irq(); if (*(uint32_t*)(APP_ADDRESS + 4) == 0xFFFFFFFF) { return; // invalid reset handler } uint32_t jump_address = *(volatile uint32_t*)(APP_ADDRESS + 4); void (*app_reset_handler)(void) = (void (*)(void))jump_address; __set_MSP(*(volatile uint32_t*)APP_ADDRESS); app_reset_handler(); } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); if (!HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin)) { // press button to go to app JumpToApplication(); } while(1) { // no jump took place: blink slowly HAL_GPIO_TogglePin(GPIOA, LD2_Pin); HAL_Delay(1000); } }
with something like this section in *FLASH.ld:
#define VECTOR_TABLE_SIZE 48 // Covers 0xC0 bytes (16 + IRQs) #define APP_VECTOR_TABLE ((uint32_t*)0x08004000) #define RAM_VECTOR_TABLE ((uint32_t*)0x20000000) void relocate_vector_table_to_ram(void) { for (uint32_t i = 0; i < VECTOR_TABLE_SIZE; i++) { RAM_VECTOR_TABLE[i] = APP_VECTOR_TABLE[i]; } __HAL_SYSCFG_REMAPMEMORY_SRAM(); } int main(void){ __enable_irq(); relocate_vector_table_to_ram(); HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while(1){ // quickly blink in the app HAL_GPIO_TogglePin(GPIOA, LD2_Pin); // Example: onboard LED HAL_Delay(500); } }
Where __HAL_SYSCFG_REMAPMEMORY_SRAM(); is critical, this macro sets MEM_MODE to 0b11 in SYSCFG->CFGR1
Thanks for sharing this case and the solution you found.
To make this post more visible and easy to find by others who may face the same issue, I mark my reply as the solution.
But yes, the solution is on your original post below!
This is not a question, but a solution to a problem that took me forever to solve. This may be evident to many, but it was not to me, soI hope this will save others (and my future self) a lot of time...
I was trying to implement a custom bootloader, where I could not even get the minimal implementation working: a slowly blinking LED when doing nothing and staying in the bootloader, or a quickly blinking LED when jumping to a different application.
The issue is that this is tricky for the STM32F030/070 on which I am developing, because it does not have a VTOR register and the few code examples I found did not work, or did jump, but interrupts stopped working.
The bootloader only needs to jump to the new reset vector:
#define APP_ADDRESS 0x08004000U void JumpToApplication(void) { __disable_irq(); if (*(uint32_t*)(APP_ADDRESS + 4) == 0xFFFFFFFF) { return; // invalid reset handler } uint32_t jump_address = *(volatile uint32_t*)(APP_ADDRESS + 4); void (*app_reset_handler)(void) = (void (*)(void))jump_address; __set_MSP(*(volatile uint32_t*)APP_ADDRESS); app_reset_handler(); } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); if (!HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin)) { // press button to go to app JumpToApplication(); } while(1) { // no jump took place: blink slowly HAL_GPIO_TogglePin(GPIOA, LD2_Pin); HAL_Delay(1000); } }
with something like this section in *FLASH.ld:
#define VECTOR_TABLE_SIZE 48 // Covers 0xC0 bytes (16 + IRQs) #define APP_VECTOR_TABLE ((uint32_t*)0x08004000) #define RAM_VECTOR_TABLE ((uint32_t*)0x20000000) void relocate_vector_table_to_ram(void) { for (uint32_t i = 0; i < VECTOR_TABLE_SIZE; i++) { RAM_VECTOR_TABLE[i] = APP_VECTOR_TABLE[i]; } __HAL_SYSCFG_REMAPMEMORY_SRAM(); } int main(void){ __enable_irq(); relocate_vector_table_to_ram(); HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while(1){ // quickly blink in the app HAL_GPIO_TogglePin(GPIOA, LD2_Pin); // Example: onboard LED HAL_Delay(500); } }
Where __HAL_SYSCFG_REMAPMEMORY_SRAM(); is critical, this macro sets MEM_MODE to 0b11 in SYSCFG->CFGR1
Thanks for sharing this case and the solution you found.
To make this post more visible and easy to find by others who may face the same issue, I mark my reply as the solution.
But yes, the solution is on your original post below!
This is not a question, but a solution to a problem that took me forever to solve. This may be evident to many, but it was not to me, soI hope this will save others (and my future self) a lot of time...
I was trying to implement a custom bootloader, where I could not even get the minimal implementation working: a slowly blinking LED when doing nothing and staying in the bootloader, or a quickly blinking LED when jumping to a different application.
The issue is that this is tricky for the STM32F030/070 on which I am developing, because it does not have a VTOR register and the few code examples I found did not work, or did jump, but interrupts stopped working.
The bootloader only needs to jump to the new reset vector:
#define APP_ADDRESS 0x08004000U void JumpToApplication(void) { __disable_irq(); if (*(uint32_t*)(APP_ADDRESS + 4) == 0xFFFFFFFF) { return; // invalid reset handler } uint32_t jump_address = *(volatile uint32_t*)(APP_ADDRESS + 4); void (*app_reset_handler)(void) = (void (*)(void))jump_address; __set_MSP(*(volatile uint32_t*)APP_ADDRESS); app_reset_handler(); } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); if (!HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin)) { // press button to go to app JumpToApplication(); } while(1) { // no jump took place: blink slowly HAL_GPIO_TogglePin(GPIOA, LD2_Pin); HAL_Delay(1000); } }
with something like this section in *FLASH.ld:
#define VECTOR_TABLE_SIZE 48 // Covers 0xC0 bytes (16 + IRQs) #define APP_VECTOR_TABLE ((uint32_t*)0x08004000) #define RAM_VECTOR_TABLE ((uint32_t*)0x20000000) void relocate_vector_table_to_ram(void) { for (uint32_t i = 0; i < VECTOR_TABLE_SIZE; i++) { RAM_VECTOR_TABLE[i] = APP_VECTOR_TABLE[i]; } __HAL_SYSCFG_REMAPMEMORY_SRAM(); } int main(void){ __enable_irq(); relocate_vector_table_to_ram(); HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while(1){ // quickly blink in the app HAL_GPIO_TogglePin(GPIOA, LD2_Pin); // Example: onboard LED HAL_Delay(500); } }
Where __HAL_SYSCFG_REMAPMEMORY_SRAM(); is critical, this macro sets MEM_MODE to 0b11 in SYSCFG->CFGR1