cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with HAL_FLASH_OB_Launch, STM32H7 swapping flash banks

aldridge.nicholas
Associate

Ok just trying to get the bank swapping working.

Loaded and flashed new firmware in to 0x08100000 all goes fine, all i need to do is to swap the flash banks.

Now the code below does do the bank swap fine, but it gets stuck at the HAL_FLASH_OB_Launch();

Does not hard fault, but does not get past it either, the cpu just seems to stop??

If i then press reset button on the board, the bank swap does complete and all is well,

I thought the HAL_FLASH_OB_Launch(); was supposed to reset the cpu?

If not why does it not get any further than that function?

I do have a workaround, by setting the watchdog timer, but would like to know whats going on?

 Im using STM32Cube_FW_H7_V1.3.0

HAL_FLASH_OB_Unlock();

/* Get FLASH_WRP_SECTORS write protection status */

 //OBInit.Banks   = FLASH_BANK_1;

 HAL_FLASHEx_OBGetConfig(&OBInit);

  

 /* Check Swap Flash banks status */

 if ((OBInit.USERConfig & OB_SWAP_BANK_ENABLE) == OB_SWAP_BANK_DISABLE) 

 {

  /*Swap to bank2 */

  /*Set OB SWAP_BANK_OPT to swap Bank2*/

printf("Swapping to bank2\r\n");

  OBInit.OptionType = OPTIONBYTE_USER;

  OBInit.USERType  = OB_USER_SWAP_BANK;

  OBInit.USERConfig = OB_SWAP_BANK_ENABLE;

  HAL_FLASHEx_OBProgram(&OBInit);

  printf("Launch\r\n");

  /* Launch Option bytes loading */

  HAL_FLASH_OB_Launch();

  printf("DONE Restarting\r\n");

  /*

    as the CPU is executing from the Flash Bank1, and the I-Cache is enabled :

    Instruction cache must be invalidated after bank switching to ensure that

    CPU will fetch correct instructions from the flash.

    */

    SCB_InvalidateICache();

HAL_NVIC_SystemReset();

}

 else

 {

  /* Swap to bank1 */

  /*Set OB SWAP_BANK_OPT to swap Bank1*/

printf("Swapping to bank1\r\n");

  OBInit.OptionType = OPTIONBYTE_USER;

  OBInit.USERType = OB_USER_SWAP_BANK;

  OBInit.USERConfig = OB_SWAP_BANK_DISABLE;

  HAL_FLASHEx_OBProgram(&OBInit);

  printf("Launch\r\n");

  /* Launch Option bytes loading */

  HAL_FLASH_OB_Launch();

  printf("DONE Restarting\r\n");

/*

    as the CPU is executing from the Flash Bank1, and the I-Cache is enabled :

    Instruction cache must be invalidated after bank switching to ensure that

    CPU will fetch correct instructions from the flash.

    */

    SCB_InvalidateICache();

HAL_NVIC_SystemReset();

 }

6 REPLIES 6
Owain Phillips_2
Associate II

We too are having problems in the bank switch; but we are using STM32F429.

This used to work fine for us but we switched from IWDG to WWDG at some point.

We switch bank at the HAL_FLASH_OB_Launch() fine if we disable using WWDG; but if watchdog is enabled its like we hang in that call; our HW Watchdog does not seem to restart the board.

If we than use ST-Link to read the option bytes its like all sectors are read protected.

Hossein
Associate

​I fixed this problem by moving the soft reset up before invalidating the I cache

HAL_FLASH_OB_Launch();

HAL_NVIC_SystemReset();

SCB_InvalidateICache();

SF??r
Associate III

Hello,

have basically the same problem with a Stm32h743 in ! V revision !

The program stucks if option byte is switched from bank 2 to bank 1... also debugger access is lost...

After power cycling the bank is successful selected and runs.

Any new thinks here?

My workflow:

  • program new firmware every time to 0x08100000 ("bank2")
  • swap banks like in flow chart of reference manual: "Figure 10. Flash bank swapping sequence"

Some comments to the other comments:

  • HAL_NVIC_SystemReset() has an endless loop and no command can executed after this function
  • Invalidating the I Cache is not necessary, the swapping takes only place after reboot

Pavel A.
Evangelist III

> Have basically the same problem with a Stm32h743 in ! V revision !

See AN5312 Migration from Rev Y to rev V, page 6: "It is not possible to swap banks on the fly".

-- pa

SF??r
Associate III

Ah, the above source codes tries to swap the banks on the fly... that's why clearing the instruction cash is required.

I get it... But it's not my use case. I just want to set swap banks and wait for the user until power cycle or (reboot -> NVIC_SystemReset).

Here are the source, with a lot of maybe non req. safety checks -> wait for last ob operation... etc.

