TRTOS的TQFS文件系统文件驱动层代…

NandFlash 作为嵌入式存储用的主流存储芯片,不仅仅是因为它的密度高,擦写速度快,成本低是它成为中低端嵌入式设备的首选存储方案。

在拥有诸多优点的同时,NANDFlash由于生产工艺的问题,其在出厂时可能存在一定的坏块。这些固有坏块不能用于存储数据,已被产家标识好。另外,使用过程中由于读写次数增多,好块也会变得不稳定或失效,成为坏块,这就是出厂后产生的坏块。

介于NandFlash的这些特性,传统的文件系统Fat  NTFS ext2根本没法完美支持NandFlash,YAFFS文件系统的出现,解决了这一尴尬局面, YAFFS (Yet Another Flash File System) 是由Aleph One公司所发展出来的NAND flash 嵌入式文件系统。YAFFS是第一个专门为NAND Flash存储器设计的嵌入式文件系统,适用于大容量的存储设备;并且是在GPL(General Public License)协议下发布的。但由于YAFFS初期时为类似于Linux的嵌入式操作系统准备的,代码量的庞大根本不适合移植到小型嵌入式操作系统上使用,这就有必要开发一种新的代码量少,却又能完美支持NandFlash的文件系统出现。这是TQFS文件系统诞生的主要原因。


TQFS文件系统文件驱动层介绍 

TRTOS的TQFS文件系统文件驱动层代码(针对NandFlash的第二款嵌入式文件系统)

根据NandFlash的特性:以K9F2G080B为例   一个设备有2048个块,每个块有64页,每页有2048个字节的数据内容存储区和64个字节的Spare附加信息区,并且擦出的最小单位为块,读取的最小单位为字节。根据这些特征为NandFlash专门设计的文件操作系统TQFS能完美解决在NandFLash上进行文件管理的难题。

TQFS的文件系统结构包括两个主要部分,文件表TAB区和文件内容区,还有一些辅助存储区Spare用来记存储校验码记录坏块和Spare所在页的内容描述信息,整个TQFS的文件系统存储方式是树形结构,且根目录位置不固定。

文件表所存放的位置在NandFlash的首个不是坏块的存储块上,块的所有页的数据内容存储区的每个个字节对应文件内容区域中的每一页,根据这个字节存储区的值可以获得相映射的内容存储区的状态是否可以用来存储数据是否能够进行资源回收的重要标志

enum Page_Status
{
PS_NotUsed=0xff,//页未被使用
PS_CanUse=0xfe, //页可以使用
PS_Used=0xfc, //页被使用
PS_Delete=0xf8, //页删除
PS_Dis=0xf0, //页屏蔽区
PS_Bad=0x00 //页损坏区
};

void Nand_InforCollect(Nand_UserInfor *NUI);函数负责获取TQFS文件系统的存储信息,总共容量,可以空间被删除空间大小以及坏块的个数等信息,内容如下。

typedef struct
{
uint32 PS_NotUsed;
uint32 PS_CanUse;
uint32 PS_Used;
uint32 PS_Delete;
uint32 PS_Dis;
uint32 PS_Bad;
uint32 PS_Other;
uint16 TabInBlock;
uint32 FileStartPage;
}Nand_UserInfor;


文件内容所在区域页的Spare区域存放的信息如下,整个文件的存储形式是链式存储这点跟FAT文件系统类似,但这里的一个文件可以是文件夹文件,可以是链接文件,链接文件指向的是其他wen
typedef struct
{
uint8 Page_Ok;
uint8 FileType;//该页内容类型
uint8 PS_ST;//页状态
uint8 DataPageIndex;//页在文件所有页中位置
uint32 NextPageAddr;//下一页的地址
uint32 PreviousAddr;//前一页的地址
uint16 DataLegnth;//当前页内容长度 偏移地址为SpareLength+2字节长度
uint8 SpareLength;//当前页Spare区域长度//SpareCrc不在该区域
uint16 DataCrc;//数据区域校验值
uint16 SpareCrc;//Spare区域校验值
}Spare_Infor;//页头结构体

TRTOS的TQFS文件系统文件驱动层代码(针对NandFlash的第二款嵌入式文件系统)


TQFS头文件

#ifndef _TQFS_H_

#define _TQFS_H_
#include “Define.h”
#include ”Nand_Flash.h“



