STM32G030Cx HAL库Flash擦除与编程操作
例程说明
- STM32G0芯片对Flash操作容易出错,经常出现擦除失败或编程失败的情况,故有此记录。
- STM32G0芯片LL库没有对Flash的操作需要自己实现,可借鉴HAL库。
- STM32G0芯片对Flash的编程必须是双字(64位)。
一、宏定义及变量
#define FLASH_BASE (0x08000000UL)
#define FLASH_PAGE_SIZE (0x00000800UL)
#define SYS_ARGS_STORE_START_ADDER (0x0800F800UL)
#define SYS_ARGS_TAB_SIZE (20)
u64 SYS_ARGS_TAB[SYS_ARGS_TAB_SIZE] = {0};
#if ( SYS_ARGS_TAB_SIZE > (FLASH_PAGE_SIZE >> 3) )
#error "System Argument Over Flash Page Size..."
#endif
二、获取页
static u32 ulGetPage(u32 startAddr)
{
return (startAddr - FLASH_BASE) / FLASH_PAGE_SIZE;;
}
三、写数据(双字)
u8 vFlash_WriteData_DoubleWord(u32 startAddr, u64 * pDat, u16 num)
{
FLASH_EraseInitTypeDef EraseInitStruct = {0};
u32 Address = 0, PageError = 0;
u8 i = 0, tryCount = 0;
u8 res = 0;
dprintf("Start Flash Erase Write...\r\n");
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Page = ulGetPage(startAddr);
EraseInitStruct.NbPages = 1;
EraseInitStruct.Banks = FLASH_BANK_1;
FLASH_UNLOCK_TRY:
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY) != 0x00U)
{
*(u32 *)(startAddr + 600) = 12323;
FLASH->SR = FLASH_SR_CLEAR;
}
if(HAL_FLASH_Unlock() != HAL_OK)
{
tryCount++;
if (tryCount < 5)
{
FLASH_WaitForLastOperation(50);
goto FLASH_UNLOCK_TRY;
}
else
{
dprintf("Flash Unlock Fail...\r\n");
return 1;
}
}
tryCount = 0;
FLASH_ERASE_TRY:
FLASH_WaitForLastOperation(50);
HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
if(PageError != 0xFFFFFFFF)
{
tryCount++;
if (tryCount < 5)
{
goto FLASH_ERASE_TRY;
}
else
{
dprintf("Flash Erase Fail...\r\n");
res = 2;
goto FLASH_ERROR_EXIT;
}
}
for (i = 0; i < num; ++i)
{
while(tryCount < 5)
{
FLASH_WaitForLastOperation(50);
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, startAddr, *(pDat + i)) == HAL_OK)
{
startAddr += 8;
tryCount = 0;
break;
}
else
{
tryCount++;
}
}
}
if (tryCount)
{
dprintf("Write Flash Fail...\r\n");
res = 3;
}
else
{
dprintf("Write Flash OK...\r\n");
}
FLASH_ERROR_EXIT:
HAL_FLASH_Lock();
oPrintf("Exit Flash Opration...\r\n");
return res;
}
四、调用验证
vFlash_WriteData_DoubleWord(SYS_ARGS_STORE_START_ADDER, SYS_ARGS_TAB, SYS_ARGS_TAB_SIZE);