请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32G0xx HAL和LL库Flash读写擦除操作

[复制链接]
STMCU小助手 发布时间:2022-11-24 15:03
例程说明
STM32G0xx在对Flash操作时,有时会出现HardFault异常、或者出现擦除、写入失败的情况,故有此记录。
STM32G0xx LL库官方没有提供Flash相关的操作需要自己写,可借鉴HAL库。

宏定义说明

  1. #define XMEM_ALIGN_SIZE(size , align)                                        (((size) + (align) - 1) / (align))

  2. /* 获取成员m在结构体t中的偏移位置 */
  3. #define XOFS(t , m)                                                         ((u32)(&(((t *)0)->m)))

  4. #define SYSTEM_ARG_STORE_START_ADDRE                                        (0x0800F800UL)

  5. #define FLASH_OPT_OVERTIMER                                                                                         (0x1FFFF)
  6. #define FLASH_OPT_TRY_COUNT                                                                                         (5)
复制代码

Flash解锁与加锁
  1. /* Unlock the FLASH control register access */
  2. static u8 ubFLASH_Unlock(void)
  3. {
  4.     u8 sta = 0;

  5.     if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U)
  6.     {
  7.         /* Authorize the FLASH Registers access */
  8.         WRITE_REG(FLASH->KEYR, FLASH_KEY1);
  9.         WRITE_REG(FLASH->KEYR, FLASH_KEY2);

  10.         /* verify Flash is unlock */
  11.         if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U)
  12.         {
  13.             sta = 1;
  14.         }
  15.     }

  16.     return sta;        
  17. }


  18. /* Lock the FLASH control register access */
  19. static u8 ubFLASH_Lock(void)
  20. {
  21.     u8 sta = 1;

  22.     /* Set the LOCK Bit to lock the FLASH Registers access */
  23.     SET_BIT(FLASH->CR, FLASH_CR_LOCK);

  24.     /* verify Flash is locked */
  25.     if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00u)
  26.     {
  27.         sta = 0;
  28.     }

  29.     return sta;
  30. }
复制代码

Flash选项字节解锁与加锁
  1. /* Unlock the FLASH Option Bytes Registers access */
  2. static u8 ubFLASH_OB_Unlock(void)
  3. {
  4.     u8 sta = 1;

  5.     if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0x00U)
  6.     {
  7.         /* Authorizes the Option Byte register programming */
  8.         WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
  9.         WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);

  10.         /* verify option bytes are unlocked */
  11.         if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == 0x00U)
  12.         {
  13.             sta = 0;
  14.         }
  15.     }

  16.     return sta;
  17. }


  18. /* Lock the FLASH Option Bytes Registers access */
  19. static u8 ubFLASH_OB_Lock(void)
  20. {
  21.     u8 sta = 1;

  22.     /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
  23.     SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);

  24.     /* verify option bytes are locked */
  25.     if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0x00u)
  26.     {
  27.         sta = 0;
  28.     }

  29.     return sta;
  30. }
复制代码

Flash擦除页

  1. /* Gets the page of a given address */
  2. static u32 ulGetPage(u32 startAddr)
  3. {
  4.     return ((startAddr - FLASH_BASE) / FLASH_PAGE_SIZE);
  5. }


  6. /* Erase the specified FLASH memory page */
  7. static u8 ubFLASH_PageErase(u32 page)
  8. {
  9.     u32 tmp  = 0;
  10.     u32 time = 0;
  11.     u8  res  = 0;

  12.     /* Get configuration register, then clear page number */
  13.     tmp = (FLASH->CR & ~FLASH_CR_PNB);

  14.     /* Set page number, Page Erase bit & Start bit */
  15.     FLASH->CR = (tmp | (FLASH_CR_STRT | (page <<  FLASH_CR_PNB_Pos) | FLASH_CR_PER));

  16.     /* wait for BSY1 in order to be sure that flash operation is ended before allowing prefetch in flash */
  17.     while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U)
  18.     {
  19.         if ((++time) > FLASH_OPT_OVERTIMER)
  20.         {
  21.             res = 1;
  22.             break;
  23.         }
  24.     }

  25.     /* If operation is completed or interrupted, disable the Page Erase Bit */
  26.     CLEAR_BIT(FLASH->CR, FLASH_CR_PER);

  27.     return res;
  28. }
