当前位置:   article > 正文

STM32G070系列芯片擦除、写入Flash错误解决

STM32G070系列芯片擦除、写入Flash错误解决

    在用G070KBT6芯片调用HAL_FLASHEx_Erase(&EraseInitStruct, &PageError)时,调试发现该函数返回HAL_ERROR,最后定位到FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE)函数出现错误,pFlash.ErrorCode为0xA0,即FLASH错误标志位 FLASH_SR_PGSERR和FLASH_SR_PGAERR被置位;

  1. static void Flash_EraseSector(uint32_t PageAddress) {
  2. FLASH_EraseInitTypeDef EraseInitStruct;
  3. uint32_t PageError = 0;
  4. /* Fill EraseInit structure */
  5. EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
  6. EraseInitStruct.Page = (PageAddress - FLASH_BASE) / FLASH_PAGE_SIZE;
  7. EraseInitStruct.NbPages = 1;
  8. EraseInitStruct.Banks = FLASH_BANK_1;
  9. //FLASH->SR = FLASH_SR_CLEAR;
  10. if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) {
  11. /* Error occurred while page erase */
  12. Flash_Error_Handler();
  13. }
  14. }

在网上找半天找不到问题原因,最后在【问题】STM32G0芯片擦除flash失败,发现死在FLASH_SR_CFGBSY一直为1(已解决)_读出的选项字节:芯片做全片擦除失败-CSDN博客

    博客和评论区中发现是由于我程序中调用了看门狗喂狗函数,但是为了调试就把看门狗初始化函数注释调了,导致出现FLASH标志位错误,我把喂狗函数也一起注释掉再调试就发现能够正常对FLASH进行擦除。

