基于msp430F149管理sst25vf016b存储芯片的文件管理系统
sst25vf016b是以块2Mbyte大小的存储芯片总共分为啦512块,每块4K,来进行管理, 首先介绍全局变量: unsigned char Flag_Key12=0; 标志是否为最后一块 unsigned char Flag_Read=0; 标志读完整块flash, unsigned int Flag_16Num=0; 写数据,读数据时的控制器 unsigned int Block_MuluNow=0; 保存当前正在操作的目录 unsigned int Table_Block[64]; 每两个Bit表示一个块,每8个块压缩正一个字节,64个字节,正好对应512个块,每个块有3种状态,00空,01占用,10脏块 unsigned char Table_Block_1[8]; 把一个字节展开放入此数组,查找的时候更快速 unsigned int Next_Block=0; 下一块 unsigned char block_n=1; 记录当前操作块的下一块,以此来实现擦出的轮番使用,不会应为某一块的过度擦除而导致整块flash损坏 unsigned char Name_Front=0; 记录管理的条目,本系统设置是不超过146个条目 unsigned char Name_Empty=0; 记录要删除的条目 flash管理的总体规划: ???? flash的存储管理就是按照实现安排的内容来进行管理的. 函数说明: /* ????功能:检查目录,开机进行 */ unsigned char Flash_JCmulu() { unsigned int i=0; unsigned char Table[2]={0,0}; unsigned long int Block_MuluAdd=0; unsigned char Table_Block_H=0,Table_Block_L=0; for(i=0;i<512;i++) {????? ? Block_MuluAdd=i<<12; ? ? ?//首先i进行右移12位,总是乘以4096,即4K,达到对 ? ? ? ? ? ? ? ? ? ? Read_Byte_Cont(Block_MuluAdd,Table,2);?//512?块的循环 if((Table[0]==0)&&(Table[1])==0) ?//首先查找目录块 { Block_MuluNow=i; break; } else if(i==511) return 0; } Block_MuluAdd=Block_MuluNow<<12; ? ?//赋值给Block_MuluAdd,来进行保存Block_MuluNow Name_Front=Read_Byte(Block_MuluAdd+1024);//的值 //读取64字节的Table_Block的内容 ????????for(i=0;i<64;i++) { Table_Block_H=Read_Byte(Block_MuluAdd+1024+1+i); Table_Block_L=Read_Byte(Block_MuluAdd+1024+2+i); Table_Block[i]=(Table_Block_H<<8)|Table_Block_L; } ????????//按照上表来进行读取相关内容 Read_Byte_Cont(Block_MuluAdd+1024+1+128,Table_Block_1,8); Next_Block=Read_Byte(Block_MuluAdd+1024+1+128+8+2); block_n=Read_Byte(Block_MuluAdd+1024+1+128+8+3); return 1; } //给新的条目分配空间,同时更新目录,当然只有第一次使用时不需要更新,以后使用每次都更新目录 unsigned char Flash_AllocateSpace(unsigned char *Table_Time) { unsigned long int Block_MuluAdd=0; unsigned int Block=0; if(Name_Front!=146) { Block_MuluAdd=(Block_MuluNow<<12); ???????????????? ????????????????Block=Search_Block(); ? //搜寻空块 if(Block==512)return 0; else Block_MuluNow=Block; ?//作为本次操作使用 Block=Search_Block(); ?//搜寻空块,作为下次操作使用 if(Block==512)return 0; else Next_Block=Block; Write_Byte(Block_MuluNow<<12,0); //标志为目录 Write_Byte((Block_MuluNow<<12)+1,0); //向里面写入Table_Time数据,以及下一块的标号 Write_Byte_Cont((Block_MuluNow<<12)+2+Name_Front*7,Table_Time,5); Write_Byte((Block_MuluNow<<12)+2+Name_Front*7+5,(Next_Block>>8)&&0xff); Write_Byte((Block_MuluNow<<12)+2+Name_Front*7+6,Next_Block&0xff); ? ? //第一次时,不需要更新,以后每次都更新目录,并且相应目录块标志为11(分配空间时标志为1,后更新目录时又和2相或,故为3) if(Block_MuluAdd!=(Block_MuluNow<<12)) Mulu_InformationUpdate(Block_MuluAdd,WRITE); //条目加1 ????????????????Name_Front++; ????//同时当前操作块表为1,占用块,此为有用数据 Table_Block[Block_MuluNow/8]|=0x0001<<((Block_MuluNow%8)*2); ????//当然下一块也要更新为占用块,以免下次查找到同一块 Table_Block[Next_Block/8] |= 0x0001<<((Next_Block%8)*2); return 1; } return 0; } void Flash_Write(unsigned char*Table,unsigned char Flag_Key12) { unsigned long int Next_Block_MuluAdd=0; unsigned long int Next_BlockAdd=0; unsigned int Block=0; ????????//每次写入16字节,Flag_16Num为256时,写满一个块 Next_BlockAdd=(Next_Block<<12)+16*Flag_16Num; Write_Byte_Cont(Next_BlockAdd,16); Flag_16Num++; ????//当写满一个块时,查询下一块,并写入Next_Block_MuluAdd这个地址,然后向下一空块继续写入数据 if(Flag_16Num==256) { Flag_16Num=0; Next_Block_MuluAdd=(Block_MuluNow<<12)+3072+Next_Block*2; Block=Search_Block(); if(Block==512)return; else Next_Block=Block; Table_Block[Next_Block/8] |=0x0001<<((Next_Block%8)*2); Write_Byte(Next_Block_MuluAdd,(Next_Block&0xff00)>>8); Write_Byte(Next_Block_MuluAdd+1,Next_Block&0xff); } ????//如果是向末块,即512写入,就写如512,表示用完 if(Flag_Key12) {???? if(Flag_16Num!=0) Next_Block_MuluAdd=(Block_MuluNow<<12)+3072+Next_Block*2; Write_Byte(Next_Block_MuluAdd,0x02); Write_Byte(Next_Block_MuluAdd+1,0x00); Flag_16Num=0; } } //搜寻空块 unsigned int Search_Block() { unsigned char i=0; unsigned char num=block_n-1; ?//block_n记录当前操作Table_Block字节的下一字节 ???????????????????????????????????? //即返回操作块的标号 for(i=0;i<8;i++) { if(Table_Block_1[i]==0) { Table_Block_1[i]=3; return num*8+i; } } num=Search_Table(); for(i=0;i<8;i++) { if(Table_Block_1[i]==0) { Table_Block_1[i]=3; return num*8+i; } } return ?512; } //搜寻Table_Block中的空块,并展开到Table_Block_1 unsigned int Search_Table() { unsigned char num=0; unsigned char i=0; unsigned char Flag_0=0; for(num=block_n;num<64;num++) { for(i=0;i<8;i++) { Table_Block_1[i]=(Table_Block[num]>>(i*2))&0x0003; if(Table_Block_1[i]==0) Flag_0=1; //只要有一个空块,Flag_0就为1 } if(Flag_0==1) ? ? ? ? ? ? ? ?? { block_n=num+1; ? ? ? ? ?//操作block_n指向下一要操作的8个块,即 if(block_n==64)block_n=0;????//Table_Block对应的下一字节 ? ? ? ? ? ? ? ? ? ? ? ? return num; } } for(num=0;num<block_n;num++) { for(i=0;i<8;i++) { Table_Block_1[i]=(Table_Block[num]>>(i*2))&0x0003; if(Table_Block_1[i]==0) Flag_0=1; } if(Flag_0==1) { block_n=num+1; if(block_n==64)block_n=0; return num; } } return 64; } //擦除空块 void Flash_DirtyBlock() { unsigned int i=0; unsigned char num=0; for(num=0;num<64;num++) { for(i=0;i<8;i++) { if(2==((Table_Block[num]>>(i*2))&0x0003)) { Block_Erase_4K((num*8+i)<<12); Table_Block[(num*8+i)/8]&=0xfffc<<(((num*8+i)%8)*2); } } } } //把全局变量更新到目录中, void Process_TableBlock() { unsigned char i; Write_Byte((Block_MuluNow<<12)+1024,Name_Front); for(i=0;i<64;i++) { Write_Byte((Block_MuluNow<<12)+1024+1+i,(Table_Block[i]>>8)&0xff); } for(i=0;i<64;i++) { Write_Byte((Block_MuluNow<<12)+1024+1+64+i,(Table_Block[i]>>8)&0xff); } Write_Byte_Cont((Block_MuluNow<<12)+1024+1+128,8); Write_Byte((Block_MuluNow<<12)+1024+1+128+8,Block_MuluNow); Write_Byte((Block_MuluNow<<12)+1024+1+128+8+1,Next_Block); Write_Byte((Block_MuluNow<<12)+1024+1+128+8+2,block_n); } //目录更新 //WRITE:把Name_Front中的条目直接复制即可 READ:把Name_Empty记录的条目删除 void Mulu_InformationUpdate(unsigned long int Block_MuluAdd,unsigned char Flag_Write_Read) { unsigned char num=0; unsigned char i=0; unsigned char SST_Read[7]={0}; if(Flag_Write_Read==WRITE) { for(i=0;i<Name_Front;i++) { Read_Byte_Cont(Block_MuluAdd+2+i*7,SST_Read,7); Write_Byte_Cont((Block_MuluNow<<12)+2+i*7,7); } } else if(Flag_Write_Read==READ) { for(i=0;i<Name_Front;i++) { if(i<Name_Empty) { Read_Byte_Cont(Block_MuluAdd+2+i*7,7); } else if(i>Name_Empty) { Read_Byte_Cont(Block_MuluAdd+2+i*7,7); Write_Byte_Cont((Block_MuluNow<<12)+2+(i-1)*7,7); } } Name_Front--; } for(num=0;num<64;num++) { for(i=0;i<8;i++) { if(1==(Table_Block[i]>>(i*2))&0x0003) { Read_Byte_Cont(Block_MuluAdd+3072+(num*8+i)*2,2); Write_Byte_Cont((Block_MuluNow<<12)+3072+(num*8+i)*2,2); } } } ? ? //擦出原来的目录,并置位脏块 Block_Erase_4K(Block_MuluAdd); ? ? ? Table_Block[(Block_MuluAdd>>12)/8]|=0x0002<<(((Block_MuluAdd>>12)%8)*2); } 经过验证可以使用.. 并且读取依靠的是链表,当存储的数据大于一个块时,每个块的末尾存储着下一块的号码,可以继续读写. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |