cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F0x0 custom bootloader

EvO
Associate II

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 :)

Best regards,
Edwin
0 REPLIES 0