FLASH仿EEPROM

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值