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被置位;

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博客

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32G0系列单片机可以使用HAL库提供的函数来将变量写入Flash中。 以下是一个示例代码,将一个16位的整数写入Flash中: ```c #include "stm32g0xx_hal.h" #define FLASH_USER_START_ADDR ADDR_FLASH_PAGE_31 // 定义 Flash 起始地址,这里选择了倒数第二个扇区 #define FLASH_USER_END_ADDR ADDR_FLASH_PAGE_31 + FLASH_PAGE_SIZE - 1 // 定义 Flash 结束地址 uint16_t data = 1234; // 要写入 Flash 的数据 // 函数声明 void WriteToFlash(uint32_t address, uint16_t data); int main(void) { HAL_Init(); // 写入数据到 Flash WriteToFlash(FLASH_USER_START_ADDR, data); while (1) { // 程序执行其他任务 } } // 将数据写入 Flash void WriteToFlash(uint32_t address, uint16_t data) { HAL_StatusTypeDef status = HAL_OK; uint32_t pageError = 0; // 擦除 Flash 扇区 FLASH_EraseInitTypeDef eraseInitStruct; eraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; eraseInitStruct.PageAddress = FLASH_USER_START_ADDR; eraseInitStruct.NbPages = 1; status = HAL_FLASHEx_Erase(&eraseInitStruct, &pageError); if (status != HAL_OK) { // 发生错误,处理错误 return; } // 写入数据到 Flash status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, data); if (status != HAL_OK) { // 发生错误,处理错误 return; } } ``` 在这个示例代码中,我们首先定义了要写入 Flash 的数据 `data`,然后调用 `WriteToFlash()` 函数将数据写入 Flash。该函数首先使用HAL库提供的 `HAL_FLASHEx_Erase()` 函数擦除 Flash 扇区,然后使用 `HAL_FLASH_Program()` 函数将数据写入 Flash。在写入数据之前,我们需要定义要写入Flash 起始地址,并且要确保不会写入到 Bootloader 或其他重要数据的位置。此外,还需要注意的是,STM32G0系列单片机Flash只能写入半字(16位),因此在这个示例中,我们使用 `FLASH_TYPEPROGRAM_HALFWORD` 来指定写入半字。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值