赞
踩
在用G070KBT6芯片调用HAL_FLASHEx_Erase(&EraseInitStruct, &PageError)时,调试发现该函数返回HAL_ERROR,最后定位到FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE)函数出现错误,pFlash.ErrorCode为0xA0,即FLASH错误标志位 FLASH_SR_PGSERR和FLASH_SR_PGAERR被置位;
- static void Flash_EraseSector(uint32_t PageAddress) {
- FLASH_EraseInitTypeDef EraseInitStruct;
- uint32_t PageError = 0;
-
- /* Fill EraseInit structure */
- EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
- EraseInitStruct.Page = (PageAddress - FLASH_BASE) / FLASH_PAGE_SIZE;
- EraseInitStruct.NbPages = 1;
- EraseInitStruct.Banks = FLASH_BANK_1;
-
-
- //FLASH->SR = FLASH_SR_CLEAR;
- if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) {
- /* Error occurred while page erase */
- Flash_Error_Handler();
- }
- }
在网上找半天找不到问题原因,最后在【问题】STM32G0芯片擦除flash失败,发现死在FLASH_SR_CFGBSY一直为1(已解决)_读出的选项字节:芯片做全片擦除失败-CSDN博客
博客和评论区中发现是由于我程序中调用了看门狗喂狗函数,但是为了调试就把看门狗初始化函数注释调了,导致出现FLASH标志位错误,我把喂狗函数也一起注释掉再调试就发现能够正常对FLASH进行擦除。
然后就是对FLASH进行写和读,当我以32位数据为单位对FLASH进行读写时会进入HardFAULT_Handle,后面在这篇博客中发现要改为以64位数据为单位读写才可以;STM32G030F6P6读写flash失败问题(HAL)-CSDN博客
至此,就能对FLASH进行正常擦除和读写,可以用这个将单片机板载FLASH中的一部份区域用作用户数据掉电保存,功能实现和测试代码如下(包括64字节读写和FLASH结构体读写):
- User_Flash.c:
-
- #include "User_Flash.h"
- #include <string.h>
- #include "usart.h"
-
- static void Flash_Error_Handler(void) {
- while (1) {
- // Error handling
- }
- }
-
- /*
- * @function: flash页擦除函数,擦除指定地址所处的页(扇区)
- * @parm1: uint32_t PageAddress 要擦除的页中的任意地址
- */
- static void Flash_EraseSector(uint32_t PageAddress) {
- FLASH_EraseInitTypeDef EraseInitStruct;
- uint32_t PageError = 0;
-
- /* Fill EraseInit structure */
- EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
- EraseInitStruct.Page = (PageAddress - FLASH_BASE) / FLASH_PAGE_SIZE;
- EraseInitStruct.NbPages = 1;
- EraseInitStruct.Banks = FLASH_BANK_1;
-
-
- //FLASH->SR = FLASH_SR_CLEAR;
- if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) {
- /* Error occurred while page erase */
- Flash_Error_Handler();
- }
- }
-
-
-
-
- /*
- * @function: 在指定地址写入32位数据
- 先解锁flash,再擦除指定地址对应页,写入数据,最后重新上锁Flash
- * @parm1: uint32_t Address 要写入的数据起始地址
- * @parm2: uint32_t Data 要写入的数据
- */
- void Flash_WriteData(uint32_t Address, uint64_t Data) {
- HAL_FLASH_Unlock(); //先解锁FLASH
-
- Flash_EraseSector(Address); //擦除要写入的扇区(页)
-
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, Data) == HAL_OK) {
- /* Check the written value */
- if (*(uint64_t*)Address != Data) {
- /* Error occurred while writing data */
- Flash_Error_Handler();
- }
- } else {
- /* Error occurred while writing data */
- Flash_Error_Handler();
- }
-
- HAL_FLASH_Lock(); //重新上锁FLASH
- }
-
-
- /*
- * @function: 读取Flash指定地址的32位数据
- * @parm1: uint32_t Address 要读取的地址
- *
- * @return: 读取的32位数据
- */
- uint64_t Flash_ReadData(uint32_t Address) {
- return *(uint64_t*)Address;
- }
-
- /*
- * @function: 在指定地址写入结构体数据
- 先解锁flash,再擦除指定地址对应页,写入数据,最后重新上锁Flash
- * @parm1: uint32_t Address 要写入的数据起始地址
- * @parm2: MyData_t *data 要写入的结构体数据的指针
- */
- void Flash_WriteStruct(uint32_t Address, MyData_t *data) {
- HAL_FLASH_Unlock(); //先解锁FLASH
- Flash_EraseSector(Address); //擦除要写入的扇区(页)
-
-
- uint64_t *dataPtr = (uint64_t*)data;
- size_t size = sizeof(MyData_t) / 8; // Number of 64-bit words
-
- if (sizeof(MyData_t) % 8 != 0) size++; // handle cases where size is not multiple of 4
-
- // Write the data
- for (size_t i = 0; i < size; i++) {
- if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address + (i * 8), dataPtr[i]) == HAL_OK){
- if (*(uint64_t*)(Address + (i * 8)) != dataPtr[i]) {
- Flash_Error_Handler();
- }
- } else {
- Flash_Error_Handler();
- }
- }
-
-
- HAL_FLASH_Lock(); //重新上锁FLASH
- }
-
- /*
- * @function: 读取Flash指定地址的结构体数据
- * @parm1: uint32_t Address 要读取的地址
- * @parm2: MyData_t *data 读取的结构体数据保存地址
- */
- void Flash_ReadStruct(uint32_t Address, MyData_t *data) {
- uint64_t *pData = (uint64_t*)data;
- uint32_t size = sizeof(MyData_t) / 8; // assuming size is a multiple of 4
- if (sizeof(MyData_t) % 8 != 0) size++; // handle cases where size is not multiple of 4
-
- for (uint32_t i = 0; i < size; i++) {
- pData[i] = *(uint64_t*)(Address + (i * 8));
- }
- }
-
-
-
- /******测试代码******/
- uint64_t data;
- void Flash_Test(void)
- {
- //EraseFlash(63,1);
- Flash_WriteData(FLASH_USER_START_ADDR, DATA_64);
- data = Flash_ReadData(FLASH_USER_START_ADDR);
- if (data == DATA_64) {
- myprintf("Flash_WriteData OK");
- } else {
- myprintf("Flash_WriteData ERROR");// Data write error
- }
-
-
-
- MyData_t myData = {0x12345678, 0xABCD, 0xEF, "Hello"};
- MyData_t readData;
- /* Program the user Flash area */
- Flash_WriteStruct(FLASH_USER_START_ADDR, &myData);
-
- /* Verify the data */
- Flash_ReadStruct(FLASH_USER_START_ADDR, &readData);
-
- // 验证数据
- if (memcmp(&myData, &readData, sizeof(MyData_t)) == 0) {
- myprintf("Flash_WriteStruct OK");// Data written and read correctly
- } else {
- myprintf("Flash_WriteStruct ERROR");// Data write or read error
- }
- }
-
-
-
- User_Flash.h:
- #ifndef __USER_FLASH_H__
- #define __USER_FLASH_H__
-
- #include "stm32g0xx_hal.h"
-
-
- #define FLASH_USER_START_ADDR 0x0801F800 /* G070KBT6 flash大小为128KB,每页2KB,这里用最后一页作为用户数据保存区域 */
- #define FLASH_USER_END_ADDR (0x08020000 - 1) /* End address of Flash */
- //#define FLASH_PAGE_SIZE 2048 /* Page size of 2 KB */
- #define DATA_32 ((uint32_t)0x12345678)
- #define DATA_64 ((uint64_t)0x12345678)
-
- typedef struct {
- uint32_t field1;
- uint16_t field2;
- uint8_t field3;
- char field4[10];
- } MyData_t;
-
- static void Flash_Error_Handler(void) ;
- static void Flash_EraseSector(uint32_t PageAddress) ;
- void Flash_WriteData(uint32_t Address, uint64_t Data);
- uint64_t Flash_ReadData(uint32_t Address);
- void Flash_WriteStruct(uint32_t Address, MyData_t *data) ;
- void Flash_ReadStruct(uint32_t Address, MyData_t *data) ;
- void Flash_Test(void);
-
- #endif
-
-
-
-
-
参考文章:STM32G030F6P6读写flash失败问题(HAL)-CSDN博客
【问题】STM32G0芯片擦除flash失败,发现死在FLASH_SR_CFGBSY一直为1(已解决)_读出的选项字节:芯片做全片擦除失败-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。