int flashoper_swapbanks(uint32_t crc_value)
{
	//if crc of flash firmware matches with the given crc in the file header
	if(!flashoper_crccheck(crc_value, curr_programming_addr))
	{
		return 0;
	}
 
	logging_debug(LOGMOD_FWUPDATE, "Start swap bank process from bank %u to bank %u", flashoper_getactbank(), (flashoper_getactbank() == 1) ? 2 : 1);
	vTaskDelay(10);
 
	if(HAL_GetREVID() == 0x1003)
	{
		//Y device does not support error free bank swapping
		logging_error(LOGMOD_FWUPDATE, "Bank swapping unsupported on this device");
		vTaskDelay(50);
		assert_param(0);
		return 0;
 
		/*2.2.8 Flash memory bank swapping might impact embedded
		Flash memory interface behavior
		Description
		When Flash memory bank swapping feature is enabled, the embedded Flash memory interface behavior might become unpredictable.
		Workaround
		Do not enable the Flash memory bank swapping feature on devices revision Y.
		 */
	}
 
	logging_debug(LOGMOD_FWUPDATE, "hier 1");
	vTaskDelay(10);
 
	HAL_FLASH_OB_Unlock();
 
	logging_debug(LOGMOD_FWUPDATE, "hier 2");
	vTaskDelay(10);
 
	int bank = flashoper_getactbank();
 
	if(bank == 1)
		SET_BIT(FLASH->OPTSR_PRG, FLASH_OPTCR_SWAP_BANK);
	else
		CLEAR_BIT(FLASH->OPTSR_PRG, FLASH_OPTCR_SWAP_BANK);
 
	logging_debug(LOGMOD_FWUPDATE, "hier 3 0x%08X", FLASH->OPTSR_PRG);
	vTaskDelay(10);
 
	int timeout = FLASHOPERATIONS_FLASHOPERTIMEOUT; //ms
	//wait until option byte flash is ready -> blocking!
	while(FLASH_OB_WaitForLastOperation(0) != HAL_OK)
	{
		logging_debug(LOGMOD_FWUPDATE, "hier 4 0x%08X", FLASH->OPTSR_CUR);
		if(timeout-- <= 0)
		{
			HAL_FLASH_OB_Lock();
			logging_error(LOGMOD_FWUPDATE, "Option bytes not ready");
			return 0;
		}
 
		vTaskDelay(1);
 
 
	}
 
	logging_debug(LOGMOD_FWUPDATE, "hier 5");
	vTaskDelay(10);
 
	//start writing option bit
	SET_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTSTART);
 
	logging_debug(LOGMOD_FWUPDATE, "hier 6 0x%08X", FLASH->OPTCR);
	vTaskDelay(10);
 
	//wait until option byte is set
	timeout = FLASHOPERATIONS_FLASHOPERTIMEOUT;
	if(bank == 1)
	{
		while(HAL_IS_BIT_CLR(FLASH->OPTSR_CUR, FLASH_OPTSR_SWAP_BANK_OPT))
		{
			logging_debug(LOGMOD_FWUPDATE, "hier 7");
 
			if(timeout-- <= 0)
			{
				HAL_FLASH_OB_Lock();
				logging_error(LOGMOD_FWUPDATE, "Option byte set from bank 1 fails");
				return 0;
			}
 
			vTaskDelay(1);
		}
	}
	else
	{
		while(HAL_IS_BIT_SET(FLASH->OPTSR_CUR, FLASH_OPTSR_SWAP_BANK_OPT))
		{
			logging_debug(LOGMOD_FWUPDATE, "hier 8");
 
			if(timeout-- <= 0)
			{
				HAL_FLASH_OB_Lock();
				logging_error(LOGMOD_FWUPDATE, "Option byte set from bank 2 fails");
				return 0;
			}
 
 
			vTaskDelay(1);
		}
	}
 
	logging_debug(LOGMOD_FWUPDATE, "hier 9 0x%08X", FLASH->OPTSR_CUR);
	vTaskDelay(10);
 
	timeout = FLASHOPERATIONS_FLASHOPERTIMEOUT; //ms
	//wait until option byte flash is ready -> blocking!
	while(FLASH_OB_WaitForLastOperation(0) != HAL_OK)
	{
		logging_debug(LOGMOD_FWUPDATE, "hier 10");
 
		if(timeout-- <= 0)
		{
			HAL_FLASH_OB_Lock();
			logging_error(LOGMOD_FWUPDATE, "Option bytes not ready");
			return 0;
		}
		vTaskDelay(1);
	}
 
	logging_debug(LOGMOD_FWUPDATE, "hier 11");
 
	HAL_FLASH_OB_Lock();
 
	logging_debug(LOGMOD_FWUPDATE, "hier 12");
 
	return 1;
}

Output:

Start swap bank process from bank 1 to bank 2
hier 1
hier 2
hier 3 0x8BC6AAF0
hier 5
hier 6 0x00000000
hier 9 0x8BC6AAF0
hier 11
hier 12
$
 
......
 
Start swap bank process from bank 2 to bank 1
hier 1
hier 2
hier 3 0x0BC6AAF0
hier 5
hier 6 0x80000000

The process stuck's on "hier 6" if bank 2 to bank 1 swap is req.

SF??r
Associate III

Okay, got it!

The calibration values for the internal temperature measurement used with the marcro: __HAL_ADC_CALC_TEMPERATURE are stored on flash bank 1 (System Flash memory 0x1FF0 0000 - 0x1FF1 FFFF). If the erase of flash bank 1 is ongoing the program (all tasks) stalls even if you have two banks and the program works an bank 2.

Also the reading from flash bank 1 (__HAL_ADC_CALC_TEMPERATURE ) will perhaps crash the option byte programming (FLASH_OB_WaitForLastOperation) in an RTOS environment.