/*************************************************************
* 转载时请保留博客链接地址:https://blog.csdn.net/yunjie167/article/details/84285513
**************************************************************/
#include <stdio.h>
#include <string.h>
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned long
#define ERROR_OPREA -1
#define ERROR_NOSPACE -2
#define ERROR_NO_UPDATE_LOG -3
#define ERROR_NO_RECORD -4
#define PAGENUMS 4
#define PAGESIZE 512
u8 VirFlashBuff[PAGENUMS][PAGESIZE];
#define ITEM_HEADER_SIZE sizeof(SFS_Item_t)
typedef struct {
u16 remain; //剩余的字节数
u16 recycle; //可回收的字节数
} SFS_Info_t;
SFS_Info_t sfs_info;
#define LOGMSG_KEY 0xFE
#define MAGICNUM 0xAABB
#define UNUSEVALUE 0xFFFFFFFF
#define MARK_USE 0xDF
#define MARK_DIRTY 0xDD
#define FLASHSIZE sizeof(VirFlashBuff)
/*
typedef struct {
const SFS_Item_t *p_header;
const void * p_data;
} sfs_flash_record_t;*/
typedef struct {
u16 magic;
u8 pagenum;
u8 pagetype;
//u16 page_state;
//u16 resv;
} SFS_Header_t;
SFS_Header_t SFS_Header;
typedef struct {
u8 recodeKEY;
u8 mark;
u16 length;
} SFS_Item_t;
/*
typedef struct {
u16 recodeKEY;
} SFS_Des_t;*/
//flash里建议用字来存储,这里只是模拟flash的操作
int my_memcpy(u32 *des,const u32 *src,int length)
{
int flag=0;
int cpsize=0;
if(((u32)src&0x03)!=0)
printf("地址不对齐!!!!!!!!!!!!!!!!!!!\n");
if(length>0)
{
if(length & 0x03)
flag=1;
length>>=2;
length+=flag;
cpsize=length<<2;
while(length--)
*des++=*src++;
}
return cpsize;
}
void SFS_Init(void)
{
u32 *t=(u32 *)VirFlashBuff;
if(*t != MAGICNUM)
{
memset(VirFlashBuff,0xff,sizeof(VirFlashBuff));
SFS_Header.magic=MAGICNUM;
memcpy(VirFlashBuff,&SFS_Header,sizeof(SFS_Header));
sfs_info.remain=sizeof(VirFlashBuff)-sizeof(SFS_Header);
sfs_info.recycle=0;
printf("整个Flash缓存已经初始化过了! sfs_info.remain=%ld\n",sfs_info.remain);
}
//如果已经初始化的了,也得计算下sfs_info.remain
}
u8 * Find_Record(SFS_Item_t *des)
{
u32 *pstart=(u32 *)(((u8 *)&VirFlashBuff)+(sizeof(SFS_Header_t)));
SFS_Item_t tmpdes;
for(;pstart<pstart+FLASHSIZE/4;)
{
if(*pstart!=UNUSEVALUE)
{
tmpdes=*(SFS_Item_t *)&(*pstart);
if(tmpdes.recodeKEY==des->recodeKEY && tmpdes.mark!=MARK_DIRTY)
{
des->length=tmpdes.length;
return (u8 *)(pstart+sizeof(SFS_Item_t)/4); //偏移到数据区域
}
else
{
tmpdes=*(SFS_Item_t*)pstart; //寻找下一个数据项目
pstart+=(tmpdes.length+sizeof(SFS_Item_t))/4;
if(tmpdes.length%4!=0)
pstart++;
}
}
else
{
return NULL;
}
}
}
u8 * Find_Record_Token(SFS_Item_t *des,u32 **ftok)
{
u32 *pstart;
SFS_Item_t tmpdes;
u8 *retaddr=NULL;
if(*ftok!=NULL)
{
pstart=*ftok;
}
else
{
pstart=(u32 *)(((u8 *)&VirFlashBuff)+(sizeof(SFS_Header_t)));
}
for(;pstart<pstart+FLASHSIZE/4;)
{
if(*pstart!=UNUSEVALUE)
{
tmpdes=*(SFS_Item_t *)&(*pstart);
if(tmpdes.recodeKEY==des->recodeKEY && tmpdes.mark!=MARK_DIRTY)
{
des->length=tmpdes.length;
retaddr=(u8 *)(pstart+sizeof(SFS_Item_t)/4);
tmpdes=*(SFS_Item_t*)pstart; //将下一个项目地址赋值给ftok
pstart+=(tmpdes.length+sizeof(SFS_Item_t))/4;
if(tmpdes.length%4!=0)
pstart++;
*ftok=pstart;
return retaddr;
}
else
{
tmpdes=*(SFS_Item_t*)pstart; //寻找下一个数据项目
pstart+=(tmpdes.length+sizeof(SFS_Item_t))/4;
if(tmpdes.length%4!=0)
pstart++;
}
}
else
{
*ftok=NULL;
return NULL;
}
}
}
u8 *FindEmptyPostion(void)
{
u32 *pstart=(u32 *)(((u8 *)&VirFlashBuff)+(sizeof(SFS_Header_t)));
SFS_Item_t tmpdes;
for(;pstart<pstart+FLASHSIZE/4;)
{
if(*pstart==UNUSEVALUE)
{
printf("FindEmptyPostion():pstart=0x%X \n",pstart);
return (u8 *)pstart;
}
else
{
tmpdes=*(SFS_Item_t*)pstart; //寻找下一个数据项目
pstart+=(tmpdes.length+sizeof(SFS_Item_t))/4;
if(tmpdes.length%4!=0)
pstart++;
}
}
return NULL;
}
int SaveItem2Falsh(SFS_Item_t *des,void *pMsg,int length)
{
u8 *pstart;
int cpysize;
if(sfs_info.remain<length+ITEM_HEADER_SIZE) //存储空间不足,直接返回
return -2;
pstart=FindEmptyPostion();
if(pstart!=NULL)
{
printf("找到一个空的位置:0x%X,",pstart);
des->length=length;
des->mark=MARK_USE;
my_memcpy((u32 *)pstart,(u32 *)des,sizeof(SFS_Item_t)); //memcpy(pstart,des,sizeof(SFS_Item_t)); //将记录写上
cpysize=my_memcpy((u32 *)(pstart+sizeof(SFS_Item_t)),(u32 *)pMsg,length); //memcpy(pstart+sizeof(SFS_Item_t),pMsg,length);
sfs_info.remain-=(cpysize+ITEM_HEADER_SIZE);
printf("剩余%d个字节\n",sfs_info.remain);
return 0;
}
return -1;
}
int delete_record(SFS_Item_t *des)
{
u8 *p_header;
SFS_Item_t *tmpdes;
int flag=0;
int ret=0;
if(des->recodeKEY==LOGMSG_KEY) //如果是日志类的要删除就得全部删除
{
flag=1;
printf("\t您删除的是日志类消息,会全部删除!!!!!!\t");
}
do {
if((p_header=Find_Record(des)) != NULL)
{
p_header-=ITEM_HEADER_SIZE; //指向头域
tmpdes=(SFS_Item_t *)p_header;
tmpdes->mark=MARK_DIRTY;
sfs_info.recycle+=tmpdes->length+ITEM_HEADER_SIZE;
ret++;
}
else
break;
} while(flag);
return ret;
}
int update_a_record(SFS_Item_t *des,void *pMsg,int length)
{
u8 *p_header;
SFS_Item_t *tmpdes;
int ret=-1;
if(des->recodeKEY==LOGMSG_KEY)
{
printf("\t日志类信息不支持更改!!!!!!\t");
return -3;
}
if(sfs_info.remain<length+ITEM_HEADER_SIZE) //存储空间不足,直接返回
return -2;
ret=delete_record(des); //删除掉之前的旧记录
if(ret<0)
return ret;
return SaveItem2Falsh(des, pMsg, length); //再将新的存储进去
}
#define TEST_KEY 0x0D
#pragma pack (push,4)
typedef struct {
int a;
u8 str[16];
float b;
u8 c;
short d;
} TestVal_t;
#pragma pack(pop)
TestVal_t TestVal;
int ret;
int main()
{
int repeat;
SFS_Init();
SFS_Item_t des;
des.recodeKEY=TEST_KEY;
strcpy(TestVal.str,"hello!");
TestVal.a=0x11223344;
TestVal.b=3.1415926f;
ret=SaveItem2Falsh(&des,&TestVal,sizeof(TestVal_t));
if(ret>=0)
{
printf("存储数据成功1!\n");
ret=delete_record(&des);
if(ret>=0)
{
printf("删除记录1成功!!!\n");
}
}
//------------------------------------
TestVal.a=0x33221199;
TestVal.c=0x55;
TestVal.d=0xaa66;
ret=SaveItem2Falsh(&des,&TestVal,sizeof(TestVal_t));
if(ret>=0)
{
printf("存储数据成功2!\n");
//--------------update------------------
printf("更新存储记录2...\n");
TestVal.a=0x44444444;
if(update_a_record(&des,&TestVal,sizeof(TestVal_t))>=0)
{
printf("更新存储记录2成功!\n\n");
}
}
//--------------find------------------
{
u8 *p_recode;
TestVal_t readval;
des.recodeKEY=TEST_KEY;
if((p_recode=Find_Record(&des))!=NULL)
{
memcpy(&readval,p_recode,des.length);
printf("找到一个记录! 0x%X length=%d\n",p_recode,des.length);
printf("readval.str=%s,readval.a=0x%X,readval.b=%f,readval.c=0X%x,readval.d=0X%x\n"
,readval.str,readval.a,readval.b,readval.c,readval.d);
}
else
{
printf("未找到KEY=0x%X\n",des.recodeKEY);
}
}
//--------------save a string------------------
repeat=5;
while(repeat)
{
int stringlen;
//des.recodeID=LOGMSG_ID;
des.recodeKEY=LOGMSG_KEY;
char mytest_str[64];//="你们好啊今天杭州下大雪!!!!.\n";
sprintf(mytest_str,"你们好啊今天杭州下大雪! %d\n",repeat);
stringlen=strlen(mytest_str);
ret=SaveItem2Falsh(&des,mytest_str,stringlen+1); //加1是想多存一个字符串结束符
if(ret>=0)
{
printf("存储字符串 %d\n",repeat);
}
else
{
printf("存储空间不足!!!\n");
if(sfs_info.recycle+sfs_info.remain>=stringlen+1+ITEM_HEADER_SIZE)
{
printf("回收后的空间是足够的.remain=%d\n",sfs_info.recycle+sfs_info.remain);
}
else
{
printf("回收后的空间还是不够 !!!\n");
}
break;
}
repeat--;
}
//--------------find all log------------------
printf("*********** find all log!!! ***********\n");
{
u8 *p_recode;
u32 *ftok=NULL;
des.recodeKEY=LOGMSG_KEY;
do {
if((p_recode=Find_Record_Token(&des,&ftok))!=NULL)
{
printf("找到一个记录!length=%d %.*s\n",des.length,des.length,p_recode);
}
else
{
printf("查找结束!\n");
}
} while(ftok!=NULL);
}
des.recodeKEY=LOGMSG_KEY;
ret=delete_record(&des);
printf("删除记录%d条\n",ret);
printf("end\n");
}
一个简易文件日志记录系统,适合单片机使用.