enum Page_Status
{
PS_NotUsed=0xff,//页未被使用
PS_CanUse=0xfe, //页可以使用
PS_Used=0xfc, //页被使用
PS_Delete=0xf8, //页删除
PS_Dis=0xf0, //页屏蔽区
PS_Bad=0x00 //页损坏区
};
enum FileType{
FT_File=0x01,//文件类型
FT_Folde=0x02,//文件夹类型
FT_Content=0x03,//文件内容页
FT_Link=0x04//链接类型
};

typedef struct
{
uint32 PS_NotUsed;
uint32 PS_CanUse;
uint32 PS_Used;
uint32 PS_Delete;
uint32 PS_Dis;
uint32 PS_Bad;
uint32 PS_Other;
uint16 TabInBlock;
uint32 FileStartPage;
}Nand_UserInfor;


///每个内容存放页存页
typedef struct
{
uint8 Page_Ok;
uint8 FileType;//该页内容类型
uint8 PS_ST;//页状态
uint8 DataPageIndex;//页在文件所有页中位置
uint32 NextPageAddr;//下一页的地址
uint32 PreviousAddr;//前一页的地址
uint16 DataLegnth;//当前页内容长度 偏移地址为SpareLength+2字节长度
uint8 SpareLength;//当前页Spare区域长度//SpareCrc不在该区域
uint16 DataCrc;//数据区域校验值
uint16 SpareCrc;//Spare区域校验值
}Spare_Infor;//页头结构体

typedef struct
{
uint8 Page_Ok;
uint8 FileType;//该页内容类型
uint8 PS_ST;//页状态
uint8 FileName[16];//文件名长度为16个字节
uint8 FileVirtue;//文件属性
Date_Time CreateDate;//文件创建时间
Date_Time ReBuildDate;//文件修改时间
uint32 NextPageAddr;//内容页地址
uint32 FileSize;
uint16 FileID;
uint16 DataCrc;

}File_Infor;//文件头结构体//文件头页不存放任何文件内容,只存放文件信息

extern Nand_UserInfor Nand_Infor;
BOOL Read_FileInfor(uint32 Page,File_Infor *FI);
BOOL Write_FileInfor(uint32 Page,File_Infor *FI);
BOOL Read_SpareInfor(uint32 Page,Spare_Infor *FI);
uint16 TQFS_FormatNand(void);
uint16 TQFS_FindTabAddr(void);
uint32 TQFS_FindFirstUsingPage(uint32 StartPage);
void Nand_InforCollect(Nand_UserInfor *NUI);
void TQFS_Init(void);
void DeviceMount_TQFS(void);

#endif


TQFS的代码文件部分

#include
#include

Nand_UserInfor Nand_Infor;


BOOL Read_FileInfor(uint32 Page,File_Infor *FI)
{
uint16 CRC_Value;
Page+=Nand_Infor.FileStartPage;
Nand_ReadPage(Page,(uint8 *)FI,0,sizeof(File_Infor));
CRC_Value=SmallCrc((uint8 *)FI,sizeof(File_Infor)-2);
DeBug("CRC_Value:%x",CRC_Value);
DeBug("FI->DataCrc:%x",FI->DataCrc);
if(CRC_Value==FI->DataCrc)return TRUE;
else return FALSE;
}
BOOL Write_FileInfor(uint32 Page,File_Infor *FI)
{
File_Infor spare_infor;
Page+=Nand_Infor.FileStartPage;
FI->DataCrc=SmallCrc((uint8 *)FI,sizeof(File_Infor)-2);
Nand_WritePage(Page,(uint8 *)FI,0,sizeof(File_Infor));
return Read_FileInfor(Page,&spare_infor);
}

BOOL Read_SpareInfor(uint32 Page,Spare_Infor *SI)
{
uint16 CRC_Value;
Page+=Nand_Infor.FileStartPage;
Nand_ReadPage(Page,(uint8 *)SI,0,sizeof(Spare_Infor));
CRC_Value=Tools_GetCRC16((uint8 *)SI,sizeof(Spare_Infor)-2);
if(CRC_Value==SI->DataCrc)return TRUE;
else return FALSE;
}

void TQFS_MarkPageInTab(uint32 Block,uint8 *Mark)
{
uint32 TabPage,TabOffset;
if(NAND_ZONE_SIZE>Nand_Infor.TabInBlock)
{
Block-=(Nand_Infor.TabInBlock+1);//偏移内容块到相对位置0
Block*=NAND_BLOCK_SIZE;
TabPage=Block/NAND_PAGE_SIZE;
TabOffset=Block%NAND_PAGE_SIZE;
Nand_WritePage(TabPage,&Mark[0],TabOffset+NAND_SPARE_SIZE,NAND_BLOCK_SIZE);
}
}

