How to configure swap bank on STM32H7 part 1
-
Objective
An important requirement for flash-memory based systems is the ability to update firmware when installed in the end-product. This facility is referred to as in-application programming (IAP) which can be used to restart the microcontroller on a new firmware after a system reset.
In most STM32H7 with 2MBytes flash memory, the embedded flash memory allows this facility while swapping bank 1 and bank 2.
The objective of this article is to explain the swap bank feature based on an example.
-
Dual Bank flash memory Organization in STM32H7
Depending on the configuration of the SWAP_BANK bit (in the FLASH_OPTCR register), the memory map will be accessed by the embedded flash memory AXI slave interface:
|
Flash memory area |
Flash memory corresponding bank |
Start address |
End address |
|
|
SWAP_ BANK=0 |
SWAP_ BANK=1 |
|||
|
User main memory |
Bank 1 |
Bank 2 |
0x0800 0000 |
0x080F FFFF |
|
Bank 2 |
Bank 1 |
0x0810 0000 |
0x081F FFFF |
|
|
System Memory |
Bank1 |
0x1FF0 0000 |
0x1FF1 FFFF |
|
|
Bank 2 |
0x1FF4 0000 |
0x1FF5 FFFF |
||
-
Required Swap Bank sequence
To change the SWAP_BANK bit (for example to apply a new firmware update), respect the sequence below :
a- Unlock OPTLOCK bit, if not already unlocked.
b- Set the new desired SWAP_BANK_OPT value in the FLASH_OPTSR_PRG register.
c- Start the option byte change sequence by setting the OPTSTART bit in the FLASH_OPTCR register.
d- Once the option byte change has completed, FLASH_OPTSR_CUR contains the expected SWAP_BANK_OPT value, but SWAP_BANK bit in FLASH_OPTCR has not yet been modified and the bank swapping is not yet effective.
e- Force a system reset or a Power on Reset (POR).
When the reset rises, the bank swapping is effective (SWAP_BANK value updated in FLASH_OPTCR) and the new firmware shall be executed.
-
Hands-On Swap Bank
The purpose of this hands-on is to demonstrate how to configure swap bank.
Step 1: Create a new project in STM32CubeMX and select NUCLEO-H745ZI-Q.
- Initialize all peripherals with their default mode? Yes. Then, clear pinout
-
Configure 2 LEDs (PB0 led 1 for Bank1, PE1 Led2 for bank2) and 1 user push button B1 (PC13).
-
All used pins should be assigned to Cortex® M7. CM4 boot should be disabled.
-
Keep clock configuration default state.
-
In the project manager, rename your project (Swap for example) and generate code with EWARM tool chain

Step 2: Update code
-
To start, open the Cortex® M7 workspace: Swap_CM7.
-
Update the main.c in order to add or remove some lines of code as detailed here:
*** /* USER CODE BEGIN PV */ *** FLASH_OBProgramInitTypeDef OBInit; *** /* USER CODE END PV */ ***
-
Boot_Mode_Sequences should be removed. Comment code between USER CODE BEGIN and END of Boot_Mode_Sequence_0 Boot_Mode_Sequence_1 and Boot_Mode_Sequence_2
-
Add these lines of code between /* USER CODE BEGIN 2 */ and /* USER CODE END 2 */ to unlock flash memory and option bytes
**********/* USER CODE BEGIN 2 */********** /* Unlock the User flash memory area */ HAL_FLASH_Unlock(); HAL_FLASH_OB_Unlock(); ***********/* USER CODE END 2 */**********
-
Add these code lines between /* USER CODE BEGIN 3 */ and /* USER CODE END 3 */ to swapping
***************************/* USER CODE BEGIN 3 */*********************************
/* Wait for USER_BUTTON is released */
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == 1)
{
while (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == 1)
{
/* Get the configuration of Dual Bank status in FLASH_BANK_1 */
OBInit. Banks = FLASH_BANK_1;
HAL_FLASHEx_OBGetConfig(&OBInit);
/* Check Swap flash memory banks status */
if ((OBInit.USERConfig & OB_SWAP_BANK_ENABLE) == OB_SWAP_BANK_DISABLE)
{
/*Swap to bank2 */
/*Set OB SWAP_BANK_OPT to swap Bank2*/
OBInit.OptionType = OPTIONBYTE_USER;
OBInit.USERType = OB_USER_SWAP_BANK;
OBInit.USERConfig = OB_SWAP_BANK_ENABLE;
HAL_FLASHEx_OBProgram(&OBInit);
/* Launch Option bytes loading */
HAL_FLASH_OB_Launch();
/*
as the CPU is executing from the flash memory Bank 2 and the I-Cache is enabled:
Instruction cache must be invalidated after bank switching to ensure that CPU fetches correct instructions from the flash memory.
*/
SCB_InvalidateICache();
}
else
{
/* Swap to bank1 */
/*Set OB SWAP_BANK_OPT to swap Bank1*/
OBInit.OptionType = OPTIONBYTE_USER;
OBInit.USERType = OB_USER_SWAP_BANK;
OBInit.USERConfig = OB_SWAP_BANK_DISABLE;
HAL_FLASHEx_OBProgram(&OBInit);
/* Launch Option bytes loading */
HAL_FLASH_OB_Launch();
/*
as the CPU is executing from the flash memory Bank1, and the I-Cache is enabled:
Instruction cache must be invalidated after bank switching to ensure that CPU fetches correct instructions from the flash memory.
*/
SCB_InvalidateICache();
}
}
}
else
{
/* Now assume that FLASH_BANK1 to be defined later on in the linker configuration file */
#ifdef FLASH_BANK1
/* Toggle LED1 */
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
/* Turn off LED2 */
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1,GPIO_PIN_RESET);
#else
/* Toggle LED2 */
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1);
/* Turn off LED1 */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0,GPIO_PIN_RESET);
#endif
/* Insert 100 ms delay */
HAL_Delay(100);
}
*********************** /* USER CODE END 3 */**************************
Part 2 is available under this link.
