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

【经验分享】STM32F1系列HAL库读写内部FLASH

[复制链接]
STMCU小助手 发布时间:2022-4-11 10:16
测试环境:
STM32F103RB
20KBytes RAM
128KBytes FLASH
注:本章节代码只适合STM32F1系列!

20201024152250174.png

头文件

  1. /**
  2. * @brief Create by AnKun on 2019/10/10
  3. */

  4. #ifndef __FLASH_H
  5. #define __FLASH_H

  6. #include "main.h"

  7. 移植修改区 ///

  8. /* FLASH大小:128K */
  9. #define STM32FLASH_SIZE  0x00020000UL

  10. /* FLASH起始地址 */
  11. #define STM32FLASH_BASE  FLASH_BASE

  12. /* FLASH结束地址 */
  13. #define STM32FLASH_END   (STM32FLASH_BASE | STM32FLASH_SIZE)

  14. /* FLASH页大小:1K */
  15. #define STM32FLASH_PAGE_SIZE FLASH_PAGE_SIZE

  16. /* FLASH总页数 */
  17. #define STM32FLASH_PAGE_NUM  (STM32FLASH_SIZE / STM32FLASH_PAGE_SIZE)

  18. /// 导出函数声明
  19. void FLASH_Init(void);
  20. uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size);
  21. uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
  22. int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages);
  23. uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);

  24. #endif // !__FLASH_H

  25. end of file
复制代码