uint16 TQFS_FormatNand()
{
uint32 m,n;
uint8 Buf[NAND_BLOCK_SIZE];
uint16 Bad_Count=0;//总坏的页
uint16 BlockBad_Count;//块坏的页
if(!_Tos_Device_Tab[DeviceId_TQFS].Init)
{
DeBug("You Must Be Run NandInit",Infor_Error);
return 0xffff;
}
DeBug_Get();
Nand_Infor.TabInBlock=0xffff;
for(m=0;m
{
BlockBad_Count=0;
Nand_EraseBlock(m);
for(n=0;n
{

if(Cheak_BadPage(NAND_BLOCK_SIZE*m+n)==0xffff)Buf[n]=PS_CanUse;
else Buf[n]=PS_Bad;
}
TQFS_MarkPageInTab(m,&Buf[0]);
if(Nand_Infor.TabInBlock==0xffff&&!BlockBad_Count)Nand_Infor.TabInBlock=m;//记录首个能用的块当作系统页映射表
DeBug("Block[%d]Find[%d]BadPage",m,BlockBad_Count,Infor_Infor);
}
DeBug("DeviceFind[%d]BadPage",m,Bad_Count,Infor_Infor);
DeBug_Drop();
return Bad_Count;
}

uint16 TQFS_FindTabAddr()
{
uint8 Buf[2];
uint32 i;
for(i=0;i
{
Nand_ReadPage(i*NAND_BLOCK_SIZE,&Buf[0],0,2);
if(Buf[0]==0xff)return i;
}
return 0xffff;
}

uint32 TQFS_FindFirstUsingPage(uint32 StartPage)
{
uint16 Length;
uint32 Offset,i;
Length=NAND_BLOCK_SIZE-StartPage;//剩余可以搜索的页
for(i=0;i
{
Offset=Nand_FindPageKey(Nand_Infor.TabInBlock*NAND_BLOCK_SIZE+StartPage++,PS_CanUse);
DeBug("Offset%x",Offset,Infor_Infor);
if(Offset!=0xffff)break;
}
DeBug("TQFS_FindFirstUsingPage%d",i,Infor_Infor);
i*=NAND_PAGE_SIZE;
i+=Offset;
return i;
}

void Nand_InforCollect(Nand_UserInfor *NUI)
{

uint32 m,n;
for(m=0;m
{
NAND_CMD=0x00;
Nand_WriteAddr(Nand_Infor.TabInBlock*NAND_BLOCK_SIZE+m,NAND_SPARE_SIZE);
NAND_CMD=0x30;
Tos_TaskDelay(1);
for(n=0;n
{
switch(NAND_DAT8)
{
case PS_NotUsed:NUI->PS_NotUsed++;break;
case PS_Bad:NUI->PS_Bad++;break;
case PS_CanUse:NUI->PS_CanUse++;break;
case PS_Delete:NUI->PS_Delete++;break;
case PS_Dis:NUI->PS_Delete++;break;
default :NUI->PS_Other++;break;
}
}
}
}

void TQFS_Init()
{
Nand_FSMC_Init();
Nand_Infor.TabInBlock=TQFS_FindTabAddr();
Nand_Infor.FileStartPage=Nand_Infor.TabInBlock+1;//加上Tab表占用的一个块
Nand_Infor.FileStartPage*=NAND_BLOCK_SIZE;//文件起始页
Nand_InforCollect(&Nand_Infor);
}
void DeviceMount_TQFS()
{
_Tos_Device_Tab[DeviceId_TQFS].DeviceId=DeviceId_TQFS;
_Tos_Device_Tab[DeviceId_TQFS].DeviceName="TQFS";
_Tos_Device_Tab[DeviceId_TQFS].DeviceOwnerId=Null;
_Tos_Device_Tab[DeviceId_TQFS].DeviceVirtue=ReadOnly|WriteOnly|CharDerice;
_Tos_Device_Tab[DeviceId_TQFS].DeviceState=Ready;
_Tos_Device_Tab[DeviceId_TQFS].Init=TQFS_Init;
_Tos_Device_Tab[DeviceId_TQFS].Write=Null;
_Tos_Device_Tab[DeviceId_TQFS].Read=Null;
_Tos_Device_Tab[DeviceId_TQFS].Exit=Null;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值