STM32H5 Daul Bank Implementation
前言
之前實做過L4 Daul bank,這邊針對H5在實做一次,但因H5的Daul bank架構邏輯與L4不同這邊在踩了坑後發現他會直接映射到另一個空間,這邊就針對H5這系列IC做深入介紹Daul bank,讓大家都可以避開坑洞快速順利完成專案
架構
因H5裡面的Daul bank初始就是開啟的,所以和G4或L4不同,他是一開始就切割成2塊獨立的區域在舊的L4或G4上是使用下圖去BFB去判讀轉跳
實作
在取得目前所在Bank位置來說因與G4或L4不同不是判讀BFB,所以這邊要修改一下
uint8_t getActiveBank() {
/* Get the boot configuration status */
HAL_FLASHEx_OBGetConfig(&OBInit);
/* Check Swap Flash banks status */
if ((OBInit.USERConfig & OB_SWAP_BANK_ENABLE) == OB_SWAP_BANK_DISABLE)
{
/*Active Bank is bank 1 */
printf("Active Bank is bank 1\n");
return BANK1_ACTIVE;
}
else
{
/*Active Bank is bank 2 */
printf("Active Bank is bank 2\n");
return BANK2_ACTIVE;
}
}
在取得不同Bank後轉跳這邊基本上透過reset會比較快速,因為如果透過address指向,必須2 bank code差異不能太大且個數據address需要固定住位置避免MCU邏輯異常(這塊範例code其實就有提供)
void BT_SWAP_thread_entry(FLASH_OBProgramInitTypeDef OBInit)
{
/* Get the boot configuration status */
// __disable_irq();
HAL_FLASH_OB_Unlock();
HAL_FLASHEx_OBGetConfig(&OBInit);
/* Check Swap Flash 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;
if (HAL_FLASHEx_OBProgram(&OBInit) != HAL_OK) {
printf("OBINT Fail\n\r ");
while (1) {
}
}
/* Launch Option bytes loading */
if (HAL_FLASH_OB_Launch() != HAL_OK) {
printf("OBLaunch Fail\n\r ");
while (1) {
}
}
HAL_FLASH_OB_Lock();
/* Reset the MCU */
// __enable_irq();
// __disable_irq();
HAL_NVIC_SystemReset();
}
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;
if (HAL_FLASHEx_OBProgram(&OBInit) != HAL_OK) {
printf("OBINT Fail\n\r ");
while (1) {
}
}
/* Launch Option bytes loading */
if (HAL_FLASH_OB_Launch() != HAL_OK) {
printf("OBLaunch Fail\n\r ");
while (1) {
}
}
HAL_FLASH_OB_Lock();
/* Reset the MCU */
HAL_NVIC_SystemReset();
}
}
注意要點
因H5是個別獨立的Bank,所以轉換Bank是會連同起始address一起轉換,如下圖會連同所存取的Flash資訊憶起轉換,所以在判讀資料時候如果2個Bank有個存不同Data需要指向不同位置,而優先判讀是看在哪個Bank
這邊可以參考以下部分code擷取,第一不需要判讀在哪個Bank,然後針對不同Bank讀取不同Data做資料分析
uint32_t DateBank1=0;
uint8_t Data1_m=0,Data1_h=0,Data2_m=0,Data2_h=0;
uint32_t DateBank2=0;
uint8_t bank_inform=0;
uint32_t QuadWord[4] = {0,0,0,0};//{bank_inform,bank_flag,0,0}
bank_inform=getActiveBank();
printf("Bank=%d\n\r",bank_inform);
if(bank_inform==1)
{
DateBank1 = *(__IO uint32_t *)0x0807C004;//bank 1 VERSION data
DateBank2 = *(__IO uint32_t *)0x0817C004;//bank 2 VERSION data need modify 0x080FC004 on 1M flash size
}
else
{
DateBank2 = *(__IO uint32_t *)0x0807C004;//bank 1 VERSION data
DateBank1 = *(__IO uint32_t *)0x0817C004;//bank 2 VERSION data need modify 0x080FC004 on 1M flash size
}
另一個要點是雖然Address變更但在擦除Flash部分還是依照原先規則
舉例目前在Bank1 要清除Bank1 第63 sectors程式會使用以下宣告
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.Banks = 1;
EraseInitStruct.Sector = 63;
EraseInitStruct.NbSectors = 1;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)
printf("Erase fail\n\r");
如果目前切換到Bank2 要清除Bank1 第63 sectors程式宣告方式也會與在Bank1相同如下,並不會因為不同Bank不同
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.Banks = 1;
EraseInitStruct.Sector = 63;
EraseInitStruct.NbSectors = 1;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)
printf("Erase fail\n\r");