复制代码

Flash忙等待
  1. /* Wait for a FLASH operation to complete */
  2. static u8 ubFlash_WaitFor_Operate(u32 timeOut)
  3. {
  4.     u32 timer = 0;
  5.     u32 error = 0;

  6.     while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U)
  7.     {
  8.         if ((++timer) >= timeOut)
  9.         {
  10.             return 1;
  11.         }
  12.     }

  13. #if ( USE_STM32G0_LL_LIB_ENABLE > 0)
  14.     /* check flash errors */
  15.     error = (FLASH->SR & FLASH_FLAG_SR_ERROR);

  16.     /* Clear SR register */
  17.     FLASH->SR = FLASH_FLAG_SR_CLEAR;
  18. #endif


  19. #if ( USE_STM32G0_HAL_LIB_ENABLE > 0)
  20.     /* check flash errors */
  21.     error = (FLASH->SR & FLASH_SR_ERRORS);

  22.     /* Clear SR register */
  23.     FLASH->SR = FLASH_SR_CLEAR;
  24. #endif


  25.     if (error != 0x00U)
  26.     {
  27.         return 2;
  28.     }

  29.     timer = 0;
  30.     while ((FLASH->SR & FLASH_SR_CFGBSY) != 0x00U)
  31.     {
  32.         if ((++timer) > timeOut)
  33.         {
  34.             return 3;
  35.         }
  36.     }

  37.     return 0;
  38. }
复制代码

Flash双字写入
  1. /* Program double-word (64-bit) at a specified address */
  2. /* Must EN PG bit before and DIS PG bit after */
  3. static u8 ubFLASH_Program_DoubleWord(u32 addr, u64 data)
  4. {
  5.     u32 time = 0;

  6.         
  7.     /* Wait for last operation to be completed */
  8.     while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U)
  9.     {
  10.         if ((++time) > FLASH_OPT_OVERTIMER)
  11.         {
  12.             return 1;
  13.         }
  14.     }
  15.         
  16.         /* Set PG bit */
  17.         SET_BIT(FLASH->CR, FLASH_CR_PG);

  18.     /* Program first word */
  19.     *(u32 *)addr = (u32)data;

  20.     /* Barrier to ensure programming is performed in 2 steps, in right order
  21.     (independently of compiler optimization behavior) */
  22.     __ISB();

  23.     /* Program second word */
  24.     *(u32 *)(addr + 4U) = (u32)(data >> 32U);

  25.     /* Wait for last operation to be completed */
  26.     while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U)
  27.     {
  28.         if ((++time) > FLASH_OPT_OVERTIMER)
  29.         {
  30.             return 2;
  31.         }
  32.     }

  33.     return 0;
  34. }
复制代码

