cancel
Showing results for 
Search instead for 
Did you mean: 

Dual-bank mode to switch and boot with the firmware present in the Bank-2 of the flash from the Bank-1

shabaz704
Associate II

Hi,

I am using LED blink firmware generated using CUBE-MX by Disabling all the modes and Clearing the pinouts.

I flashed one firmware in the bank-1 (0x08000000) and

second firmware(with few changes the way the led blinks) flashed into the bank-2 (0x08018000) using the stm32 programmer.

First I writing the firmware-2 into bank-2 like this.

0693W00000BbKnzQAF.png 

Next I am flashing the firmware-1 in the bank-1 and running .

0693W00000BbKpCQAV.pngI kept the bank switch logic in firmware-1.

My main() fun will look like this:

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
 
  __HAL_RCC_SYSCFG_CLK_ENABLE();
 
  int i = 9;
 
  while (i > 0)
  {
	 // printf("LED BLINK\n");
    /* USER CODE END WHILE */
	HAL_GPIO_WritePin(GPIOB, greenLed_Pin, GPIO_PIN_RESET);
	HAL_Delay(1000);
	HAL_GPIO_WritePin(GPIOB, greenLed_Pin, GPIO_PIN_SET);
	HAL_Delay(1000);
	i--;
  }
  	HAL_FLASH_Unlock();
  	HAL_FLASH_OB_Unlock();
 
	FLASH_OB_BootConfig(OB_BOOT_BANK2);
 
	if(READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_MEM_MODE) == 0)
	{
		HAL_GPIO_WritePin(GPIOB, RedLed_Pin|BlueLed_Pin, GPIO_PIN_SET);
		HAL_Delay(2000);
		HAL_GPIO_WritePin(GPIOB, RedLed_Pin| BlueLed_Pin, GPIO_PIN_RESET);
		HAL_Delay(2000);
		SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_UFB);
		if(READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_UFB) == 1)
		{
			HAL_GPIO_WritePin(GPIOB, BlueLed_Pin, GPIO_PIN_SET);
			HAL_Delay(2000);
			HAL_GPIO_WritePin(GPIOB, BlueLed_Pin, GPIO_PIN_RESET);
			HAL_Delay(2000);
			HAL_GPIO_WritePin(GPIOB, greenLed_Pin, GPIO_PIN_RESET);
			HAL_Delay(2000);
		}
		else
		{
			HAL_GPIO_WritePin(GPIOB, RedLed_Pin, GPIO_PIN_SET);
			HAL_Delay(2000);
			HAL_GPIO_WritePin(GPIOB, RedLed_Pin, GPIO_PIN_RESET);
			HAL_Delay(2000);
			HAL_GPIO_WritePin(GPIOB, greenLed_Pin, GPIO_PIN_RESET);
			HAL_Delay(2000);
 
		}
	}
  	HAL_FLASH_OB_Lock();
	HAL_FLASH_Lock();
 
  NVIC_SystemReset();
 
}

Leds I kept for the debug. The code is executing till the leds BLUE and RED glowing together and fading (line 36) after that I am not able to see the leds. So I am thinking it got stuck at

SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_UFB);

Is this aporach is right? Anything else is required? Please suggest?

Thanks

Shabaz

10 REPLIES 10
Bubbles
ST Employee

Hello @shabaz704​ ,

not all STM32 handle the dual bank configuration the same way. What particular product are you using?

Normally live code switching between the banks is not encouraged. You need to take care of the interrupts, make sure the next fetch is safely determined and so on. If you really need your code to perform such tricks, try reading our AN4767.

Rgds,

J.

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.

shabaz704
Associate II

Thank you @JHOUD​,

I am using the B-L072z-LRWAN1 board. In stm32L0x2 MCU datasheet mentioned as it will have two banks.

Can you please suggest any example code for bank switch for booting?

I am actually trying to perform FUOTA over lorawan. For this purpose, I am trying this with a small application.

@shabaz704​ the DBFU example includes a L073 code which should help you:

