cancel
Showing results for 
Search instead for 
Did you mean: 

custom bootloader on STM32F446

fab04
Senior

Hi everybody,

I'm trying to make a bootloader in my STM32F446. The aim if this one is the possibility to update the firmware but with keeping the previous one in case of issue. So, I'll have two slots for firmware.

For now, I have the following sectors in my flash :

BOOTLOADER : 0x0800 0000 -> 0x0800BFFF (it only uses sector 0 & 1 for code, so I use last word of sector 2 (0x0800 BFFE & 0x0800 BFFF) to write a "magic word" which gives me the information, if we're currently running on SLOT 1 or 2).

SLOT 1 : 0x0800 C000 -> 0x0800 3FFF

SLOT 2 : 0x0804 0000 -> 0x0807 FFFF

My FW is running on slot 1. It receives the order to update, so it restarts, checks on which slot the new FM must be copied, writes into the flash, and starts again on new slot (and this is done at each update, so FM is running on SLOT1/2 alternatively).

Everything works well, except the last step, it always run on slot 1 (even if all the code has been written in the slot 2).

In the two first 32 bytes (0x0800 0000), I have the stack pointer and the program counter. One thing, I have noticed is that the PC is always the same (0x08010AC1), but it must be changed if the FW runs on slot2, but I cannot change this one when I made the *.hex* (and I don't want) because I'll never know in advance where the FW is running.

I think I misunderstand something, if you can help me on this point.

Thank you in advance,

 

 

3 REPLIES 3
Saket_Om
ST Employee

Hello @fab04 

When the bootloader needs to start the firmware from slot 2, it should perform the following steps:

  1. Reads the vector table from the base address of slot 2 (0x08040000).
  2. Sets the Main Stack Pointer (MSP) to the value found at the start of slot 2, ensuring the application has the correct stack configuration.
  3. Jumps to the reset handler (the second word in the vector table) in slot 2, effectively starting the application as if it had booted from its original address.
To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

Hello Saket_Om,

Thank you for your answer.

What I've done is the following :

void
jump_to_app(uint32_t addr_app) {
	uint32_t sp = *(__IO uint32_t*)addr_app;			/*<! Main Stack Pointer */
	uint32_t pc = *(__IO uint32_t*)(addr_app + 4);		/*<! Program Counter */

	// Vérifier que SP et PC sont plausibles
	if ((sp < SRAM_BASE) || (sp > (SRAM_BASE + SRAM_SIZE)) ||
		(pc < FLASH_BASE) || (pc > (FLASH_BASE + FLASH_SIZE))) {
		// Erreur : slot invalide
		while(1); // Bloquer ou signaler erreur
	}

	__disable_irq();

	SCB->CPACR |= (0xF << 20); // CP10 & CP11 full access
	//__DSB();
	//__ISB();

	FPU->FPCCR &= ~(FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk);
	//__DSB();
	//__ISB();

  /* désactiver UART + DMA */
   //HAL_UART_DMAStop(&huart1);
   HAL_DMA_DeInit(&hdma_usart1_rx);
   HAL_UART_DeInit(&huart1);
   HAL_RCC_DeInit();
   HAL_DeInit();

   SysTick->CTRL = 0;
   SysTick->LOAD = 0;
   SysTick->VAL  = 0;

   /* Remap du vecteur d'interruptions */
   SCB->VTOR = addr_app;

   for (int i = 0; i < 8; i++) {
	   NVIC->ICER[i] = 0xFFFFFFFF; // 240 IRQ max
	   NVIC->ICPR[i] = 0xFFFFFFFF; // clear pending flags
   }

  /* Charger le MSP de l'application */
   __set_MSP(sp);

   __enable_irq();

   __DSB();
   __ISB();

   pFunction app_main = (pFunction)(pc | 1U);
   app_main();

  while(1) { __NOP(); } // ne devrait jamais revenir
}

When I put my first version of firmware , I've the following data :

0x0800 C000 : 2002 0000 (address of MSP)

0x0800 C004 : 08024AC1 (Program Counter)

When I put my new version of FM (I just change a colour of LED), I've the following data :

0x0800 C000 : 2002 0000

0x0800 C004 : 08024AC1

In the two cases, I've the same data at these addresses, so I think it's normal that it jumps only on slot 1. I think the PC address must be changed, but I think it must be done dynamically, because when I compile my firmware, I don't know in which slot it will put.

 

gbm
Principal

Read the content of this file, esp. the comments:

https://github.com/gbm-ii/STM32_Inc/blob/main/cm_boot.h

Your code will probably fail with -O0. Use -O1 or above.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice