cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L476 hangs when HAL_Flash_OB_Launch is called

kpate.11
Associate II

I have multiple boards of STM32L476 board. In our application, we have OTA module in which we use dual bank feature.

The OTA flow is like:

1) Read data from SPI

2) Write to Bank 2's pages in incremental order

3) Once all data are transferred, go for flash bank switch

4) The bank switch code is as per Dual boot example provided by ST. See below snippet.

HAL_StatusTypeDef FLASH_If_BankSwitch(void)
{
  FLASH_OBProgramInitTypeDef ob_config;
  HAL_StatusTypeDef result;
 
  HAL_FLASH_Lock();
 
  /* Clear OPTVERR bit set on virgin samples */
  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
 
  /* Get the current configuration */
  HAL_FLASHEx_OBGetConfig( &ob_config );
 
  ob_config.OptionType = OPTIONBYTE_USER;
  ob_config.USERType = OB_USER_BFB2;
  if ((ob_config.USERConfig) & (OB_BFB2_ENABLE)) /* BANK1 active for boot */
  {
    ob_config.USERConfig = OB_BFB2_DISABLE;
  }
  else
  {
    ob_config.USERConfig = OB_BFB2_ENABLE;
  }
 
  /* Initiating the modifications */
  result = HAL_FLASH_Unlock();
 
  /* program if unlock is successful */
  if ( result == HAL_OK )
  {
    result = HAL_FLASH_OB_Unlock();
 
    /* program if unlock is successful*/
    if ((READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == RESET))
    {
      result = HAL_FLASHEx_OBProgram(&ob_config);
    }
    if (result == HAL_OK)
    {
      HAL_FLASH_OB_Launch();
    }
  }
  return result;
}

By adding debug prints after every flash call and found that, it gets stuck at Flash_OB_Launch on some of the boards. But on other boards it is working fine. All these boards are machine assembled so all the boards are identical. So, I have somewhat more confidence on HW.

5) If we power cycle the board couple of times, then it starts with new firmware.

PS: We are using Freertos. Before calling above API, we call XTaskSuspendAll() and taskENTER_CRITICAL() to make sure no interrupt affects the switching.

3 REPLIES 3
SStor
Senior

Hello,

I use dual bank firmware flashing on 476/496 with these 2 functions without problems:

(first switch bank then restart with new firmware)

BYTE HW_SwitchBANK(void)
{
    static BYTE bankswitched = 0;
    if (bankswitched) return 1;
 
    BYTE ret = 1;
 
    HAL_IWDG_Refresh(&hiwdg);
 
    // Set BFB2 bit to enable boot from Flash Bank2
    // Allow Access to Flash control registers and user Flash
    HAL_FLASH_Unlock();
 
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
 
    // Allow Access to option bytes sector
    HAL_FLASH_OB_Unlock();
 
    // Get the Dual boot configuration status
    FLASH_OBProgramInitTypeDef OBInit; 
    HAL_FLASHEx_OBGetConfig(&OBInit);
 
    // Enable/Disable dual boot feature
    OBInit.OptionType = OPTIONBYTE_USER;
    OBInit.USERType   = OB_USER_BFB2;
    OBInit.USERConfig = (OBInit.USERConfig & OB_BFB2_ENABLE) ? OB_BFB2_DISABLE : OB_BFB2_ENABLE;
 
    if (HAL_FLASHEx_OBProgram(&OBInit) != HAL_OK)
    {
        // Error occurred while setting option bytes configuration.
        // User can add here some code to deal with this error.
        // To know the code error, user can call function 'HAL_FLASH_GetError()'
        // Infinite loop
        //while (1) {}
        ret = 0;
    }
 
    // Lock the Flash to disable the flash control register access
    // (recommended to protect the FLASH memory against possible unwanted operation)
    HAL_FLASH_OB_Lock();
    HAL_FLASH_Lock();
 
    if (ret) bankswitched = 1;
    return ret;
}
 
void HW_ResetBANK(void)
{
    HAL_IWDG_Refresh(&hiwdg);
 
    // Set BFB2 bit to enable boot from Flash Bank2
    // Allow Access to Flash control registers and user Flash
    HAL_FLASH_Unlock();
 
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
 
    // Allow Access to option bytes sector
    HAL_FLASH_OB_Unlock();
 
    // Start the Option Bytes programming process
    HAL_FLASH_OB_Launch();
 
    // Lock the Flash to disable the flash control register access
    // (recommended to protect the FLASH memory against possible unwanted operation)
    HAL_FLASH_OB_Lock();
    HAL_FLASH_Lock();
 
    NVIC_SystemReset();
}

kpate.11
Associate II

Yes, it is working for me. But why ST's sample code didn't mention anything related to adding watchdog in this routine. ? Shouldn't it be in errata sheet?

SStor
Senior

I've adapted only some parts of ST sample code for my application requirements and added the IWDG refresh.

Of course if you don't use IWDG or WWDG you don't take care about it. Also if you use FreeRTOS you should consider it.

But the 2 functions above can show you a reliable way for dual bank switching. I've used it in >1000 STM32L476/496 for firmware upgrades without a single problem.