源文件


  1. /**
  2. * @file  flash.c
  3. *
  4. * @brief Create by AnKun on 2019/10/10
  5. *
  6. */

  7. #include "flash.h"
  8. #include <string.h>

  9. static uint16_t FlashBuffer[STM32FLASH_PAGE_SIZE >> 1];

  10. /// 初始化FLASH
  11. void FLASH_Init(void)
  12. {
  13.     HAL_FLASH_Unlock();
  14.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
  15.     HAL_FLASH_Lock();
  16. }

  17. /**
  18. * 读FLASH
  19. * @param  Address 地址
  20. * @param  Buffer  存放读取的数据
  21. * @param  Size    要读取的数据大小,单位字节
  22. * @return         读出成功的字节数
  23. */
  24. uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size)
  25. {
  26.     uint32_t nread = Size;
  27.     uint8_t* d = (uint8_t *)Buffer;
  28.     const uint8_t* s = (const uint8_t *)Address;

  29.     if (!Buffer || Address < STM32FLASH_BASE || Address >= STM32FLASH_END)
  30.         return 0;

  31.     while (nread >= sizeof(uint32_t) && (((uint32_t)s) <= (STM32FLASH_END - 4)))
  32.     {
  33.         *(uint32_t *)d = *(uint32_t *)s;
  34.         d += sizeof(uint32_t);
  35.         s += sizeof(uint32_t);
  36.         nread -= sizeof(uint32_t);
  37.     }

  38.     while (nread && (((uint32_t)s) < STM32FLASH_END))
  39.     {
  40.         *d++ = *s++;
  41.         nread--;
  42.     }

  43.     return Size - nread;
  44. }

  45. /**
  46. * 写FLASH
  47. * @param  Address    写入起始地址,!!!要求2字节对齐!!!
  48. * @param  Buffer     待写入的数据,!!!要求2字节对齐!!!
  49. * @param  NumToWrite 要写入的数据量,单位:半字,!!!要求2字节对齐!!!
  50. * @return            实际写入的数据量,单位:字节
  51. */
  52. uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
  53. {
  54.     uint32_t i = 0;
  55.     uint32_t pagepos = 0;         // 页位置
  56.     uint32_t pageoff = 0;         // 页内偏移地址
  57.     uint32_t pagefre = 0;         // 页内空余空间
  58.     uint32_t offset = 0;          // Address在FLASH中的偏移
  59.     uint32_t nwrite = NumToWrite; // 记录剩余要写入的数据量
  60.     const uint16_t *pBuffer = (const uint16_t *)Buffer;

  61.     /* 非法地址 */
  62.     if (Address < STM32FLASH_BASE || Address > (STM32FLASH_END - 2) || NumToWrite == 0 || pBuffer == NULL)
  63.         return 0;

  64.     /* 解锁FLASH */
  65.     HAL_FLASH_Unlock();

  66.     /* 计算偏移地址 */
  67.     offset = Address - STM32FLASH_BASE;

  68.     /* 计算当前页位置 */
  69.     pagepos = offset / STM32FLASH_PAGE_SIZE;

  70.     /* 计算要写数据的起始地址在当前页内的偏移地址 */
  71.     pageoff = ((offset % STM32FLASH_PAGE_SIZE) >> 1);

  72.     /* 计算当前页内空余空间 */
  73.     pagefre = ((STM32FLASH_PAGE_SIZE >> 1) - pageoff);

  74.     /* 要写入的数据量低于当前页空余量 */
  75.     if (nwrite <= pagefre)
  76.         pagefre = nwrite;

  77.     while (nwrite != 0)
  78.     {
  79.         /* 检查是否超页 */
  80.         if (pagepos >= STM32FLASH_PAGE_NUM)
  81.             break;

  82.         /* 读取一页 */
  83.         FLASH_Read(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE);

  84.         /* 检查是否需要擦除 */
  85.         for (i = 0; i < pagefre; i++)
  86.         {
  87.             if (*(FlashBuffer + pageoff + i) != 0xFFFF) /* FLASH擦出后默认内容全为0xFF */
  88.                 break;
  89.         }

  90.         if (i < pagefre)
  91.         {
  92.             uint32_t count = 0;
  93.             uint32_t index = 0;
  94.             uint32_t PageError = 0;
  95.             FLASH_EraseInitTypeDef pEraseInit;

  96.             /* 擦除一页 */
  97.             pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
  98.             pEraseInit.PageAddress = STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE;
  99.             pEraseInit.Banks = FLASH_BANK_1;
  100.             pEraseInit.NbPages = 1;
  101.             if (HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)
  102.                 break;

  103.             /* 复制到缓存 */
  104.             for (index = 0; index < pagefre; index++)
  105.             {
  106.                 *(FlashBuffer + pageoff + index) = *(pBuffer + index);
  107.             }

  108.             /* 写回FLASH */
  109.             count = FLASH_WriteNotCheck(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE >> 1);
  110.             if (count != (STM32FLASH_PAGE_SIZE >> 1))
  111.             {
  112.                 nwrite -= count;
  113.                 break;
  114.             }
  115.         }
  116.         else
  117.         {
  118.             /* 无需擦除,直接写 */
  119.             uint32_t count = FLASH_WriteNotCheck(Address, pBuffer, pagefre);
  120.             if (count != pagefre)
  121.             {
  122.                 nwrite -= count;
  123.                 break;
  124.             }
  125.         }

  126.         pBuffer += pagefre;         /* 读取地址递增         */
  127.         Address += (pagefre << 1);  /* 写入地址递增         */
  128.         nwrite -= pagefre;          /* 更新剩余未写入数据量 */

  129.         pagepos++;     /* 下一页           */
  130.         pageoff = 0;   /* 页内偏移地址置零  */

  131.         /* 根据剩余量计算下次写入数据量 */
  132.         pagefre = nwrite >= (STM32FLASH_PAGE_SIZE >> 1) ? (STM32FLASH_PAGE_SIZE >> 1) : nwrite;
  133.     }

  134.     /* 加锁FLASH */
  135.     HAL_FLASH_Lock();

  136.     return ((NumToWrite - nwrite) << 1);
  137. }

  138. uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
  139. {
  140.     uint32_t nwrite = NumToWrite;
  141.     uint32_t addrmax = STM32FLASH_END - 2;

  142.     while (nwrite)
  143.     {
  144.         if (Address > addrmax)
  145.             break;

  146.         HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, *Buffer);
  147.         if ((*(__IO uint16_t*) Address) != *Buffer)
  148.             break;

  149.         nwrite--;
  150.         Buffer++;
  151.         Address += 2;
  152.     }
  153.     return (NumToWrite - nwrite);
  154. }

  155. int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages)
  156. {
  157.         uint32_t PageError = 0;
  158.         FLASH_EraseInitTypeDef pEraseInit;
  159.         pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
  160.         pEraseInit.PageAddress = PageAddress;
  161.         pEraseInit.Banks = FLASH_BANK_1;
  162.         pEraseInit.NbPages = 1;
  163.         if(HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)
  164.         {
  165.                 return -1;
  166.         }
  167.         return 0;
  168. }

  169. end of file
复制代码







收藏 评论0 发布时间:2022-4-11 10:16

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版