Flash LL库双字写
  1. /* Program double-word(64-bit) at a specified address */
  2. u8 ubFlash_Write_DoubleWord(u32 startAddr, u64 * pDat, u16 len)
  3. {
  4.     u32 page = 0, time = 0;
  5.     u8  tryCount = 0, res = 0;
  6.     u16 i = 0;


  7. FLASH_UNLOCK:
  8.     if (ubFLASH_Unlock())
  9.     {
  10.         if ((++tryCount) < FLASH_OPT_TRY_COUNT)
  11.         {
  12.             res = ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);
  13.                         dprintf("Wait For Operate %s...%d\r\n", (res ? "Fail" : "OK"), res);
  14.             goto FLASH_UNLOCK;
  15.         }
  16.         else
  17.         {
  18.             dprintf("Flash Unlock Fail...\r\n");
  19.             return 1;
  20.         }   
  21.     }

  22.     page = ulGetPage(startAddr);
  23.     tryCount = 0;


  24. FLASH_ERASE:
  25.     if(ubFLASH_PageErase(page))
  26.     {
  27.         if ((++tryCount) < FLASH_OPT_TRY_COUNT)
  28.         {
  29.             res = ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);
  30.                         dprintf("Wait For Operate %s...%d\r\n", (res ? "Fail" : "OK"), res);
  31.             goto FLASH_ERASE;
  32.         }
  33.         else
  34.         {
  35.             ubFLASH_Lock();
  36.             dprintf("Flash Erase Fail...\r\n");
  37.             return 2;
  38.         }   
  39.     }


  40.     tryCount = 0;
  41.     for (i = 0; i < len; ++i)
  42.     {
  43.         while(tryCount < FLASH_OPT_TRY_COUNT)
  44.         {
  45.             if(ubFLASH_Program_DoubleWord(startAddr , pDat<i>))
  46.             {
  47.                 res = ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);
  48.                                 dprintf("Wait For Operate %s...%d\r\n", (res ? "Fail" : "OK"), res);
  49.                 tryCount++;
  50.             }
  51.             else
  52.             {
  53.                 startAddr += 8;
  54.                 tryCount   = 0;
  55.                 break;
  56.             }
  57.         }

  58.         if (tryCount)
  59.         {
  60.             ubFLASH_Lock();
  61.             dprintf("Write Flash Fail...\r\n");
  62.             return 3;
  63.         }
  64.     }


  65.     ubFLASH_Lock();
  66.     dprintf("Write Flash OK...\r\n");
  67.     return 0;
  68. }</i>
复制代码

Flash HAL库双字写
  1. /* Program double-word(64-bit) at a specified address */
  2. u8 ubHAL_Flash_Write_DoubleWord(u32 startAddr, u64 * pDat, u16 len)
  3. {
  4.     FLASH_EraseInitTypeDef EraseInitStruct = {0};
  5.     u32 pageError = 0;
  6.     u8 i = 0, tryCount = 0;



  7.     EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
  8.     EraseInitStruct.Page           = ulGetPage(startAddr);
  9.     EraseInitStruct.NbPages          = 1 ;
  10.     EraseInitStruct.Banks          = FLASH_BANK_1 ;


  11. FLASH_UNLOCK_TRY:
  12.     if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY) != 0x00U)
  13.     {
  14.         *(u32 *)(startAddr + 600) = 0x123123;
  15.         FLASH->SR = FLASH_SR_CLEAR;
  16.     }

  17.     if(HAL_FLASH_Unlock() != HAL_OK)
  18.     {
  19.         if ((++tryCount) < FLASH_OPT_TRY_COUNT)
  20.         {
  21.             FLASH_WaitForLastOperation(50);
  22.             goto FLASH_UNLOCK_TRY;
  23.         }
  24.         else
  25.         {
  26.             dprintf("Flash Unlock Fail...\r\n");
  27.             return 1;
  28.         }
  29.     }

  30.     tryCount = 0;




  31. FLASH_ERASE_TRY:
  32.     HAL_FLASHEx_Erase(&EraseInitStruct, &pageError);
  33.     if(pageError != 0xFFFFFFFF)
  34.     {
  35.         if ((++tryCount) < FLASH_OPT_TRY_COUNT)
  36.         {
  37.             FLASH_WaitForLastOperation(50);
  38.             goto FLASH_ERASE_TRY;
  39.         }
  40.         else
  41.         {
  42.             HAL_FLASH_Lock();
  43.             dprintf("Flash Erase Fail...\r\n");
  44.             return 2;
  45.         }
  46.     }


  47.     tryCount = 0;
  48.     for (i = 0; i < len; ++i)
  49.     {
  50.         while(tryCount < FLASH_OPT_TRY_COUNT)
  51.         {
  52.             if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, startAddr, pDat) == HAL_OK)
  53.             {
  54.                 startAddr += 8;
  55.                 tryCount   = 0;
  56.                 break;
  57.             }
  58.             else
  59.             {
  60.                 FLASH_WaitForLastOperation(50);
  61.                 tryCount++;
  62.             }
  63.         }

  64.         if (tryCount)
  65.         {
  66.             HAL_FLASH_Lock();
  67.             dprintf("Write Flash Fail...\r\n");
  68.             return 3;
  69.         }
  70.     }


  71.     dprintf("Write Flash OK...\r\n");
  72.     HAL_FLASH_Lock();
  73.     return 0;

  74. }