X-CUBE-DBFU - On-the-fly firmware update for dual bank STM32 microcontrollers (AN4767) - STMicroelectronics

J.

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.

We have refered the above suggested code and integrated same in our application as well.

But still we are unable to set UFB bit from SYSCFG_CFGR1 register. We have gone through datasheet and did not find anything regarding write protection of SYSCFG_CFGR1 register.

static uint32_t Bank_Swap( void )
{
  __disable_irq();
 
  /* disable buffer */
  SET_BIT(FLASH->ACR, FLASH_ACR_DISAB_BUF);
 
  /* branch based on the current bank setting */
  if (READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_UFB) == 0 )
  {
    // debug print
    sprintf(uartBuf, "SYSCFG_CFGR1_UFB setting\r\n");
    HAL_UART_Transmit(&huart2, (uint8_t *)uartBuf, strlen(uartBuf), 100);
    
    SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_UFB);
    
    if (READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_UFB) == 1 )
    {
    	sprintf(uartBuf, "SYSCFG_CFGR1_UFB 1\r\n");
    	HAL_UART_Transmit(&huart2, (uint8_t *)uartBuf, strlen(uartBuf), 100);
    }
 
  }
  else
  {
    CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_UFB);
  }
 
  /* enable buffers */
  CLEAR_BIT(FLASH->ACR, FLASH_ACR_DISAB_BUF);
  /* Note - this does not restore pre-read or prefetch */
  if (READ_BIT(FLASH->ACR, FLASH_ACR_DISAB_BUF) == 0 )
  {
        // debug print
  	sprintf(uartBuf, "FLASH->ACR cleared\r\n");
  	HAL_UART_Transmit(&huart2, (uint8_t *)uartBuf, strlen(uartBuf), 100);
  }
 
  /* restore interrupt capability */
  __enable_irq();
  // debug print
  sprintf(uartBuf, "bank swap end\r\n");
  HAL_UART_Transmit(&huart2, (uint8_t *)uartBuf, strlen(uartBuf), 100);
  return 0;
}

I am able to see the prints only till the line-13.

So, it again stuck at SET_BIT (line-15).

What can be the problem?

shabaz704
Associate II

Hi,

The problem resolved for me by simply ignoring the UFB bit in SYSCFG register. I am not setting it.

By setting BFB2 to 1 itself done the boot form directly from bank2. It's seems the bank swap also done by BFB2 itself. Because when we read the data from the banks after the BFB2 bit set the data from BANK2 is present at the BANK1 address i.e., 0x08000000.

This worked for this board I didn't tested with any other board.

Thank you

GLASS
Senior

Hi, be carefull to not write option bytes each boot! It is stored in flash​. You can easily reach max write cycles of flash and also when power can be lost at anytime you can corrupt option bytes.

An other way is to have custom bootloader​ that chose beetwen two app (one in each flash bank). Part of code making dynamic bank swap and App launch MUST be located in RAM (so no printf an d no Irq during bank swap)

Tested Ok on stm32f429 from years.

Hi @GLASS​ ,

"Part of code making dynamic bank swap and App launch MUST be located in RAM"

Can you elaborate about this statement.

What I understood from "dynamic bank swap" is to use the UFB bit.Right?

If that the case we are unable to set the UFB bit. The code execution is getting stuck at that specific instruction.

SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_UFB);

GLASS
Senior

If you execute code to swap bank flash from flash the next instruction fetch has à very large chance to crash... so the part of code that swap ths bank flash MUST be located in Ram. You MUST also consider that debugger is not aware of bank flash swap. So this difficult piece of code is also difficult to debug...

@shabaz704​ ,

the BFB2 sets the device to actually swap the banks automatically using the same UFB bit. The fact that it works using BFB2 and not directly may suggest that there is a problem when fetching the next instruction from the other bank. Placing the switch code to SRAM as @GLASS​ suggested is a good idea how to avoid such problem. You can also check the addresses in the map file to see differences between linking of the two code versions. You should pay special attention to interrupt vectors too. But that's also part of the AN4767.

J.

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.