cancel
Showing results for 
Search instead for 
Did you mean: 

Application booting issue after FW upgrade using ROM bootloader

vibhor-mpc
Associate II

Hi, 

I am using STM32U575 MCU and implementing firmware upgrade feature in it using the ROM bootloader. The application code boots the bootloader by calling the following function. The firmware upgrades correctly and I verified that all the bytes are written correctly into the flash memory. But after upgrade the new application code does not boot up. I have to restart my nucleo board to boot the new firmware.
Also, my application code uses following peripherals - 

  1. GPIO
  2. GPDMA1
  3. I2C1 and I2C4
  4. TIM2, TIM3, TIM4, TIM15, TIM6
  5. UART1 and LPUART1
  6. SPI2

If I use a simple blinky FW and on top of it I try to upgrade the FW, the upgrade works correctly, and the new FW boots up. However, if my actual application code is running and I do FW upgrade, the new FW does not bootup. 
I assume it could be an issue of peripherals not initializing correctly during boot up because on hardware reset the new FW boots up. What needs to be done to load the new firmware without resetting the board. Also I am sending the GO command (0x21) after completion of image transfer and also getting a positive response for that. I am using UART port for transferring image.
Kindly help me out on this issue.

 

#define BOOT_ADDR	0x0BF90000	// my MCU boot code base address
#define	MCU_IRQS	125u	// no. of NVIC IRQ inputs

void JumpToBootloader(void)
{
	uint8_t Test[] = "Jumping to Bootloader...!!!\r\n"; //Data to send
	HAL_UART_Transmit(&huart1, Test, sizeof(Test), 10);

	void (*SysMemBootJump)(void) = (void*)(*((volatile uint32_t*) (BOOT_ADDR + 4U)));
	__set_MSP(*(uint32_t *)BOOT_ADDR);

	/* Disable all interrupts */
	__disable_irq();

	/* Set the clock to the default state */
	HAL_UART_DeInit(&huart1);
	HAL_RCC_DeInit();
	HAL_DeInit();

	/* Clear Interrupt Enable Register & Interrupt Pending Register */
  	for (uint8_t i = 0; i < (MCU_IRQS + 31u) / 32; i++)
	{
		NVIC->ICER[i]=0xFFFFFFFF;
		NVIC->ICPR[i]=0xFFFFFFFF;
	}
	/* Disable Systick timer */
	  SysTick->CTRL = 0;
	  SysTick->LOAD = 0;
	  SysTick->VAL = 0;
	/* Re-enable all interrupts */
	__enable_irq();

	SysMemBootJump();
}

 

 

8 REPLIES 8

The loading of option bytes and mapping of ROM vs FLASH occurs at a power-cycle, not a simple reset.

Transfer of control likely occurs, be wary of memory mapping at zero and any watchdog that's left running.

Watch also for NVIC state, you can't transfer control out of an IRQ Handler or Call-Back

For RTOS watch protection state.

I'd set the SP in Reset_Handler rather than break the stack context in a function.

Validate what you're actually setting SP/PC too, and that it's not erased FLASH

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
TDK
Guru

Generally, the startup code assumes a fresh state. If your application leaves behind artifacts or peripherals in an unknown state, it can cause problems during startup.

Debug the code, pause it when the problems occurs and examine where the code is at to understand what is happening. Likely it is stuck at startup. Don't guess at the problem, debug and find out.

If you feel a post has answered your question, please click "Accept as Solution".
vibhor-mpc
Associate II

vibhormpc_0-1725646842551.png

I tried to debug the application during FW upgrade. The upgrade happens successfully but when booting new firmware, the code fails at 0x08000e16 flash address. I then flashed the new firmware separately in debug mode to check what code is present at this address and I see that the code runs into NMI handler. I am not sure how to debug this further.

I also checked the reset_handler, and the stack pointer is pointing to correct flash address.

for RTOS protection I also added vTaskSuspendAll(); in JumpToBootloader.

Additionally, I tried to deinit all the peripherals manually in JumpToBootloader. Still no luck.

 

 

  MX_GPIO_DeInit();
  MX_GPDMA1_DeInit();
  MX_I2C_DeInit();
  MX_TIM_DeInit();
  MX_USART_DeInit();
  MX_SPI_DeInit();
  MX_TIMEBASE_DeInit();
  HAL_RCC_DeInit();
  HAL_DeInit();

 

The processor's registers and return stack might be more enlightening.

ie where it came from and what it was doing at the time of the NMI, if that's actually the source.

On the STM32U5 what would cause an NMI some kind of memory or ECC failure?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
vibhor-mpc
Associate II

1. I cannot view the call stack as after upgrade, the FW is different than the one I put in debug mode.
2. I am seeing "Bus, memory management or usage fault" in the fault analyzer.
3. I tried to look at fault status registers and following are the values I got.
CFSR Value: 0x20000
HFSR Value: 0x40000000
MMFAR Value: 0x200bffa4
BFAR Value: 0x200bffa4

vibhormpc_0-1725749709581.png

 

In the screenshot you posted, execution is paused at the HAL_Init line. It's not in the error handler. Maybe it goes there if you unpause, but nothing is abnormal in the screenshot.

TDK_0-1725755423807.png

 

If you feel a post has answered your question, please click "Accept as Solution".
vibhor-mpc
Associate II

The screenshot I posted is of the New firmware that gets flashed. The base firmware is entirely different than the upgraded FW.

I had flashed the base fw and started the debugger. I did the FW upgrade and then the code halted at this address. To check what code is present at that address I had to reflash the new FW separately (through ST link and not FW upgrade) and check disassembly at that address. That is what I have posted. 

vibhor-mpc
Associate II

I did some debugging and found that, If I call jumpToBootloader function directly in main before the schedular starts, the upgrade works correctly and the new FW boots correctly as well.
So I assume kernel could be causing the problem. So in the jumpToBootloader function I tried adding vTaskSuspendAll function. But it didn't help. The vTaskEndScheduler function doesn't work. It gets stuck in an infinite while loop.