基于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管理的总体规划:

    

wKioL1VQqCixjgjtAAH4UB0keA8015.jpg

wKiom1VQpq_jW13ZAAK2tPM3TiU611.jpg

wKioL1VQqCnioWCmAAJiJDG3l10763.jpg

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,Table,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,Table_Block_1,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,SST_Read,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,SST_Read,7);

Write_Byte_Cont((Block_MuluNow<<12)+2+i*7,SST_Read,7);


}


else if(i>Name_Empty)

{

Read_Byte_Cont(Block_MuluAdd+2+i*7,SST_Read,7);

Write_Byte_Cont((Block_MuluNow<<12)+2+(i-1)*7,SST_Read,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,SST_Read,2);

Write_Byte_Cont((Block_MuluNow<<12)+3072+(num*8+i)*2,SST_Read,2);

}

}

}

    //擦出原来的目录,并置位脏块

Block_Erase_4K(Block_MuluAdd);      

Table_Block[(Block_MuluAdd>>12)/8]|=0x0002<<(((Block_MuluAdd>>12)%8)*2);

}



经过验证可以使用..

并且读取依靠的是链表,当存储的数据大于一个块时,每个块的末尾存储着下一块的号码,可以继续读写.
















































本文出自 “我的博客” 博客,谢绝转载!

你可能感兴趣的:(Flash,记录,控制器,文件管理)