营销网站建设规划方案,贵阳网站建设是什么,百度点击器找名风,中国人在俄罗斯做网站需要多少卢布STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入 参考例程例程说明一、存储到Flash中的数据二、Flash最底层操作(解锁#xff0c;加锁#xff0c;擦除#xff0c;读写)三、从Flash块中读取数据五、测试验证 参考例程
STM32G0xx HAL和LL库Flash读写擦除操… STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入 参考例程例程说明一、存储到Flash中的数据二、Flash最底层操作(解锁加锁擦除读写)三、从Flash块中读取数据五、测试验证 参考例程
STM32G0xx HAL和LL库Flash读写擦除操作 STM32G030Cx HAL库Flash擦除或编程操作出错的解决办法
例程说明
1.Flash存储数据采用页分块方式实现一次擦除多次写入每块128Byte总共16块当存满16块后擦除一次
2.将数据写入Flash前需要前后对比数据只有数据发生变化才能写入Flash中
3.从Flash读取数据后进行CRC校验校验不通过往前继续读取数据然后重新校验数据
4.将数据写如Flash前需要确保改块都是0xFF保证写入数据成功一、存储到Flash中的数据 说明
Header用来标识存储的头部信息在Flash读取或写入时用到ubRes用来作块对齐使用默认进行128Byte对齐 #define FLASH_STORE_PARM_HEADER_TAG (0x6C5A) //固定头信息
#define FLASH_STORE_PARM_BLOCK_SIZE (128) //块大小
#define FLASH_STORE_PARM_BLOCK_COUNT (u16)(FLASH_PAGE_SIZE / FLASH_STORE_PARM_BLOCK_SIZE) //1页分块的数量#pragma pack(1)
typedef struct
{........................
}GlobalParamStore, * GlobalParamStore_t;typedef struct
{........................
}DemarParamStore, * DemarParamStore_t, * pDemarParamStore;typedef struct
{........................
}ExceptionTrace;typedef struct
{........................
}ExtraLibPara;typedef struct
{u16 HeaderTag;u16 StoreIndex;
}FlashStoreHeader, * FlashStoreHeader_t;typedef struct
{FlashStoreHeader Header;GlobalParamStore SysPar;DemarParamStore DemarPar;ExceptionTrace ExpTrace;ExtraLibPara ExtLibPar;u8 ubRes[16];u8 ubCRC8;
}SystemParamStore, * SystemParamStore_t;
#pragma pack() 二、Flash最底层操作(解锁加锁擦除读写) 说明
XSUPER_STM32G0_LL_LIB_ENABLE 被使能使用LL库Flash相关操作失败可多次尝试尽可能让操作成功 #define FLASH_OPT_OVERTIMER (0x1FFFF)
#define FLASH_OPT_TRY_COUNT (5)/* 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;
}/* 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;
}/* 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;
}/* 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 ( XSUPER_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 ( XSUPER_STM32G0_HAL_LIB_ENABLE 0)/* check flash errors */error (FLASH-SR FLASH_SR_ERRORS);/* Clear SR register */FLASH-SR FLASH_SR_CLEAR;
#endifif (error ! 0x00U){return 2;}timer 0;while ((FLASH-SR FLASH_SR_CFGBSY) ! 0x00U){if ((timer) timeOut){return 3;}}return 0;
}/* 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));}
}static u8 xSuper_Flash_Unlock(void)
{u8 tryCount 0;for (tryCount 0; tryCount FLASH_OPT_TRY_COUNT; tryCount){if (!ubFLASH_Unlock()) return 0;ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);}return 1;
}static u8 xSuper_Flash_Lock(void)
{u8 tryCount 0;for (tryCount 0; tryCount FLASH_OPT_TRY_COUNT; tryCount){if (!ubFLASH_Lock()) return 0;ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);}return 1;
}static u8 xSuper_Flash_EreasePage(u32 startAddr)
{u8 tryCount 0;u32 page ulGetPage(startAddr);for (tryCount 0; tryCount FLASH_OPT_TRY_COUNT; tryCount){if (!ubFLASH_PageErase(page)) return 0;ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);}return 1;
}static u8 xSuper_Flash_Program(u32 startAddr, u64 * pDat, u16 len)
{u64 rData 0;u16 i 0;u8 tryCount 0;for (i 0; i len; i){for (tryCount 0; tryCount FLASH_OPT_TRY_COUNT; tryCount){if(!ubFLASH_Program_DoubleWord(startAddr , pDat[i])){rData *(volatile u64 *)(startAddr);if (rData ! pDat[i]){return 1;}else{startAddr 8;tryCount 0;break;}}else{ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);}}if (tryCount) return 2;}return 0;
}u8 ubFlash_Write_DoubleWord_EreasePage(u32 startAddr, u64 * pDat, u16 len, u8 mode)
{//避免HardFault三级流水线__asm volatile(NOP); __asm volatile(NOP); __asm volatile(NOP);__DMB(); __DSB(); __ISB();__asm volatile(NOP); __asm volatile(NOP); __asm volatile(NOP);if (xSuper_Flash_Unlock()){#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Flash Unlock Error...\r\n);#endifreturn 1;}if (mode){if (xSuper_Flash_EreasePage(startAddr)){xSuper_Flash_Lock();#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Flash Erease Error...\r\n);#endifreturn 2;}#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Flash Erease OK...\r\n);#endif}if (xSuper_Flash_Program(startAddr, pDat, len)){xSuper_Flash_Lock();#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Flash Program Error...\r\n);#endifreturn 3;}if (xSuper_Flash_Lock()){#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Flash Lock Error...\r\n);#endifreturn 4;}return 0;
} 三、从Flash块中读取数据 vRead_System_Parameter开始打印每个结构体大小便于调试对齐使用 /* 获取读Flash块索引 */
static u16 usGet_Flash_Read_Index(void)
{u16 dat 0, i 0;u8 crc 0;for (i 0; i FLASH_STORE_PARM_BLOCK_COUNT; i){dat *(volatile u16 *)(SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * (FLASH_STORE_PARM_BLOCK_COUNT - 1 - i)));if (dat FLASH_STORE_PARM_HEADER_TAG) {crc ubCheckSum_CRC8((void *)(SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * (FLASH_STORE_PARM_BLOCK_COUNT - 1 - i))), XOFS(SystemParamStore , ubCRC8));dat *(volatile u8 *)(SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * (FLASH_STORE_PARM_BLOCK_COUNT - 1 - i)) (FLASH_STORE_PARM_BLOCK_SIZE - 1));if (dat crc){return (FLASH_STORE_PARM_BLOCK_COUNT - 1 - i);}}}return FLASH_STORE_PARM_BLOCK_COUNT;
}static void vRead_GlobalSystem_Parameter(void)
{u16 index usGet_Flash_Read_Index();if (index FLASH_STORE_PARM_BLOCK_COUNT){/* 读取块内容 */vFlash_Read_DoubleWord(SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * index), (u64 *)SystemParam, (FLASH_STORE_PARM_BLOCK_SIZE 3));#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Read Param OK...%u\r\n, SystemParam.Header.StoreIndex);#endif}else{/* 块索引无效 恢复默认值 */vRestoreDefault_GlobalSystemParam();#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Restore Param...%u\r\n, SystemParam.Header.StoreIndex);#endif}/* 打印块数据 */#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(\r\n);dprintf( 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F \r\n);dprintf(-------------------------------------------------------------\r\n);for (index 0; index FLASH_STORE_PARM_BLOCK_SIZE; index){if (index (index % 16 0)) dprintf(\r\n);if (index % 16 0) dprintf(0x%08X , (SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * SystemParam.Header.StoreIndex) index));dprintf(%02X , *(volatile u8 *)(SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * SystemParam.Header.StoreIndex) index));}dprintf(\r\n\r\n);#endif
}void vRead_System_Parameter(void)
{#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Header Size :%u\r\n, sizeof(FlashStoreHeader));dprintf(SysPar Size :%u\r\n, sizeof(GlobalParamStore));dprintf(DemarPar Size :%u\r\n, sizeof(DemarParamStore));dprintf(ExpTrace Size :%u\r\n, sizeof(ExceptionTrace));dprintf(ExtLibPar Size:%u\r\n, sizeof(ExtraLibPara));dprintf(SystemParamStore Size......%u\r\n, sizeof(SystemParamStore));if (sizeof(SystemParamStore) ! FLASH_STORE_PARM_BLOCK_SIZE) while (1);#endifvRead_GlobalSystem_Parameter();
}
四、将数据写入Flash块中 static u16 usGet_Flash_Write_Index(void)
{u16 dat 0, i 0, x 0;u8 uFlg 0;for (i 0; i FLASH_STORE_PARM_BLOCK_COUNT; i){dat *(volatile u16 *)(SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * i));if (dat 0xFFFFU){uFlg 0;for (x 0; x FLASH_STORE_PARM_BLOCK_SIZE; x){dat *(volatile u8 *)(SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * i) x);if (dat ! 0xFFU){uFlg 1;break;}}if (!uFlg) {return i;}}}return FLASH_STORE_PARM_BLOCK_COUNT;
}static void vSave_GlobalSystem_Parameter(void)
{u8 * pSrc (u8 *)SystemParam;u8 mode 0, dat 0;u16 index 0;for (index 0; index FLASH_STORE_PARM_BLOCK_SIZE; index){dat *(volatile u8 *)(SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * SystemParam.Header.StoreIndex) index);if (dat ! *pSrc){mode 1;break;}}if (!mode){#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Flash Pram Same...%u\r\n, SystemParam.Header.StoreIndex);#endifreturn;}mode 0;index usGet_Flash_Write_Index();if (index FLASH_STORE_PARM_BLOCK_COUNT){SystemParam.Header.StoreIndex index;}else{SystemParam.Header.StoreIndex 0;mode 1;}SystemParam.ubCRC8 ubCheckSum_CRC8((void *)(SystemParam), XOFS(SystemParamStore , ubCRC8));if (ubFlash_Write_DoubleWord_EreasePage((SYSTEM_ARG_STORE_START_ADDRE (FLASH_STORE_PARM_BLOCK_SIZE * SystemParam.Header.StoreIndex)), (u64 *)SystemParam, (FLASH_STORE_PARM_BLOCK_SIZE 3), mode)){#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Flash Write Error...%u\r\n, SystemParam.Header.StoreIndex);#endif}else{#if defined(DEBUG_RELEASE_VERSION_ENABLE) (DEBUG_RELEASE_VERSION_ENABLE 0)dprintf(Flash Write OK...%u CRC:%02X\r\n, SystemParam.Header.StoreIndex, SystemParam.ubCRC8);#endif}
}void vSave_System_Parameter(void)
{vSave_GlobalSystem_Parameter();
} 五、测试验证 只需调用一下函数即可
从Flash块中读取数据 void vSave_System_Parameter(void)
将数据写入Flash块中 void vRead_System_Parameter(void)