大家在使用 GD25Q64 存储东西时,如果没有移植现有文件系统。那是怎么存储的呢?
这里给大家推荐一种方式。动态链表存储。写的还不太完善,最近太累了,没时间完善了。
# 理念
如果一块控件不够存储了,可以再创建一块
# 代码实现
memory.h
#ifndef __MEMORYMANAGEMENT_H | |
#define __MEMORYMANAGEMENT_H | |
#include "gd32f30x.h" | |
#include <stdbool.h> | |
// 起始地址 | |
#define MEMORYSTARTADD 0 | |
// 内存大小 | |
#define MEMORYSIZE 2048 | |
// 每一块的大小 | |
#define MEMORYCHUNKINGSIZE 256 | |
// 块内每一组数据的长度 | |
#define MEMORYEACHGROUPDATALENGTH 16 | |
// 读出内存数据的缓存 | |
#define MEMORYREADBUFFERSIZE 256 | |
// 内存管理初始化结构体 | |
typedef struct | |
{ | |
uint32_t memorysize; | |
uint32_t memorystartaddress; | |
uint32_t memorychunkingsize; | |
uint32_t Datalengthforeachgroup; | |
uint8_t chunkinghead[8]; | |
uint8_t chunkingtail[8]; | |
void (*FlashWrite)(uint8_t *data,uint32_t address,uint32_t length); | |
void (*FlashRead)(uint8_t *data,uint32_t address,uint32_t length); | |
void (*FlashErase)(uint32_t address,uint32_t length); | |
} MemoryInit_struct; | |
// 每一块可以存储多少组数据 | |
#define EACHCHUNKINGDATAGROUP ((MEMORYCHUNKINGSIZE-40)/MEMORYEACHGROUPDATALENGTH) | |
typedef union | |
{ | |
struct | |
{ | |
uint8_t flag[4]; | |
uint8_t index[4]; | |
} Info; | |
uint8_t Byte[8]; | |
} Memoryinfomation_union; | |
// 块内元素的定位 | |
enum { | |
POS_DATA_chunkinghead = 0, | |
POS_DATA_infomation = 8, | |
POS_DATA_datalength = 16, | |
POS_DATA_storagenum = 18, | |
POS_DATA_data = 20, | |
POS_DATA_previouspageadd = MEMORYCHUNKINGSIZE-8-4-4-4, | |
POS_DATA_currentpageadd = MEMORYCHUNKINGSIZE-8-4-4, | |
POS_DATA_nextpageadd = MEMORYCHUNKINGSIZE-8-4, | |
POS_DATA_chunkingtail = MEMORYCHUNKINGSIZE-8, | |
}; | |
// 内存读出缓存共用体 | |
typedef union | |
{ | |
struct | |
{ | |
// 块头 | |
uint8_t chunkinghead[8]; | |
// 块信息 | |
Memoryinfomation_union infomation; | |
// 块存储的数据组数(总数,这个是真实存储的数量)删除后减少 | |
uint8_t datanum[2]; | |
// 当前块的存储数据组数(存储数量,这个删除后不减少,继续往后写入) | |
uint8_t storagenum[2]; | |
// 数据主体 | |
uint8_t data[EACHCHUNKINGDATAGROUP][MEMORYEACHGROUPDATALENGTH]; | |
// 地址索引 | |
uint8_t previouspageadd[4];// 上一页 | |
uint8_t currentpageadd[4];// 当前页 | |
uint8_t nextpageadd[4];// 下一页 | |
// 块尾 | |
uint8_t chunkingtail[8]; | |
} Info; | |
uint8_t Byte[MEMORYCHUNKINGSIZE]; | |
} MemoryData_union; | |
// 内存块索引结构体 | |
typedef union | |
{ | |
struct | |
{ | |
uint8_t infomation[8]; | |
uint8_t currentpageadd[4]; | |
} Info; | |
uint8_t Byte[12]; | |
} MemoryIndex_union; | |
// 内存管理控制结构体 | |
typedef struct | |
{ | |
void (*CreatChunking)(uint8_t *index, uint8_t *info); | |
void (*InquiryChunking)(uint8_t *data,uint32_t address,uint32_t length); | |
void (*DeleteChunking)(uint32_t address,uint32_t length); | |
bool (*Insert)(uint8_t *index,uint8_t *data,uint32_t group); | |
void (*Delete)(uint8_t *index,uint8_t *data,uint32_t group); | |
void (*Inquiry)(uint8_t *index); | |
}Memory_Control; | |
// 存储块的首地址 | |
#define MEMORYINDEX_CHUNKINGINDEX_FIRSTADDRESS (MEMORYSTARTADD+256) | |
// 用来存储块的索引的页数 | |
#define MEMORYINDEX_CHUNKINGINDEX_NUM ((MEMORYSIZE/4096)+1) | |
// 块索引的大小 | |
#define MEMORYINDEX_SIZE (MEMORYINDEX_CHUNKINGINDEX_NUM*256) | |
// 块索引数量的最大值 | |
#define MEMORYINDEX_CHUNKINGINFO_NUM (MEMORYINDEX_SIZE/12) | |
// 用来存储数据的块的个数(总大小 - 首页存储数量 - 存储索引)/ 每一块的大小 | |
#define MEMORYDATA_CHUNKING_NUMBER ((MEMORYSIZE-256-MEMORYINDEX_SIZE)/MEMORYCHUNKINGSIZE) | |
// 存储数据区的起始地址 | |
#define MEMORYDATA_CHUNKING_STARTADDRESS (MEMORYSTARTADD+256+MEMORYINDEX_SIZE) | |
// 内存管理结构体 | |
typedef struct | |
{ | |
MemoryInit_struct config; | |
Memory_Control control; | |
MemoryData_union data; | |
MemoryIndex_union index[MEMORYINDEX_CHUNKINGINFO_NUM]; | |
}Memory_Struct; | |
// 向存储块中插入数据 | |
bool bmemoryInsert(uint8_t *index, uint8_t *data, uint32_t group); | |
// 删除存储块中的数据 | |
void vmemoryDelete(uint8_t *index,uint8_t *data,uint32_t group); | |
// 获取基本信息 地址 存储数据数量 | |
void vmemoryInquiry(uint8_t *index); | |
// 复制数组 | |
void vmemorymamagementCopyArray(const uint8_t *source, uint8_t *target, uint32_t length); | |
// 判断两个数组是否相同 | |
bool bmemoryCheckArraySame(uint8_t *sourcearray, uint8_t *targetarray, uint32_t len); | |
// 二分法获取存储数据的地址,拿到的是数据后的第一个 FF 的地址 | |
uint32_t uimemoryGetDataPos(uint32_t Startaddress, uint32_t length); | |
// 获取一个空闲存储块 | |
uint32_t uimemoryGetFreeAddress(void); | |
// 清空数组 | |
void vmemorymamagementClearArray(uint8_t *source, uint32_t length); | |
// 输入 uint32_t 类型,输出一个 uint8_t 数组 | |
uint8_t * vmemorymamagementGetAddressArray(uint32_t address); | |
// 获取块索引的地址 | |
uint32_t vmemorymamagementGetChunkingnumberAddress(uint8_t chunkingnumber); | |
//uint8_t 数组转 uint32_t | |
uint32_t vmemory_U8Arr_To_uint32(uint8_t *arr); | |
// 获取块首地址 | |
uint32_t uimemoryGetChunkAdd(uint8_t *index); | |
// 初始化 | |
void vMemoryControlInit(MemoryInit_struct *Config); | |
// 创建一个新的块并完成初始化 | |
void vmemoryChunkingCreatBase(uint8_t *index,uint32_t creataddress,uint8_t chunkingnumber); | |
// 获取块的 Index 下的所有存储 data-> 读取到 bymemoryreadbuffer | |
void vmemoryInquiryList(uint8_t *index); | |
// 获取块下数据的添加地址 | |
uint32_t uimemoryGetChunkAddDataAdd(uint8_t *index); | |
// 根据块索引和当前块地址,创建下一块 | |
uint8_t *pmemoryCreatNextChunk(uint8_t *index,uint8_t *address); | |
#endif //__MEMORYMANAGEMENT_H |
memory.c
#include "stdio.h" | |
#include "stdlib.h" | |
#include "MemoryManagement.h" | |
#include <string.h> | |
// 内存管理结构体 | |
Memory_Struct Memory; | |
// 读取数据的缓存 | |
uint8_t bymemoryreadbuffer[MEMORYREADBUFFERSIZE]; | |
// 空白数据比较数组 | |
uint8_t bycheckarray[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | |
/*********************************************************** | |
*@fuction :vmemorymamagementInit | |
*@brief : 初始化内存管理系统的 demo | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-05-23 | |
***********************************************************/ | |
void vmemorymamagementInit(void) | |
{ | |
// 创建一个初始化结构体 | |
MemoryInit_struct memoryinitstruct; | |
// 设置内存大小 | |
memoryinitstruct.memorysize = MEMORYSIZE; | |
// 设置起始地址 | |
memoryinitstruct.memorystartaddress = MEMORYSTARTADD; | |
// 设置每一块的大小 | |
memoryinitstruct.memorychunkingsize = MEMORYCHUNKINGSIZE; | |
// 存储块内每一组数据的长度 | |
memoryinitstruct.Datalengthforeachgroup = MEMORYEACHGROUPDATALENGTH; | |
// 块起始的定位值 | |
uint8_t datahead[4] = {0xBB, 0xBB, 0xBB, 0xBB}; | |
vmemorymamagementCopyArray(datahead, memoryinitstruct.chunkinghead, 4); | |
// 块结束的值 | |
uint8_t datatail[4] = {0xEE, 0xEE, 0xEE, 0xEE}; | |
vmemorymamagementCopyArray(datatail, memoryinitstruct.chunkingtail, 4); | |
// 传递函数指针作为接口 | |
memoryinitstruct.FlashErase = vgd25q64FlushDel; | |
memoryinitstruct.FlashRead = vgd25q64ReadData; | |
memoryinitstruct.FlashWrite = vgd25q64FlushWrite; | |
// 初始化 | |
vMemoryControlInit(&memoryinitstruct); | |
} | |
/*********************************************************** | |
*@fuction :vMemoryControlInit | |
*@brief : 初始化结构体,配置信息和接口调用 | |
*@param :MemoryInit_struct | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-05-23 | |
***********************************************************/ | |
void vMemoryControlInit(MemoryInit_struct *Config) | |
{ | |
// 配置起始地址 | |
Memory.config.memorystartaddress = Config->memorystartaddress; | |
// 配置内存大小 | |
Memory.config.memorysize = Config->memorysize; | |
// 配置内存管理分配的每一块内存的大小 | |
Memory.config.memorychunkingsize = Config->memorychunkingsize; | |
// 写入数据的接口 | |
Memory.config.FlashWrite = Config->FlashWrite; | |
// 读取数据的接口 | |
Memory.config.FlashRead = Config->FlashRead; | |
// 擦除数据的接口 | |
Memory.config.FlashErase = Config->FlashErase; | |
// 存储块内每一组数据的长度 | |
Memory.config.Datalengthforeachgroup = Config->Datalengthforeachgroup; | |
// 每一块的起始值 | |
vmemorymamagementCopyArray(Config->chunkinghead, Memory.config.chunkinghead, 4); | |
// 每一块的结尾的值 | |
vmemorymamagementCopyArray(Config->chunkingtail, Memory.config.chunkingtail, 4); | |
// 内存管理的外部调用函数 | |
// 删除 | |
Memory.control.Delete = vmemoryDelete; | |
// 查询 | |
Memory.control.Inquiry = vmemoryInquiry; | |
// 插入 | |
Memory.control.Insert = bmemoryInsert; | |
} | |
/*********************************************************** | |
*@fuction :vmemoryChunkingCreat | |
*@brief : 创建一个存储块 | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-05-23 | |
***********************************************************/ | |
void vmemoryChunkingCreat(uint8_t *index, uint8_t *info) | |
{ | |
// 创建一个变量读出有多少个块 | |
uint8_t chunkingnumber = 0; | |
// 用二分查找法定位第一页存储的块数量的信息 | |
Memory.config.FlashRead(&chunkingnumber, uimemoryGetDataPos(Memory.config.memorystartaddress, 256) - 1, 1); | |
// 如果块是 FF,一块也没有 -> 初始化为 0 | |
if(chunkingnumber == 0xFF) | |
{ | |
chunkingnumber = 0x00; | |
Memory.config.FlashWrite(&chunkingnumber, uimemoryGetDataPos(Memory.config.memorystartaddress, 256), 1); | |
} | |
// 读出块索引的信息,index 重复了 | |
if(uimemoryGetChunkAdd(index) != 0) | |
return; | |
// 获取一个空闲的块地址 | |
uint32_t creataddress = uimemoryGetFreeAddress(); | |
if(creataddress == 0) | |
{ | |
// 没有空闲块了 | |
return; | |
} | |
// 创建块 | |
vmemoryChunkingCreatBase(index, creataddress, chunkingnumber); | |
} | |
/*********************************************************** | |
*@fuction :vmemoryChunkingCreatBase | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-28 | |
***********************************************************/ | |
void vmemoryChunkingCreatBase(uint8_t *index, uint32_t creataddress, uint8_t chunkingnumber) | |
{ | |
// 写入块头 | |
memset(Memory.config.chunkinghead+4,Memory.config.chunkinghead[0],4);// 此处标识为首块 | |
Memory.config.FlashWrite(Memory.config.chunkinghead, creataddress, 8); | |
// 写入块信息 | |
vmemorymamagementClearArray(Memory.data.Info.infomation.Info.flag, 4); | |
vmemorymamagementCopyArray(index, Memory.data.Info.infomation.Info.index, 4); | |
Memory.config.FlashWrite(Memory.data.Info.infomation.Byte, creataddress, 8); | |
// 写入当前页地址 | |
Memory.config.FlashWrite(vmemorymamagementGetAddressArray(creataddress), creataddress + POS_DATA_currentpageadd, 4); | |
// 写入块尾 | |
Memory.config.FlashWrite(Memory.config.chunkingtail, creataddress + POS_DATA_chunkingtail, 8); | |
// 写入索引表 | |
vmemorymamagementCopyArray(Memory.data.Info.infomation.Byte, Memory.index[chunkingnumber].Info.infomation, 8); | |
vmemorymamagementCopyArray(vmemorymamagementGetAddressArray(creataddress), Memory.index[chunkingnumber].Info.currentpageadd, 4); | |
Memory.config.FlashWrite(Memory.index[chunkingnumber].Byte, vmemorymamagementGetChunkingnumberAddress(chunkingnumber), 12); | |
// 写入数量 | |
Memory.config.FlashWrite(&chunkingnumber, uimemoryGetDataPos(MEMORYSTARTADD, 256), 1); | |
} | |
/*********************************************************** | |
*@fuction :vmemoryChunkingDelete | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-05-23 | |
***********************************************************/ | |
void vmemoryChunkingDelete(uint8_t *index, uint8_t *info) | |
{ | |
//1、找块地址 | |
uint32_t delChunkadd = uimemoryGetChunkAdd(index); | |
// 没找到 | |
if(delChunkadd == 0) | |
{ | |
return; | |
} | |
//2、遍历删除 | |
{ | |
//1、读当前页 | |
Memory.config.FlashRead(Memory.data.Byte, delChunkadd, MEMORYCHUNKINGSIZE); | |
//2、获取下一页地址 | |
uint32_t nextpageadd = vmemory_U8Arr_To_uint32(Memory.data.Info.nextpageadd); | |
//3、循环 | |
while((nextpageadd != 0x00000000) && (nextpageadd != 0xFFFFFFFF)) | |
{ | |
//4、删除 | |
Memory.config.FlashErase(vmemory_U8Arr_To_uint32(Memory.data.Info.currentpageadd), MEMORYCHUNKINGSIZE); | |
//5、读取下一页 | |
Memory.config.FlashRead(Memory.data.Byte, vmemory_U8Arr_To_uint32(Memory.data.Info.nextpageadd), MEMORYCHUNKINGSIZE); | |
} | |
//6、删除当前页,最后一页 | |
Memory.config.FlashErase(vmemory_U8Arr_To_uint32(Memory.data.Info.currentpageadd), MEMORYCHUNKINGSIZE); | |
} | |
//3、写入数量 | |
// 创建一个变量读出有多少个块 | |
uint8_t chunkingnumber = 0; | |
// 用二分查找法定位第一页存储的块数量的信息 | |
Memory.config.FlashRead(&chunkingnumber, uimemoryGetDataPos(Memory.config.memorystartaddress, 256) - 1, 1); | |
chunkingnumber--; | |
Memory.config.FlashWrite(&chunkingnumber, uimemoryGetDataPos(Memory.config.memorystartaddress, 256), 1); | |
} | |
/*********************************************************** | |
*@fuction :bmemoryInsert | |
*@brief : | |
*@param :-- | |
*@return :bool | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-05-23 | |
***********************************************************/ | |
bool bmemoryInsert(uint8_t *index, uint8_t *data, uint32_t group) | |
{ | |
//1、获取存储空间首地址 | |
uint32_t storageStartAdd = uimemoryGetChunkAdd(index); | |
if(storageStartAdd == 0) | |
{ | |
// 查无此块 | |
return false; | |
} | |
//2、获取空间内存储地址 | |
Memory.config.FlashRead(Memory.data.Byte, storageStartAdd, MEMORYCHUNKINGSIZE); | |
uint16_t current_datanum = (Memory.data.Info.datanum[0] << 8) + Memory.data.Info.datanum[1]; | |
// 这里可以高级一点 -->> 但是需要注意,存储与读取要注意 & lt;< 小端模式 >> | |
//uint16_t current_datanum = *(uint16_t *)Memory.data.Info.datanum; | |
//3、判断重复,拿到块下所有数据 | |
vmemoryInquiryList(index); | |
for(int g=0;g<group;g++){ | |
for(int n=0;n<current_datanum;n++){ | |
if(bmemoryCheckArraySame(data+g*4,bymemoryreadbuffer+n*4,4)){ | |
return false; | |
} | |
} | |
} | |
//4、计算插入数据 | |
// 计算需要添加多少新页 | |
uint16_t current_data_shift = current_datanum%EACHCHUNKINGDATAGROUP; | |
uint8_t needpage = (group + current_data_shift)/EACHCHUNKINGDATAGROUP + 1; | |
uint8_t needaddpage = needpage-1; | |
// 获取添加的首地址 | |
uint32_t firstaddress = uimemoryGetChunkAddDataAdd(index); | |
//5、循环存入并更新计数值 | |
uint8_t writedatanum = 0; | |
// 包括第一页,一共有 needpage 页需要写入 | |
while(needpage){ | |
needpage--; | |
if(!needaddpage){ | |
//!0 = 1 如果不需要创建新的块 ------------------------------------------------------------- | |
if(!writedatanum){ | |
// 第一次写入 | |
//write one by one | |
for(uint32_t i = 0; i < group; i++) | |
{ | |
Memory.config.FlashWrite(data+i*MEMORYEACHGROUPDATALENGTH, \ | |
firstaddress+(current_data_shift+i)*MEMORYEACHGROUPDATALENGTH, \ | |
MEMORYEACHGROUPDATALENGTH); | |
} | |
//change currentpage devnum | |
writedatanum += group; | |
}else{ | |
// 不会到这的、因为只会写入一次 | |
return false; | |
} | |
}else{ | |
// 需要创建新块 ---------------------------------------------------------------- | |
if(!writedatanum){ | |
// 第一次写入,写入第一页剩余的个数的数据 页 - 数据 % 页 | |
uint32_t firstpageresiduenum = EACHCHUNKINGDATAGROUP - current_datanum%EACHCHUNKINGDATAGROUP; | |
for(uint32_t i = 0; i < firstpageresiduenum; i++) | |
{ | |
Memory.config.FlashWrite(data+i*MEMORYEACHGROUPDATALENGTH, \ | |
firstaddress+(current_data_shift+i)*MEMORYEACHGROUPDATALENGTH, \ | |
MEMORYEACHGROUPDATALENGTH); | |
} | |
writedatanum += firstpageresiduenum; | |
// 创建下一页 | |
uint8_t *nextpageadd = pmemoryCreatNextChunk(index,vmemorymamagementGetAddressArray(firstaddress)); | |
// 读取下一页 | |
Memory.config.FlashRead(Memory.data.Byte,vmemory_U8Arr_To_uint32(nextpageadd),MEMORYCHUNKINGSIZE); | |
}else{ | |
// 后续写入 | |
if(needpage){ | |
// 写中间的多页 --> 因为创建完新页之后读出了新页 , 所以直接取出的新页中的地址 | |
for(uint32_t i = 0; i < EACHCHUNKINGDATAGROUP; i++) | |
{ | |
Memory.config.FlashWrite(data + ((writedatanum + i) * MEMORYEACHGROUPDATALENGTH), \ | |
vmemory_U8Arr_To_uint32(Memory.data.Info.currentpageadd) + POS_DATA_data + i * MEMORYEACHGROUPDATALENGTH,\ | |
MEMORYEACHGROUPDATALENGTH); | |
} | |
writedatanum += EACHCHUNKINGDATAGROUP; | |
// 创建下一页 | |
uint8_t *nextpageadd = pmemoryCreatNextChunk(index,Memory.data.Info.currentpageadd); | |
// 读取下一页 | |
Memory.config.FlashRead(Memory.data.Byte,vmemory_U8Arr_To_uint32(nextpageadd),MEMORYCHUNKINGSIZE); | |
}else{ | |
// 写最后一页 | |
// 计算最后一页剩余多少没写入 | |
uint32_t lastpageaddnum = (current_data_shift + group) % EACHCHUNKINGDATAGROUP; | |
for(uint32_t i = 0; i < lastpageaddnum; i++) | |
{ | |
Memory.config.FlashWrite(data + ((writedatanum + i) * MEMORYEACHGROUPDATALENGTH), \ | |
vmemory_U8Arr_To_uint32(Memory.data.Info.currentpageadd) + POS_DATA_data + i * MEMORYEACHGROUPDATALENGTH,\ | |
MEMORYEACHGROUPDATALENGTH); | |
} | |
writedatanum += lastpageaddnum; | |
} | |
} | |
} | |
} | |
// 还需要写入数据计数信息 | |
Memory.data.Info.datanum[0]=(current_datanum+group)>>8; | |
Memory.data.Info.datanum[1]=(current_datanum+group); | |
Memory.config.FlashWrite(Memory.data.Info.datanum,firstaddress+POS_DATA_datalength,2); | |
return true; | |
} | |
/*********************************************************** | |
*@fuction :*pmemoryCreatNextChunk | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
uint8_t *pmemoryCreatNextChunk(uint8_t *index,uint8_t *address){ | |
// 创建下一块 | |
//1、拿到空闲地址 | |
uint32_t nextchunkadd = uimemoryGetFreeAddress(); | |
//2、写入块头 | |
memset(Memory.config.chunkinghead+4,0xFF,4);// 此处标识为非首块 | |
Memory.config.FlashWrite(Memory.config.chunkinghead, nextchunkadd, 8); | |
//3、写入当前块的下一页地址 | |
Memory.config.FlashWrite(vmemorymamagementGetAddressArray(nextchunkadd),vmemory_U8Arr_To_uint32(address)+POS_DATA_nextpageadd, 4); | |
//4、写入下一页的前一页 | |
Memory.config.FlashWrite(address,nextchunkadd+POS_DATA_previouspageadd,4); | |
//5、写入下一页的当前页 | |
Memory.config.FlashWrite(vmemorymamagementGetAddressArray(nextchunkadd),nextchunkadd+POS_DATA_currentpageadd,4); | |
//6、写入下一页的 Index | |
Memory.config.FlashWrite(index,nextchunkadd+POS_DATA_infomation+4,4); | |
return vmemorymamagementGetAddressArray(nextchunkadd); | |
} | |
/*********************************************************** | |
*@fuction :uimemoryGetChunkAddDataAdd | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
uint32_t uimemoryGetChunkAddDataAdd(uint8_t *index){ | |
//1、获取编号首地址 | |
uint32_t storageStartAdd = uimemoryGetChunkAdd(index); | |
//2、读取首页信息 | |
Memory.config.FlashRead(Memory.data.Byte, storageStartAdd, MEMORYCHUNKINGSIZE); | |
//3、循环迭代下一页 | |
while((vmemory_U8Arr_To_uint32(Memory.data.Info.nextpageadd) != 0xFFFFFFFF)) | |
{ | |
Memory.config.FlashRead(Memory.data.Byte, vmemory_U8Arr_To_uint32(Memory.data.Info.nextpageadd), MEMORYCHUNKINGSIZE); | |
} | |
//4、返回地址 | |
return vmemory_U8Arr_To_uint32(Memory.data.Info.currentpageadd); | |
} | |
void vmemoryDelete(uint8_t *index, uint8_t *data, uint32_t group) | |
{ | |
//1、获取存储控件首地址 | |
uint32_t storageStartAdd = uimemoryGetChunkAdd(index); | |
//2、遍历删除数据 | |
// 读取首页信息 | |
Memory.config.FlashRead(Memory.data.Byte, storageStartAdd, MEMORYCHUNKINGSIZE); | |
// 读取块的存储数据数量信息 | |
uint16_t datanum = (Memory.data.Info.datanum[0]<<8)+Memory.data.Info.datanum[1]; | |
uint16_t storagedatanum = (Memory.data.Info.storagenum[0]<<8)+Memory.data.Info.storagenum[1]; | |
// 遍历删除的数据 | |
uint32_t deldatanum=0; | |
for(uint32_t g=0;g<group;g++){ | |
// 遍历当前页数据 | |
for(uint32_t i=0;i<EACHCHUNKINGDATAGROUP;i++){ | |
// 如果相同就删除 | |
if(bmemoryCheckArraySame(Memory.data.Info.data[i],data+i*MEMORYEACHGROUPDATALENGTH,MEMORYEACHGROUPDATALENGTH)){ | |
Memory.config.FlashErase(storageStartAdd+POS_DATA_data+i*MEMORYEACHGROUPDATALENGTH,MEMORYEACHGROUPDATALENGTH); | |
deldatanum++; | |
} | |
} | |
} | |
// 循环迭代下一页 | |
while((vmemory_U8Arr_To_uint32(Memory.data.Info.nextpageadd) != 0xFFFFFFFF)) | |
{ | |
Memory.config.FlashRead(Memory.data.Byte, vmemory_U8Arr_To_uint32(Memory.data.Info.nextpageadd), MEMORYCHUNKINGSIZE); | |
// 遍历删除的数据 | |
for(uint32_t g=0;g<group;g++){ | |
// 遍历当前页数据 | |
for(uint32_t i=0;i<EACHCHUNKINGDATAGROUP;i++){ | |
// 如果相同就删除 | |
if(bmemoryCheckArraySame(Memory.data.Info.data[i],data+i*MEMORYEACHGROUPDATALENGTH,MEMORYEACHGROUPDATALENGTH)){ | |
Memory.config.FlashErase(vmemory_U8Arr_To_uint32(Memory.data.Info.currentpageadd)+POS_DATA_data+i*MEMORYEACHGROUPDATALENGTH,MEMORYEACHGROUPDATALENGTH); | |
deldatanum++; | |
} | |
} | |
} | |
// 如果当前块没有存储数据了,删除 | |
} | |
//3、更新计数值 | |
datanum-=deldatanum; | |
Memory.data.Info.datanum[0]=datanum>>8; | |
Memory.data.Info.datanum[1]=datanum; | |
Memory.config.FlashWrite(Memory.data.Info.datanum,storageStartAdd+POS_DATA_datalength,2); | |
} | |
void vmemoryInquiryList(uint8_t *index) | |
{ | |
//1、获取块的 Index 下的所有存储 data-> 读取到 bymemoryreadbuffer | |
} | |
void vmemoryInquiry(uint8_t *index) | |
{ | |
//1、获取基本信息 地址 存储数据数量 | |
} | |
uint32_t uimemoryInquiryChunking(void) | |
{ | |
//1、获取所有存储块列表 | |
//2、返回存储块数量 | |
return 0; | |
} | |
/*********************************************************** | |
*@fuction :uimemoryGetChunkAdd | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
uint32_t uimemoryGetChunkAdd(uint8_t *index) | |
{ | |
// 读出块索引的信息 | |
for(uint32_t indexnum = 0; indexnum < MEMORYINDEX_CHUNKINGINDEX_NUM; indexnum++) | |
{ | |
// 读出 第一块是数量所以跳过 + 256 | |
Memory.config.FlashRead(Memory.index[0].Byte, Memory.config.memorystartaddress + (indexnum + 1) * 256, 256); | |
// 判断每一块信息索引中是否有重复的块 index | |
for(uint32_t j = 0; j < MEMORYINDEX_CHUNKINGINFO_NUM; j++) | |
{ | |
// 如果块索引号一致,块索引信息重复、创建块失败 | |
if(bmemoryCheckArraySame(index, Memory.index[0].Info.infomation, 4)) | |
{ | |
return (vmemory_U8Arr_To_uint32(Memory.index[0].Info.currentpageadd)); | |
} | |
} | |
} | |
return 0; | |
} | |
/*********************************************************** | |
*@fuction :uimemoryGetDataPos | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
uint32_t uimemoryGetDataPos(uint32_t Startaddress, uint32_t length) | |
{ | |
// 定位数据 | |
uint32_t position = 0, tempPos = 0; | |
// 计算一次读出多少组 | |
uint32_t buffergroup = length / MEMORYREADBUFFERSIZE; | |
// 根据给定的长度计算偏移量 | |
uint32_t buffershifting = length % MEMORYREADBUFFERSIZE; | |
// 方向 -> 增 | |
bool direction = false; | |
// 查询组计数 | |
uint32_t groupcount = 0; | |
for(uint32_t g = 0; g <= buffergroup; g++) | |
{ | |
if(g != buffergroup) | |
{ | |
// 如果不是最后一组 | |
Memory.config.FlashRead(bymemoryreadbuffer, Startaddress + MEMORYREADBUFFERSIZE * g, MEMORYREADBUFFERSIZE); | |
tempPos = MEMORYREADBUFFERSIZE; | |
} | |
else | |
{ | |
// 最后一组,只需要读取偏移量大小的数据 | |
Memory.config.FlashRead(bymemoryreadbuffer, Startaddress + MEMORYREADBUFFERSIZE * g, buffershifting); | |
tempPos = buffershifting; | |
} | |
do | |
{ | |
// 计算每组数据的中间位置,为 0 时退出循环 | |
tempPos /= 2; | |
// 根据方向 增 / 减 | |
direction ? (position -= tempPos) : (position += tempPos); | |
// 判断数据是否为空( 如果为空,数据在前面 / 如果不为空,数据在后面 ) | |
bmemoryCheckArraySame(bycheckarray, bymemoryreadbuffer + position, 8) ? (direction = true) : (direction = false); | |
} | |
while(tempPos > 0); | |
// 如果得到的数据在当前块内 | |
if(position < (MEMORYREADBUFFERSIZE - 1)) | |
{ | |
// 拿到当前组 | |
groupcount = g; | |
// 退出循环 | |
break; | |
} | |
} | |
// 计算最后的定位 | |
position += 1; | |
// 这里做最后的校准 | |
while((bymemoryreadbuffer[position] == 0xFF) && (position > 0)) | |
{ | |
position--; | |
} | |
// 得到 FF 所在的位置 | |
position += (groupcount * MEMORYREADBUFFERSIZE) + 1; | |
// 根据给定的起始地址得出数据最终的地址 | |
return (position + Startaddress); | |
} | |
/*********************************************************** | |
*@fuction :uimemoryGetFreeAddress | |
*@brief : 获取一块空闲的块地址 | |
*@param :-- | |
*@return : uint32_t 空闲块的地址 | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-05-23 | |
***********************************************************/ | |
uint32_t uimemoryGetFreeAddress(void) | |
{ | |
for(uint32_t i = 0; i < MEMORYDATA_CHUNKING_NUMBER; i++) | |
{ | |
// 地址 = 存储信息的首地址 + 第几块 * 每一块的大小 | |
uint32_t currentaddress = MEMORYDATA_CHUNKING_STARTADDRESS + i * MEMORYCHUNKINGSIZE; | |
// 读出块头 | |
Memory.config.FlashRead(Memory.data.Info.chunkinghead, currentaddress, 8); | |
// 如果块头为 FF | |
if(bmemoryCheckArraySame(bycheckarray, Memory.data.Info.chunkinghead, 8)) | |
{ | |
// 返回块的地址 | |
return currentaddress; | |
} | |
} | |
// 到这里就说明存储满了 | |
return false; | |
} | |
/*********************************************************** | |
*@fuction :*vmemorymamagementGetAddressArray | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
uint8_t *vmemorymamagementGetAddressArray(uint32_t address) | |
{ | |
static uint8_t addarray[4]; | |
addarray[3] = address >> 24; | |
addarray[2] = address >> 16; | |
addarray[1] = address >> 8; | |
addarray[0] = address; | |
return addarray; | |
} | |
/*********************************************************** | |
*@fuction :vmemorymamagementClearArray | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
void vmemorymamagementClearArray(uint8_t *source, uint32_t length) | |
{ | |
// 跟这个函数一样的 | |
//memset(source,0,length); | |
for(uint32_t i = 0; i < length; i++) | |
{ | |
source[i] = 0x00; | |
} | |
} | |
/*********************************************************** | |
*@fuction :vmemory_U8Arr_To_uint32 | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
uint32_t vmemory_U8Arr_To_uint32(uint8_t *arr) | |
{ | |
return ((((((arr[0] << 8) + arr[1]) << 8) + arr[2]) << 8) + arr[3]); | |
} | |
/*********************************************************** | |
*@fuction :vmemorymamagementGetChunkingnumberAddress | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
uint32_t vmemorymamagementGetChunkingnumberAddress(uint8_t chunkingnumber) | |
{ | |
uint32_t add = (chunkingnumber * 12) + MEMORYINDEX_CHUNKINGINDEX_FIRSTADDRESS; | |
return add; | |
} | |
/*********************************************************** | |
*@fuction :vmemorymamagementCopyArray | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
void vmemorymamagementCopyArray(const uint8_t *source, uint8_t *target, uint32_t length) | |
{ | |
// 跟这个函数一样的 | |
//memcpy(target,source,length); | |
for(uint32_t i = 0; i < length; i++) | |
{ | |
target[i] = source[i]; | |
} | |
} | |
/*********************************************************** | |
*@fuction :bmemoryCheckArraySame | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-07-29 | |
***********************************************************/ | |
bool bmemoryCheckArraySame(uint8_t *sourcearray, uint8_t *targetarray, uint32_t len) | |
{ | |
for(uint32_t i = 0; i < len; i++) | |
{ | |
if(sourcearray[i] != targetarray[i]) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} |
同时和存储相关的推荐大家看一下这个
GD25Q64存储芯片的读写驱动
https://zhuanlan.zhihu.com/p/638857832