2025-05-06 4:55 AM - edited 2025-05-06 5:19 AM
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:
/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K
FIRMWARE (rx) : ORIGIN = 0x08004000, LENGTH = 128K - 16K
}
The application now needs to copy the vector table:
#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
The app also needs its linker script edited:
MEMORY
{
RAM (xrw) : ORIGIN = 0x200000C0, LENGTH = 16K - 0xC0
FLASH (rx) : ORIGIN = 0x08004000, LENGTH = 128K - 16K
}
I hope this helps :)