cancel
Showing results for 
Search instead for 
Did you mean: 

Bank switch does not always work

KamilWierzbicki
Associate II

Hello everyone!

I'm facing a problem when trying to switch a bank on STM32H745 MCU. The issue happens only when the debugger is disconnected. Our implementation uses the HAL library to perform Bank switch like this:

HAL_FLASH_Unlock();
        HAL_FLASH_OB_Unlock();

        FLASH_OBProgramInitTypeDef info;
        HAL_FLASHEx_OBGetConfig(&info);

        // swap banks in option bytes
        info.OptionType = OPTIONBYTE_USER;
        info.USERType   = OB_USER_SWAP_BANK;
        if (info.USERConfig & OB_SWAP_BANK_ENABLE)
            info.USERConfig &= ~OB_SWAP_BANK_ENABLE;
        else
            info.USERConfig |= OB_SWAP_BANK_ENABLE;
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1);
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK2);
        HAL_StatusTypeDef ret = HAL_FLASHEx_OBProgram(&info);


        if (HAL_OK == ret)
        {
            // launch new configuration
            ret = HAL_FLASH_OB_Launch();
        }

        (void)HAL_FLASH_OB_Lock();
        (void)HAL_FLASH_Lock();
        __HAL_RCC_CLEAR_RESET_FLAGS();
        NVIC_SystemReset();

In some of the builds it does not work and after reset it keeps running the previous image.
I found that 

HAL_FLASHEx_OBProgram function returns HAL_ERROR which was caused by 
FLASH_WaitForLastOperation and error flag set. The 
FLASH_FLAG_PGSERR_BANK2 causes the problem so I tried to clear all of the flags just before switching with
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK2) however it does not solve the problem.
 
 
3 REPLIES 3
TDK
Super User

Here are the reasons PGSERR is set:

TDK_0-1764166962603.png

I don't see any of those conditions being caused be the code posted, so the problem is likely elsewhere. Are you writing to flash, perhaps?

If you feel a post has answered your question, please click "Accept as Solution".

Not in the same power cycle. We implemented the logic to verify if the current bank contains a stable image, and if not it should switch the bank to the second one. However, it does not work because of this PGSERR. I'm not able to catch where exactly this flag is set because the problem is not reproducible with the debugger connected. An was able to catch the problem only by putting an infinite loop in 

FLASH_WaitForLastOperation function
HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout, uint32_t Bank)
{
  /* Wait for the FLASH operation to complete by polling on QW flag to be reset.
     Even if the FLASH operation fails, the QW flag will be reset and an error
     flag will be set */

  uint32_t bsyflag = FLASH_FLAG_QW_BANK1;
  uint32_t errorflag = 0;
  uint32_t tickstart = HAL_GetTick();

  assert_param(IS_FLASH_BANK_EXCLUSIVE(Bank));

#if defined (DUAL_BANK)

  if (Bank == FLASH_BANK_2)
  {
    /* Select bsyflag depending on Bank */
    bsyflag = FLASH_FLAG_QW_BANK2;
  }
#endif /* DUAL_BANK */

  while (__HAL_FLASH_GET_FLAG(bsyflag))
  {
	  if (Timeout != HAL_MAX_DELAY)
	  {
		  if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
		  {
			  return HAL_TIMEOUT;
		  }
	  }

	  HAL_FLASH_WaitForLastOperationCallback();
  }

  /* Get Error Flags */
  if (Bank == FLASH_BANK_1)
  {
    errorflag = FLASH->SR1 & FLASH_FLAG_ALL_ERRORS_BANK1;
  }
#if defined (DUAL_BANK)
  else
  {
    errorflag = (FLASH->SR2 & FLASH_FLAG_ALL_ERRORS_BANK2) | 0x80000000U;
  }
#endif /* DUAL_BANK */

  /* In case of error reported in Flash SR1 or SR2 register */
  if((errorflag & 0x7FFFFFFFU) != 0U)
  {
    /*Save the error code*/
    pFlash.ErrorCode |= errorflag;
    while(1);
    /* Clear error programming flags */
    __HAL_FLASH_CLEAR_FLAG(errorflag);

    return HAL_ERROR;
  }

The problem seems to be occuring only when trying to switch the banks without writing any data to flash. We have another logic to update banks data and switch it and it works completely fine. 

TDK
Super User

These are hardware state machines and not prone to spontaneous behavior. I would look for a bug related to your flash write routines.

Instrument code with a UART debug stream or other output so that you can instrument the code and view what is happening without the debugger attached.

If you feel a post has answered your question, please click "Accept as Solution".