1.dFlash.h文件
/*
* Driver_Flash.h
*
* Created on: 2023/8/24
* Author: WZX
*/
#ifndef _DRIVER_FLASH_H_
#define _DRIVER_FLASH_H_
#include <stdint.h>
#include <stdbool.h>
/**
* @brief 队列状态标志
*/
typedef union __Flash_Para
{
uint32_t word;
struct
{
uint8_t yuliu :6;
uint8_t Error :1;
uint8_t flag :1;
uint8_t ID;
uint16_t data;
} fun;
} Flash_Para;
/**
* @brief 队列状态标志
*/
typedef struct
{
uint32_t Start_Address; /*!< 擦写起始地址 */
uint32_t End_Address; /*!< 擦写结束地址 */
uint32_t Program_Size; /*!< 擦写区域大小 */
uint32_t Default_Data; /*!< 擦写默认数据 */
uint8_t Erase_Flag; /*!< 擦写数据是否用完 */
uint8_t Type_Program; /*!< 擦写类型:(n)byte */
uint8_t Data_size; /*!< 擦写数据大小 */
Flash_Para *pdata; /*!< 擦写数据首地址 */
void (*flash_read_data)(uint32_t *pData, uint32_t ReadAddr);
uint8_t (*flash_write_data)(uint32_t Data, uint32_t WriteAddr);
void (*flash_erase_block)(uint32_t Address);
} Flash_Ctrl_t;
void dFlash_Init(Flash_Ctrl_t *flash_ctrl_t);
uint8_t dFlash_Get_Status(void);
void dFlash_Erase(void);
void dFlash_Write(uint8_t ID, uint16_t data, bool State);
uint16_t dFlash_Read(uint8_t ID);
#endif
2.dFlash.c文件
/*
* dFlash.h
*
* Created on: 2024/5/28
* Author: WZX
*/
#include "dFlash.h"
#include <stddef.h>
#include <stdlib.h>
static Flash_Ctrl_t *flash_ctrl = NULL;
/*********************************************************************
* @fn dFlash_Init
*
* @brief Initializes the flash data.
*
* @param none
*
* @return none
*/
void dFlash_Init(Flash_Ctrl_t *flash_ctrl_t)
{
uint8_t i, id;
uint32_t flashMessage;
if(flash_ctrl_t == NULL)
{
return;
}
flash_ctrl = flash_ctrl_t;
flash_ctrl->flash_read_data((uint32_t *)&flashMessage, flash_ctrl->Start_Address);
if(flashMessage == flash_ctrl->Default_Data)
{
for(i = 0; i < flash_ctrl->Data_size; i++)
{
flash_ctrl->flash_write_data(flash_ctrl->pdata[i].word, flash_ctrl->Start_Address);
flash_ctrl->Start_Address += flash_ctrl->Type_Program;
}
}
else
{
while(1)
{
id = (flashMessage & 0xFF00) >> 8;
if(id < flash_ctrl->Data_size)
{
flash_ctrl->pdata[id].word = flashMessage;
}
flash_ctrl->Start_Address += flash_ctrl->Type_Program;
flash_ctrl->flash_read_data((uint32_t *)&flashMessage, flash_ctrl->Start_Address);
if(flashMessage == flash_ctrl->Default_Data)
{
break;
}
if(flash_ctrl->Start_Address > flash_ctrl->End_Address)
{
flash_ctrl->Start_Address = flash_ctrl->End_Address - flash_ctrl->Program_Size;
break;
}
}
}
}
/*********************************************************************
* @fn dFlash_Erase
*
* @brief flash write data.
*
* @param none
*
* @return none
*/
void dFlash_Erase(void)
{
uint8_t i, count = 0;
if(flash_ctrl->Erase_Flag)
{
__disable_irq();
for(i = 0; i < flash_ctrl->Data_size; i++)
{
if(flash_ctrl->pdata[i].fun.flag == true)
{
count++;
}
}
if((flash_ctrl->End_Address - flash_ctrl->Start_Address)/flash_ctrl->Type_Program < count)
{
flash_ctrl->Start_Address = flash_ctrl->End_Address - flash_ctrl->Program_Size;
flash_ctrl->flash_erase_block(flash_ctrl->Start_Address);
}
for(i = 0; i < flash_ctrl->Data_size; i++)
{
if(flash_ctrl->pdata[i].fun.flag == true)
{
dFlash_Write(i, flash_ctrl->pdata[i].fun.data, false);
if(flash_ctrl->flash_write_data(flash_ctrl->pdata[i].word, flash_ctrl->Start_Address) != 0)
{
flash_ctrl->pdata[i].fun.Error = 1;
}
flash_ctrl->Start_Address += flash_ctrl->Type_Program;
}
}
flash_ctrl->Erase_Flag = 0;
__enable_irq();
}
}
/*********************************************************************
* @fn dFlash_Write
*
* @brief write flash data.
*
* @param ID : flash write id
*
* @param data: flash write data
*
* @return none
*/
void dFlash_Write(uint8_t ID, uint16_t data, bool State)
{
uint32_t temp;
temp = flash_ctrl->pdata[ID].word;
if(State == true)
{
temp |= (1<<7);
flash_ctrl->Erase_Flag = 1;
}
else
{
temp &= ~(1<<7);
}
temp = (temp & 0xffff) | (data << 16);
flash_ctrl->pdata[ID].word = temp;
}
/*********************************************************************
* @fn dFlash_Read
*
* @brief read flash data.
*
* @param ID : flash write id
*
* @return data: flash read data
*/
uint16_t dFlash_Read(uint8_t ID)
{
return flash_ctrl->pdata[ID].fun.data;
}
3.例程
dFlash.h和dFlash.c文件可以适配绝大多数flash
/*
* Cmd_Flash.c
*
* Created on: 2024/5/28
* Author: WZX
*/
/* Includes ------------------------------------------------------------------*/
#include "Cmd_Flash.h"
#include "dFlash.h"
#include "stm32f1xx.h"
/* Private functions prototypes ----------------------------------------------*/
static void cmd_flash_read_data(uint32_t *pData, uint32_t ReadAddr);
static uint8_t cmd_flash_write_data(uint32_t Data, uint32_t WriteAddr);
static void cmd_flash_erase_block(uint32_t Address);
/*********************************************************************
* @fn Cmd_Flash_Init
*
* @brief flash初始化.
*
* @param none
*
* @return none
*/
void Cmd_Flash_Init(void)
{
static Flash_Ctrl_t flash;
uint32_t end_addr;
uint32_t pro_size = 0x000003FFU; //0xFF--256byte, 0x3FF--1kbyte, 0x7ff--2kbyte, 0xfff--4kbyte
static Flash_Para flash_data[End_Rec_ID] =
{
{.fun.ID = 0, .fun.data = 0x0001, .fun.flag = false, .fun.Error = 0, .fun.yuliu = 0},
{.fun.ID = 1, .fun.data = 0x0000, .fun.flag = false, .fun.Error = 0, .fun.yuliu = 0},
{.fun.ID = 2, .fun.data = 0x0001, .fun.flag = false, .fun.Error = 0, .fun.yuliu = 0},
};
switch((*((uint16_t*) FLASH_SIZE_DATA_REGISTER)))
{
case 0x200U:
end_addr = 0x0807FFFFU; /* 512k */
break;
case 0x120U:
end_addr = 0x08047FFFU; /* 288k */
break;
case 0x100U:
end_addr = 0x0803FFFFU; /* 256k */
break;
case 0x80U:
end_addr = 0x0801FFFFU; /* 128k */
break;
case 0x40U:
end_addr = 0x0800FFFFU; /* 64k */
break;
case 0x20U:
end_addr = 0x08007FFFU; /* 32k */
break;
default:
end_addr = 0x08003FFFU; /* 16k */
break;
}
flash.Program_Size = pro_size;
flash.Start_Address = end_addr - flash.Program_Size;
flash.End_Address = end_addr;
flash.Default_Data = 0xFFFFFFFFU;
flash.Type_Program = 4;
flash.Erase_Flag = 0;
flash.Data_size = End_Rec_ID;
flash.pdata = &flash_data[0];
flash.flash_read_data = cmd_flash_read_data;
flash.flash_write_data = cmd_flash_write_data;
flash.flash_erase_block = cmd_flash_erase_block;
dFlash_Init(&flash);
}
//flash读地址中数据
static void cmd_flash_read_data(uint32_t *pData, uint32_t ReadAddr)
{
*pData = (*(__IO uint16_t*)ReadAddr) | (*(__IO uint16_t*)(ReadAddr + 2) << 16);
}
//flash写地址数据
static uint8_t cmd_flash_write_data(uint32_t Data, uint32_t WriteAddr)
{
uint8_t err = 0;
HAL_FLASH_Unlock();
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, WriteAddr, Data) != HAL_OK)
{
err = 1;
}
HAL_FLASH_Lock();
return err;
}
//flash擦除块数据
static void cmd_flash_erase_block(uint32_t Address)
{
FLASH_EraseInitTypeDef EraseFlash_Config;
uint32_t PagError = 0;
EraseFlash_Config.TypeErase = FLASH_TYPEERASE_PAGES;
EraseFlash_Config.PageAddress = Address;
EraseFlash_Config.NbPages = 1;
HAL_FLASH_Unlock();
HAL_FLASHEx_Erase(&EraseFlash_Config, (uint32_t *)&PagError);
HAL_FLASH_Lock();
}
在50ms轮询擦写函数
/*********************************************************************
* @fn task50ms
*
* @brief 50ms任务.
*
* @param none
*
* @return none
*/
void task50ms(void *pvParameters)
{
dFlash_Erase();
}
4.优化修改
1.2024.9.20
/*
* Wos_Flash.h
*
* Created on: 2023/8/24
* Author: WZX
*/
#ifndef _WOS_FLASH_H_
#define _WOS_FLASH_H_
#include <stdint.h>
#define Flash_Error_Type_None 0 /*!< 错误类型:无 */
#define Flash_Erroe_Type_Fail 1 /*!< 错误类型:失败 */
#define Flash_Earse_End 0 /*!< 数据擦写结束 */
#define Flash_Earse_Start 1 /*!< 数据擦写开始 */
#define Flash_Data_Size_Type 2 /*!< 数据类型大小:2*1byte */
#define Flash_Data_Erroe 0xFFFF /*!< 读数据出错的数据 */
/**
* @brief 数据参数
*/
typedef union
{
uint32_t Word;
struct
{
uint16_t CRC4Data :4; /*!< CRC4校验数据 */
uint16_t ErrorType :1; /*!< 错误类型 */
uint16_t EraseFlag :1; /*!< 擦写标志位 */
uint16_t ID :10; /*!< 数据标识符 */
uint16_t Data; /*!< 存储的数据 */
} Bit;
} Flash_Para;
/**
* @brief 擦写数据参数
*/
typedef struct
{
uint32_t Start_Address; /*!< 擦写起始地址 */
uint32_t End_Address; /*!< 擦写结束地址 */
uint32_t Program_Size; /*!< 擦写区域大小 */
uint32_t Default_Data; /*!< 擦写默认数据 */
uint8_t Erase_Flag; /*!< 擦写数据是否用完 */
uint8_t Type_Program; /*!< 擦写类型:(n)byte */
uint8_t Data_Size; /*!< 擦写数据大小 */
Flash_Para *pData; /*!< 擦写数据首地址 */
void (*Flash_Read_Data)(uint32_t *pData, uint32_t ReadAddr); /*!< 读flash数据 */
uint8_t (*Flash_Write_Data)(uint32_t Data, uint32_t WriteAddr); /*!< 写flash数据 */
void (*Flash_Erase_Block)(uint32_t Address); /*!< 擦除数据块 */
} Flash_Ctrl_t;
void dFlash_Init(Flash_Ctrl_t *flash_ctrl_t);
void dFlash_Erase(void);
void dFlash_Write(uint8_t ID, uint16_t data, uint8_t State);
uint16_t dFlash_Read(uint8_t ID);
#endif
/*
* Wos_Flash.h
*
* Created on: 2024/5/28
* Author: WZX
*/
#include "Wos_Flash.h"
#include "dCRC.h"
#include <stddef.h>
#include <stdlib.h>
static Flash_Ctrl_t *flash_ctrl = NULL;
/*********************************************************************
* @fn dFlash_Init
*
* @brief Initializes the flash data.
*
* @param none
*
* @return none
*/
void dFlash_Init(Flash_Ctrl_t *flash_ctrl_t)
{
uint8_t i, crc_temp;
Flash_Para flashMessage;
if(flash_ctrl_t == NULL)
{
return;
}
flash_ctrl = flash_ctrl_t;
flash_ctrl->Flash_Read_Data((uint32_t *)&flashMessage, flash_ctrl->Start_Address);
if(flashMessage.Word == flash_ctrl->Default_Data)
{
for(i = 0; i < flash_ctrl->Data_Size; i++)
{
flash_ctrl->pData[i].Bit.CRC4Data = CRC_4((uint8_t *)&flash_ctrl->pData[i].Bit.Data, \
Flash_Data_Size_Type);
flash_ctrl->Flash_Write_Data(flash_ctrl->pData[i].Word, flash_ctrl->Start_Address);
flash_ctrl->Flash_Read_Data((uint32_t *)&flashMessage, flash_ctrl->Start_Address);
if(flashMessage.Word != flash_ctrl->pData[i].Word)
{
flash_ctrl->pData[i].Bit.ErrorType = Flash_Erroe_Type_Fail;
}
else
{
flash_ctrl->Start_Address += flash_ctrl->Type_Program;
}
}
}
else
{
while(1)
{
if(flashMessage.Bit.ID < flash_ctrl->Data_Size)
{
crc_temp = CRC_4((uint8_t *)&flashMessage.Bit.Data, Flash_Data_Size_Type);
if(crc_temp != flashMessage.Bit.CRC4Data)
{
flash_ctrl->pData[flashMessage.Bit.ID].Bit.ErrorType = Flash_Erroe_Type_Fail;
flash_ctrl->pData[flashMessage.Bit.ID].Bit.Data = Flash_Data_Erroe;
}
else
{
flash_ctrl->pData[flashMessage.Bit.ID].Bit.Data = flashMessage.Bit.Data;
}
}
flash_ctrl->Start_Address += flash_ctrl->Type_Program;
flash_ctrl->Flash_Read_Data((uint32_t *)&flashMessage, flash_ctrl->Start_Address);
if(flashMessage.Word == flash_ctrl->Default_Data)
{
break;
}
if(flash_ctrl->Start_Address > flash_ctrl->End_Address)
{
flash_ctrl->Start_Address = flash_ctrl->End_Address - flash_ctrl->Program_Size;
break;
}
}
}
}
/*********************************************************************
* @fn dFlash_Erase
*
* @brief flash write data.
*
* @param none
*
* @return none
*/
void dFlash_Erase(void)
{
uint8_t i, count = 0;
Flash_Para flashMessage;
if(flash_ctrl->Erase_Flag == Flash_Earse_Start)
{
__disable_irq();
for(i = 0; i < flash_ctrl->Data_Size; i++)
{
if(flash_ctrl->pData[i].Bit.EraseFlag == Flash_Earse_Start)
{
count++;
}
}
if((flash_ctrl->End_Address - flash_ctrl->Start_Address)/flash_ctrl->Type_Program < count)
{
flash_ctrl->Start_Address = flash_ctrl->End_Address - flash_ctrl->Program_Size;
flash_ctrl->Flash_Erase_Block(flash_ctrl->Start_Address);
for(i = 0; i < flash_ctrl->Data_Size; i++)
{
flash_ctrl->Flash_Write_Data(flash_ctrl->pData[i].Word, flash_ctrl->Start_Address);
flash_ctrl->Flash_Read_Data((uint32_t *)&flashMessage, flash_ctrl->Start_Address);
if(flashMessage.Word != flash_ctrl->pData[i].Word)
{
flash_ctrl->pData[i].Bit.ErrorType = Flash_Erroe_Type_Fail;
}
else
{
flash_ctrl->Start_Address += flash_ctrl->Type_Program;
}
if(flash_ctrl->pData[i].Bit.EraseFlag == Flash_Earse_Start)
{
flash_ctrl->pData[i].Bit.EraseFlag = Flash_Earse_End;
}
}
}
else
{
for(i = 0; i < flash_ctrl->Data_Size; i++)
{
if(flash_ctrl->pData[i].Bit.EraseFlag == Flash_Earse_Start)
{
flash_ctrl->pData[i].Bit.EraseFlag = Flash_Earse_End;
if(flash_ctrl->Flash_Write_Data(flash_ctrl->pData[i].Word, flash_ctrl->Start_Address) != 0)
{
flash_ctrl->pData[i].Bit.ErrorType = Flash_Erroe_Type_Fail;
}
flash_ctrl->Start_Address += flash_ctrl->Type_Program;
}
}
}
flash_ctrl->Erase_Flag = Flash_Earse_End;
__enable_irq();
}
}
/*********************************************************************
* @fn dFlash_Write
*
* @brief write flash data.
*
* @param ID : flash write id
*
* @param data: flash write data
*
* @return none
*/
void dFlash_Write(uint8_t ID, uint16_t data, uint8_t State)
{
flash_ctrl->pData[ID].Bit.CRC4Data = CRC_4((uint8_t *)&data, Flash_Data_Size_Type);
flash_ctrl->pData[ID].Bit.Data = data;
flash_ctrl->pData[ID].Bit.EraseFlag = State;
flash_ctrl->Erase_Flag = Flash_Earse_Start;
}
/*********************************************************************
* @fn dFlash_Read
*
* @brief read flash data.
*
* @param ID : flash write id
*
* @return data: flash read data
*/
uint16_t dFlash_Read(uint8_t ID)
{
return flash_ctrl->pData[ID].Bit.Data;
}