| 
 
| 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
 
 
 | 
 |