STM32G0芯片对Flash操作容易出错,经常出现擦除失败或编程失败的情况,故有此记录。
STM32G0芯片LL库没有对Flash的操作需要自己实现,可借鉴HAL库。
STM32G0芯片对Flash的编程必须是双字(64位)。
一、宏定义及变量
#define FLASH_BASE (0x08000000UL) /* FLASH base address */
#define FLASH_PAGE_SIZE (0x00000800UL) /* FLASH Page Size, 2 KBytes */
#define SYS_ARGS_STORE_START_ADDER (0x0800F800UL) /* Store parameter start adress */
#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);
————————————————
版权声明:本文为CSDN博主「凌盛羽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Ceosat/article/details/127027399
|