on 2023-01-13 07:57 AM
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.
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 |
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.
The purpose of this hands-on is to demonstrate how to configure swap bank.
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
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.