复制代码

Flash双字读
  1. /* Read double-word (64-bit) at a specified address */
  2. void vFlash_Read_DoubleWord(u32 startAddr, u64 * pDat, u16 len)
  3. {
  4.     u16 i = 0;

  5.     for(i = 0; i < len; ++i)
  6.     {
  7.         *pDat++ = *(volatile u64 *)(startAddr + (i << 3));
  8.     }
  9. }
复制代码

Flash读写擦除测试
  1. typedef struct
  2. {
  3.     eBatteryCap eBatCap;    /* 电池容量 */
  4.     eMeasUnit   eUnit;      /* 测量单位 */

  5.     u8  LowBatFlg;          /* 电池低电标志 */
  6.     u8  MeasType;           /* 测量类型 */
  7.     u16 MeasMaxRange;       /* 测量最大量程 */

  8. }GlobalParamStore, * GlobalParamStore_t;


  9. typedef struct
  10. {
  11.     u8  AngleDemarFlg;       /* 角度标定标志 */
  12.     s16 AngleDemarVal;       /* 角度标定值 */


  13.     u8  GyroCaliFlg;        /* 陀螺仪校准标志 */
  14.     s16 xGyroCaliVal;       /* x轴陀螺仪校准值 */
  15.     s16 yGyroCaliVal;       /* y轴陀螺仪校准值 */
  16.     s16 zGyroCaliVal;       /* z轴陀螺仪校准值 */


  17.     u8  DistDemarFlg;        /* 距离标定标志 */
  18.     u8  ZeroDistDemarVal;    /* 零距离标定值 */
  19.     u16 FarDistDemarVal;     /* 远距离标定值 */
  20. }DemarParamStore, * DemarParamStore_t, * pDemarParamStore;

  21. typedef struct
  22. {
  23.     xSuperProductInfo ProInfo;      /* 产品信息 */
  24.     GlobalParamStore  SysPar;       /* 系统参数 */
  25.     DemarParamStore   DemarPar;     /* 标定参数 */


  26.     u8 ubRes[1];                    /* 预留 */
  27.     u8 ubCRC8;                      /* 校验 */
  28. }SystemParamStore, * SystemParamStore_t;





  29. SystemParamStore SystemParam = {0};

  30. /* 保存系统参数 */
  31. void vSave_System_Parameter(void)
  32. {
  33.     u16 len = 0;


  34.     len = XMEM_ALIGN_SIZE(sizeof(SystemParamStore) , 8);
  35.     if (len > (FLASH_PAGE_SIZE >> 3))
  36.     {
  37.         dprintf("System Param Over Flash Page Size...\r\n");
  38.     }
  39.     else
  40.     {
  41.         vSynWrite_System_Parameter();
  42.         SystemParam.ubCRC8 = ubCheckSum_CRC8((void *)(&SystemParam), XOFS(SystemParamStore , ubCRC8));
  43.                 dprintf("SystemParam CRC8...%X\r\n", SystemParam.ubCRC8);
  44.                 if (ubFlash_Write_DoubleWord(SYSTEM_ARG_STORE_START_ADDRE, (u64 *)&SystemParam, len) != 0x00U)
  45. //        if (ubHAL_Flash_Write_DoubleWord(SYSTEM_ARG_STORE_START_ADDRE, (u64 *)&SystemParam, len) != 0x00U)
  46.         {
  47.             dprintf("Save Param Fail...\r\n");
  48.         }
  49.         else
  50.         {
  51.             dprintf("Save Param OK...\r\n");
  52.         }
  53.     }
  54. }





  55. /* 读取系统参数 */
  56. void vRead_System_Parameter(void)
  57. {
  58.     u16 len = 0;
  59.     u8 crc8 = 0;


  60.     AppProInfo = &SystemParam.ProInfo;
  61.     len = XMEM_ALIGN_SIZE(sizeof(SystemParamStore) , 8);
  62.     dprintf("SystemParamStore Size:%d  %d\r\n", sizeof(SystemParamStore), len);

  63.     if (len > (FLASH_PAGE_SIZE >> 3))
  64.     {
  65.         len = (FLASH_PAGE_SIZE >> 3);
  66.         dprintf("System Param Over Flash Page Size...\r\n");
  67.     }

  68.         
  69. #if 1
  70.     vFlash_Read_DoubleWord(SYSTEM_ARG_STORE_START_ADDRE, (u64 *)&SystemParam, len);
  71.     crc8 = ubCheckSum_CRC8((void *)(&SystemParam), XOFS(SystemParamStore , ubCRC8));
  72.     if(crc8 != SystemParam.ubCRC8)
  73.     {
  74.         Restore_Default_SystemParam();
  75.         dprintf("Restore Default Param...%X  %X\r\n", crc8, SystemParam.ubCRC8);
  76.     }
  77.     else
  78.     {
  79.         dprintf("Read System Param OK...\r\n");
  80.     }
  81. #endif

  82.         
  83.     AppProInfo->DevInfo.SWVer.MajorVer = DEV_INFO_SOFT_MAJOR_VER;
  84.     AppProInfo->DevInfo.SWVer.MinorVer = DEV_INFO_SOFT_MINOR_VER;
  85.         

  86.     vSynRead_System_Parameter();
  87.         
  88. //        vShow_ProductInfo();
  89. }