然后就是对FLASH进行写和读,当我以32位数据为单位对FLASH进行读写时会进入HardFAULT_Handle,后面在这篇博客中发现要改为以64位数据为单位读写才可以;STM32G030F6P6读写flash失败问题(HAL)-CSDN博客

  至此,就能对FLASH进行正常擦除和读写,可以用这个将单片机板载FLASH中的一部份区域用作用户数据掉电保存,功能实现和测试代码如下(包括64字节读写和FLASH结构体读写):

  1. User_Flash.c:
  2. #include "User_Flash.h"
  3. #include <string.h>
  4. #include "usart.h"
  5. static void Flash_Error_Handler(void) {
  6. while (1) {
  7. // Error handling
  8. }
  9. }
  10. /*
  11. * @function: flash页擦除函数,擦除指定地址所处的页(扇区)
  12. * @parm1: uint32_t PageAddress 要擦除的页中的任意地址
  13. */
  14. static void Flash_EraseSector(uint32_t PageAddress) {
  15. FLASH_EraseInitTypeDef EraseInitStruct;
  16. uint32_t PageError = 0;
  17. /* Fill EraseInit structure */
  18. EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
  19. EraseInitStruct.Page = (PageAddress - FLASH_BASE) / FLASH_PAGE_SIZE;
  20. EraseInitStruct.NbPages = 1;
  21. EraseInitStruct.Banks = FLASH_BANK_1;
  22. //FLASH->SR = FLASH_SR_CLEAR;
  23. if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) {
  24. /* Error occurred while page erase */
  25. Flash_Error_Handler();
  26. }
  27. }
  28. /*
  29. * @function: 在指定地址写入32位数据
  30. 先解锁flash,再擦除指定地址对应页,写入数据,最后重新上锁Flash
  31. * @parm1: uint32_t Address 要写入的数据起始地址
  32. * @parm2: uint32_t Data 要写入的数据
  33. */
  34. void Flash_WriteData(uint32_t Address, uint64_t Data) {
  35. HAL_FLASH_Unlock(); //先解锁FLASH
  36. Flash_EraseSector(Address); //擦除要写入的扇区(页)
  37. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, Data) == HAL_OK) {
  38. /* Check the written value */
  39. if (*(uint64_t*)Address != Data) {
  40. /* Error occurred while writing data */
  41. Flash_Error_Handler();
  42. }
  43. } else {
  44. /* Error occurred while writing data */
  45. Flash_Error_Handler();
  46. }
  47. HAL_FLASH_Lock(); //重新上锁FLASH
  48. }
  49. /*
  50. * @function: 读取Flash指定地址的32位数据
  51. * @parm1: uint32_t Address 要读取的地址
  52. *
  53. * @return: 读取的32位数据
  54. */
  55. uint64_t Flash_ReadData(uint32_t Address) {
  56. return *(uint64_t*)Address;
  57. }
  58. /*
  59. * @function: 在指定地址写入结构体数据
  60. 先解锁flash,再擦除指定地址对应页,写入数据,最后重新上锁Flash
  61. * @parm1: uint32_t Address 要写入的数据起始地址
  62. * @parm2: MyData_t *data 要写入的结构体数据的指针
  63. */
  64. void Flash_WriteStruct(uint32_t Address, MyData_t *data) {
  65. HAL_FLASH_Unlock(); //先解锁FLASH
  66. Flash_EraseSector(Address); //擦除要写入的扇区(页)
  67. uint64_t *dataPtr = (uint64_t*)data;
  68. size_t size = sizeof(MyData_t) / 8; // Number of 64-bit words
  69. if (sizeof(MyData_t) % 8 != 0) size++; // handle cases where size is not multiple of 4
  70. // Write the data
  71. for (size_t i = 0; i < size; i++) {
  72. if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address + (i * 8), dataPtr[i]) == HAL_OK){
  73. if (*(uint64_t*)(Address + (i * 8)) != dataPtr[i]) {
  74. Flash_Error_Handler();
  75. }
  76. } else {
  77. Flash_Error_Handler();
  78. }
  79. }
  80. HAL_FLASH_Lock(); //重新上锁FLASH
  81. }
  82. /*
  83. * @function: 读取Flash指定地址的结构体数据
  84. * @parm1: uint32_t Address 要读取的地址
  85. * @parm2: MyData_t *data 读取的结构体数据保存地址
  86. */
  87. void Flash_ReadStruct(uint32_t Address, MyData_t *data) {
  88. uint64_t *pData = (uint64_t*)data;
  89. uint32_t size = sizeof(MyData_t) / 8; // assuming size is a multiple of 4
  90. if (sizeof(MyData_t) % 8 != 0) size++; // handle cases where size is not multiple of 4
  91. for (uint32_t i = 0; i < size; i++) {
  92. pData[i] = *(uint64_t*)(Address + (i * 8));
  93. }
  94. }
  95. /******测试代码******/
  96. uint64_t data;
  97. void Flash_Test(void)
  98. {
  99. //EraseFlash(63,1);
  100. Flash_WriteData(FLASH_USER_START_ADDR, DATA_64);
  101. data = Flash_ReadData(FLASH_USER_START_ADDR);
  102. if (data == DATA_64) {
  103. myprintf("Flash_WriteData OK");
  104. } else {
  105. myprintf("Flash_WriteData ERROR");// Data write error
  106. }
  107. MyData_t myData = {0x12345678, 0xABCD, 0xEF, "Hello"};
  108. MyData_t readData;
  109. /* Program the user Flash area */
  110. Flash_WriteStruct(FLASH_USER_START_ADDR, &myData);
  111. /* Verify the data */
  112. Flash_ReadStruct(FLASH_USER_START_ADDR, &readData);
  113. // 验证数据
  114. if (memcmp(&myData, &readData, sizeof(MyData_t)) == 0) {
  115. myprintf("Flash_WriteStruct OK");// Data written and read correctly
  116. } else {
  117. myprintf("Flash_WriteStruct ERROR");// Data write or read error
  118. }
  119. }
  120. User_Flash.h:
  121. #ifndef __USER_FLASH_H__
  122. #define __USER_FLASH_H__
  123. #include "stm32g0xx_hal.h"
  124. #define FLASH_USER_START_ADDR 0x0801F800 /* G070KBT6 flash大小为128KB,每页2KB,这里用最后一页作为用户数据保存区域 */
  125. #define FLASH_USER_END_ADDR (0x08020000 - 1) /* End address of Flash */
  126. //#define FLASH_PAGE_SIZE 2048 /* Page size of 2 KB */
  127. #define DATA_32 ((uint32_t)0x12345678)
  128. #define DATA_64 ((uint64_t)0x12345678)
  129. typedef struct {
  130. uint32_t field1;
  131. uint16_t field2;
  132. uint8_t field3;
  133. char field4[10];
  134. } MyData_t;
  135. static void Flash_Error_Handler(void) ;
  136. static void Flash_EraseSector(uint32_t PageAddress) ;
  137. void Flash_WriteData(uint32_t Address, uint64_t Data);
  138. uint64_t Flash_ReadData(uint32_t Address);
  139. void Flash_WriteStruct(uint32_t Address, MyData_t *data) ;
  140. void Flash_ReadStruct(uint32_t Address, MyData_t *data) ;
  141. void Flash_Test(void);
  142. #endif

参考文章:STM32G030F6P6读写flash失败问题(HAL)-CSDN博客

【问题】STM32G0芯片擦除flash失败,发现死在FLASH_SR_CFGBSY一直为1(已解决)_读出的选项字节:芯片做全片擦除失败-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/943365
推荐阅读
相关标签
  

闽ICP备14008679号