大家在使用 GD25Q64 存储东西时,如果没有移植现有文件系统。那是怎么存储的呢?

这里给大家推荐一种方式。动态链表存储。写的还不太完善,最近太累了,没时间完善了。

# 理念

image-20230803210004549

如果一块控件不够存储了,可以再创建一块

image-20230803210045390

# 代码实现

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

同时和存储相关的推荐大家看一下这个

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

flechazo 微信支付

微信支付

flechazo 支付宝

支付宝

flechazo 贝宝

贝宝