例程说明
STM32G0xx在对Flash操作时,有时会出现HardFault异常、或者出现擦除、写入失败的情况,故有此记录。
STM32G0xx LL库官方没有提供Flash相关的操作需要自己写,可借鉴HAL库。
宏定义说明
- #define XMEM_ALIGN_SIZE(size , align) (((size) + (align) - 1) / (align))
- /* 获取成员m在结构体t中的偏移位置 */
- #define XOFS(t , m) ((u32)(&(((t *)0)->m)))
- #define SYSTEM_ARG_STORE_START_ADDRE (0x0800F800UL)
- #define FLASH_OPT_OVERTIMER (0x1FFFF)
- #define FLASH_OPT_TRY_COUNT (5)
复制代码
Flash解锁与加锁
- /* Unlock the FLASH control register access */
- static u8 ubFLASH_Unlock(void)
- {
- u8 sta = 0;
- if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U)
- {
- /* Authorize the FLASH Registers access */
- WRITE_REG(FLASH->KEYR, FLASH_KEY1);
- WRITE_REG(FLASH->KEYR, FLASH_KEY2);
- /* verify Flash is unlock */
- if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U)
- {
- sta = 1;
- }
- }
- return sta;
- }
- /* Lock the FLASH control register access */
- static u8 ubFLASH_Lock(void)
- {
- u8 sta = 1;
- /* Set the LOCK Bit to lock the FLASH Registers access */
- SET_BIT(FLASH->CR, FLASH_CR_LOCK);
- /* verify Flash is locked */
- if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00u)
- {
- sta = 0;
- }
- return sta;
- }
复制代码
Flash选项字节解锁与加锁
- /* Unlock the FLASH Option Bytes Registers access */
- static u8 ubFLASH_OB_Unlock(void)
- {
- u8 sta = 1;
- if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0x00U)
- {
- /* Authorizes the Option Byte register programming */
- WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
- WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
- /* verify option bytes are unlocked */
- if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == 0x00U)
- {
- sta = 0;
- }
- }
- return sta;
- }
- /* Lock the FLASH Option Bytes Registers access */
- static u8 ubFLASH_OB_Lock(void)
- {
- u8 sta = 1;
- /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
- SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);
- /* verify option bytes are locked */
- if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0x00u)
- {
- sta = 0;
- }
- return sta;
- }
复制代码
Flash擦除页
- /* Gets the page of a given address */
- static u32 ulGetPage(u32 startAddr)
- {
- return ((startAddr - FLASH_BASE) / FLASH_PAGE_SIZE);
- }
- /* Erase the specified FLASH memory page */
- static u8 ubFLASH_PageErase(u32 page)
- {
- u32 tmp = 0;
- u32 time = 0;
- u8 res = 0;
- /* Get configuration register, then clear page number */
- tmp = (FLASH->CR & ~FLASH_CR_PNB);
- /* Set page number, Page Erase bit & Start bit */
- FLASH->CR = (tmp | (FLASH_CR_STRT | (page << FLASH_CR_PNB_Pos) | FLASH_CR_PER));
- /* wait for BSY1 in order to be sure that flash operation is ended before allowing prefetch in flash */
- while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U)
- {
- if ((++time) > FLASH_OPT_OVERTIMER)
- {
- res = 1;
- break;
- }
- }
- /* If operation is completed or interrupted, disable the Page Erase Bit */
- CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
- return res;
- }
复制代码
Flash忙等待
- /* Wait for a FLASH operation to complete */
- static u8 ubFlash_WaitFor_Operate(u32 timeOut)
- {
- u32 timer = 0;
- u32 error = 0;
- while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U)
- {
- if ((++timer) >= timeOut)
- {
- return 1;
- }
- }
- #if ( USE_STM32G0_LL_LIB_ENABLE > 0)
- /* check flash errors */
- error = (FLASH->SR & FLASH_FLAG_SR_ERROR);
- /* Clear SR register */
- FLASH->SR = FLASH_FLAG_SR_CLEAR;
- #endif
- #if ( USE_STM32G0_HAL_LIB_ENABLE > 0)
- /* check flash errors */
- error = (FLASH->SR & FLASH_SR_ERRORS);
- /* Clear SR register */
- FLASH->SR = FLASH_SR_CLEAR;
- #endif
- if (error != 0x00U)
- {
- return 2;
- }
- timer = 0;
- while ((FLASH->SR & FLASH_SR_CFGBSY) != 0x00U)
- {
- if ((++timer) > timeOut)
- {
- return 3;
- }
- }
- return 0;
- }
复制代码
Flash双字写入
- /* Program double-word (64-bit) at a specified address */
- /* Must EN PG bit before and DIS PG bit after */
- static u8 ubFLASH_Program_DoubleWord(u32 addr, u64 data)
- {
- u32 time = 0;
-
- /* Wait for last operation to be completed */
- while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U)
- {
- if ((++time) > FLASH_OPT_OVERTIMER)
- {
- return 1;
- }
- }
-
- /* Set PG bit */
- SET_BIT(FLASH->CR, FLASH_CR_PG);
- /* Program first word */
- *(u32 *)addr = (u32)data;
- /* Barrier to ensure programming is performed in 2 steps, in right order
- (independently of compiler optimization behavior) */
- __ISB();
- /* Program second word */
- *(u32 *)(addr + 4U) = (u32)(data >> 32U);
- /* Wait for last operation to be completed */
- while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U)
- {
- if ((++time) > FLASH_OPT_OVERTIMER)
- {
- return 2;
- }
- }
- return 0;
- }
复制代码
Flash LL库双字写
- /* Program double-word(64-bit) at a specified address */
- u8 ubFlash_Write_DoubleWord(u32 startAddr, u64 * pDat, u16 len)
- {
- u32 page = 0, time = 0;
- u8 tryCount = 0, res = 0;
- u16 i = 0;
- FLASH_UNLOCK:
- if (ubFLASH_Unlock())
- {
- if ((++tryCount) < FLASH_OPT_TRY_COUNT)
- {
- res = ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);
- dprintf("Wait For Operate %s...%d\r\n", (res ? "Fail" : "OK"), res);
- goto FLASH_UNLOCK;
- }
- else
- {
- dprintf("Flash Unlock Fail...\r\n");
- return 1;
- }
- }
- page = ulGetPage(startAddr);
- tryCount = 0;
- FLASH_ERASE:
- if(ubFLASH_PageErase(page))
- {
- if ((++tryCount) < FLASH_OPT_TRY_COUNT)
- {
- res = ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);
- dprintf("Wait For Operate %s...%d\r\n", (res ? "Fail" : "OK"), res);
- goto FLASH_ERASE;
- }
- else
- {
- ubFLASH_Lock();
- dprintf("Flash Erase Fail...\r\n");
- return 2;
- }
- }
- tryCount = 0;
- for (i = 0; i < len; ++i)
- {
- while(tryCount < FLASH_OPT_TRY_COUNT)
- {
- if(ubFLASH_Program_DoubleWord(startAddr , pDat<i>))
- {
- res = ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);
- dprintf("Wait For Operate %s...%d\r\n", (res ? "Fail" : "OK"), res);
- tryCount++;
- }
- else
- {
- startAddr += 8;
- tryCount = 0;
- break;
- }
- }
- if (tryCount)
- {
- ubFLASH_Lock();
- dprintf("Write Flash Fail...\r\n");
- return 3;
- }
- }
- ubFLASH_Lock();
- dprintf("Write Flash OK...\r\n");
- return 0;
- }</i>
复制代码
Flash HAL库双字写
- /* Program double-word(64-bit) at a specified address */
- u8 ubHAL_Flash_Write_DoubleWord(u32 startAddr, u64 * pDat, u16 len)
- {
- FLASH_EraseInitTypeDef EraseInitStruct = {0};
- u32 pageError = 0;
- u8 i = 0, tryCount = 0;
- 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) = 0x123123;
- FLASH->SR = FLASH_SR_CLEAR;
- }
- if(HAL_FLASH_Unlock() != HAL_OK)
- {
- if ((++tryCount) < FLASH_OPT_TRY_COUNT)
- {
- FLASH_WaitForLastOperation(50);
- goto FLASH_UNLOCK_TRY;
- }
- else
- {
- dprintf("Flash Unlock Fail...\r\n");
- return 1;
- }
- }
- tryCount = 0;
- FLASH_ERASE_TRY:
- HAL_FLASHEx_Erase(&EraseInitStruct, &pageError);
- if(pageError != 0xFFFFFFFF)
- {
- if ((++tryCount) < FLASH_OPT_TRY_COUNT)
- {
- FLASH_WaitForLastOperation(50);
- goto FLASH_ERASE_TRY;
- }
- else
- {
- HAL_FLASH_Lock();
- dprintf("Flash Erase Fail...\r\n");
- return 2;
- }
- }
- tryCount = 0;
- for (i = 0; i < len; ++i)
- {
- while(tryCount < FLASH_OPT_TRY_COUNT)
- {
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, startAddr, pDat) == HAL_OK)
- {
- startAddr += 8;
- tryCount = 0;
- break;
- }
- else
- {
- FLASH_WaitForLastOperation(50);
- tryCount++;
- }
- }
- if (tryCount)
- {
- HAL_FLASH_Lock();
- dprintf("Write Flash Fail...\r\n");
- return 3;
- }
- }
- dprintf("Write Flash OK...\r\n");
- HAL_FLASH_Lock();
- return 0;
- }
复制代码
Flash双字读
- /* Read double-word (64-bit) at a specified address */
- void vFlash_Read_DoubleWord(u32 startAddr, u64 * pDat, u16 len)
- {
- u16 i = 0;
- for(i = 0; i < len; ++i)
- {
- *pDat++ = *(volatile u64 *)(startAddr + (i << 3));
- }
- }
复制代码
Flash读写擦除测试
- typedef struct
- {
- eBatteryCap eBatCap; /* 电池容量 */
- eMeasUnit eUnit; /* 测量单位 */
- u8 LowBatFlg; /* 电池低电标志 */
- u8 MeasType; /* 测量类型 */
- u16 MeasMaxRange; /* 测量最大量程 */
- }GlobalParamStore, * GlobalParamStore_t;
- typedef struct
- {
- u8 AngleDemarFlg; /* 角度标定标志 */
- s16 AngleDemarVal; /* 角度标定值 */
- u8 GyroCaliFlg; /* 陀螺仪校准标志 */
- s16 xGyroCaliVal; /* x轴陀螺仪校准值 */
- s16 yGyroCaliVal; /* y轴陀螺仪校准值 */
- s16 zGyroCaliVal; /* z轴陀螺仪校准值 */
- u8 DistDemarFlg; /* 距离标定标志 */
- u8 ZeroDistDemarVal; /* 零距离标定值 */
- u16 FarDistDemarVal; /* 远距离标定值 */
- }DemarParamStore, * DemarParamStore_t, * pDemarParamStore;
- typedef struct
- {
- xSuperProductInfo ProInfo; /* 产品信息 */
- GlobalParamStore SysPar; /* 系统参数 */
- DemarParamStore DemarPar; /* 标定参数 */
- u8 ubRes[1]; /* 预留 */
- u8 ubCRC8; /* 校验 */
- }SystemParamStore, * SystemParamStore_t;
- SystemParamStore SystemParam = {0};
- /* 保存系统参数 */
- void vSave_System_Parameter(void)
- {
- u16 len = 0;
- len = XMEM_ALIGN_SIZE(sizeof(SystemParamStore) , 8);
- if (len > (FLASH_PAGE_SIZE >> 3))
- {
- dprintf("System Param Over Flash Page Size...\r\n");
- }
- else
- {
- vSynWrite_System_Parameter();
- SystemParam.ubCRC8 = ubCheckSum_CRC8((void *)(&SystemParam), XOFS(SystemParamStore , ubCRC8));
- dprintf("SystemParam CRC8...%X\r\n", SystemParam.ubCRC8);
- if (ubFlash_Write_DoubleWord(SYSTEM_ARG_STORE_START_ADDRE, (u64 *)&SystemParam, len) != 0x00U)
- // if (ubHAL_Flash_Write_DoubleWord(SYSTEM_ARG_STORE_START_ADDRE, (u64 *)&SystemParam, len) != 0x00U)
- {
- dprintf("Save Param Fail...\r\n");
- }
- else
- {
- dprintf("Save Param OK...\r\n");
- }
- }
- }
- /* 读取系统参数 */
- void vRead_System_Parameter(void)
- {
- u16 len = 0;
- u8 crc8 = 0;
- AppProInfo = &SystemParam.ProInfo;
- len = XMEM_ALIGN_SIZE(sizeof(SystemParamStore) , 8);
- dprintf("SystemParamStore Size:%d %d\r\n", sizeof(SystemParamStore), len);
- if (len > (FLASH_PAGE_SIZE >> 3))
- {
- len = (FLASH_PAGE_SIZE >> 3);
- dprintf("System Param Over Flash Page Size...\r\n");
- }
-
- #if 1
- vFlash_Read_DoubleWord(SYSTEM_ARG_STORE_START_ADDRE, (u64 *)&SystemParam, len);
- crc8 = ubCheckSum_CRC8((void *)(&SystemParam), XOFS(SystemParamStore , ubCRC8));
- if(crc8 != SystemParam.ubCRC8)
- {
- Restore_Default_SystemParam();
- dprintf("Restore Default Param...%X %X\r\n", crc8, SystemParam.ubCRC8);
- }
- else
- {
- dprintf("Read System Param OK...\r\n");
- }
- #endif
-
- AppProInfo->DevInfo.SWVer.MajorVer = DEV_INFO_SOFT_MAJOR_VER;
- AppProInfo->DevInfo.SWVer.MinorVer = DEV_INFO_SOFT_MINOR_VER;
-
- vSynRead_System_Parameter();
-
- // vShow_ProductInfo();
- }
复制代码
测试情况
- Init UART OK..
- Vref: 3298mV
- SystemParamStore Size:88 11
- Read System Param OK...
- ******************** System Parameter ********************
- Meas Masx Range: 20000dm
- Angle Demar : 0 ==> 0
- Dist Demar : 0 ==> 0
- Meas Type : 6
- Meas Unit : 1
- Gryo Cali : 0 ==> 0 0 0
- **********************************************************
- Gyro Type MPU6887 ID 0x0F
- Set Meas Type: 6
- Shutdown OverTime: 20s
- Bat Sat : 0
- Set Meas Type: 2
- Set Meas Type: 9
- Set Meas Type: 3
- Set Meas Type: 5
- Set Meas Type: 7
- Set Meas Type: 8
- SystemParam CRC8...E7
- Write Flash OK...
- Save Param OK...
- Overtime Shutdown...
- Init UART OK..
- Vref: 3302mV
- SystemParamStore Size:88 11
- Read System Param OK...
- ******************** System Parameter ********************
- Meas Max Range: 20000dm
- Angle Demar : 0 ==> 0
- Dist Demar : 0 ==> 0
- Meas Type : 8
- Meas Unit : 1
- Gryo Cali : 0 ==> 0 0 0
- **********************************************************
- Gyro Type MPU6887 ID 0x0F
- Set Meas Type: 8
- Shutdown OverTime: 20s
- Bat Sat : 0
- SystemParam CRC8...E7
- Write Flash OK...
- Save Param OK...
- Overtime Shutdown...
复制代码
————————————————
版权声明:凌盛羽
|