复制代码

测试情况
  1. Init UART OK..
  2. Vref: 3298mV
  3. SystemParamStore Size:88  11
  4. Read System Param OK...
  5. ******************** System Parameter ********************
  6. Meas Masx Range: 20000dm
  7. Angle Demar   : 0 ==> 0
  8. Dist Demar    : 0 ==> 0
  9. Meas Type     : 6
  10. Meas Unit     : 1
  11. Gryo Cali     : 0 ==> 0 0 0
  12. **********************************************************
  13. Gyro Type MPU6887 ID 0x0F
  14. Set Meas Type: 6
  15. Shutdown OverTime: 20s
  16. Bat Sat  : 0
  17. Set Meas Type: 2
  18. Set Meas Type: 9
  19. Set Meas Type: 3
  20. Set Meas Type: 5
  21. Set Meas Type: 7
  22. Set Meas Type: 8
  23. SystemParam CRC8...E7
  24. Write Flash OK...
  25. Save Param OK...
  26. Overtime Shutdown...

  27. Init UART OK..
  28. Vref: 3302mV
  29. SystemParamStore Size:88  11
  30. Read System Param OK...
  31. ******************** System Parameter ********************
  32. Meas Max Range: 20000dm
  33. Angle Demar   : 0 ==> 0
  34. Dist Demar    : 0 ==> 0
  35. Meas Type     : 8
  36. Meas Unit     : 1
  37. Gryo Cali     : 0 ==> 0 0 0
  38. **********************************************************
  39. Gyro Type MPU6887 ID 0x0F
  40. Set Meas Type: 8
  41. Shutdown OverTime: 20s
  42. Bat Sat  : 0
  43. SystemParam CRC8...E7
  44. Write Flash OK...
  45. Save Param OK...
  46. Overtime Shutdown...
复制代码

————————————————
版权声明:凌盛羽



收藏 评论0 发布时间:2022-11-24 15:03

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版