FAT32文件系统源代码
stm32sdiofatfs文件系统源码分析
、概述1、目的在移植之前,先将源代码大概的阅读一遍,主要是了解文件系统的结构、各个函数的功能和接口、与移植相关的代码等等。
2、准备工作在官方网站下载了0.07c 版本的源代码,利用记事本进行阅读。
二、源代码的结构1、源代码组成源代码压缩包解压后,共两个文件夹,doc是说明,src里就是代码。
src文件夹里共五个文件和一个文件夹。
文件夹是option,还有OOreadme.txt、diskio.c、diskio.h、ff.c、ff.h、integer.h。
对比网上的文章,版本已经不同了,已经没有所谓的tff.c 和tff.h 了,估计现在都采用条件编译解决这个问题了,当然文件更少,可能编译选项可能越复杂。
2、00readme.txt 的说明Low level disk I/O module is not included in this archive because the FatFsmodule is only a generic file system layer and not depend on any specificstorage device. You have to provide a low level disk I/O module that writtento control your storage device .主要是说不包含底层10代码,这是个通用文件系统可以在各种介质上使用。
我们移植时针对具体存储设备提供底层代码。
接下来做了版权声明-可以自由使用和传播。
然后对版本的变迁做了说明。
3、源代码阅读次序先读integer.h,了解所用的数据类型,然后是ff.h, 了解文件系统所用的数据结构和各种函数声明,然后是diskio.h,了解与介质相关的数据结构和操作函数。
再把ff.c和diskio.c两个文件所实现的函数大致扫描一遍。
最后根据用户应用层程序调用函数的次序仔细阅读相关代码。
基于51单片机FAT32文件系统程序
基于51单片机FAT32文件系统程序#ifndef __ZNFAT_H__#define __ZNFAT_H__#include "mytype.h" //类型重定义/*******************************************************///znFAT的裁减宏---------------------------------------------------------//#define ZNFAT_ENTER_DIR //有此宏,函数 znFAT_Enter_Dir() 参与编译#define ZNFAT_OPEN_FILE //有此宏,函数 znFAT_Open_File() 参与编译//#define ZNFAT_SEEK_FILE //有此宏,函数 znFAT_Seek_File() 参与编译//#define ZNFAT_READ_FILE //有此宏,函数 znFAT_Read_File() 参与编译//#define ZNFAT_READ_FILEX //有此宏,函数 znFAT_Read_FileX() 参与编译//#define ZNFAT_ADD_DAT //有此宏,函数 znFAT_Add_Dat() 参与编译//#define ZNFAT_CREATE_DIR //有此宏,函数 znFAT_Create_Dir() 参与编译//#define ZNFAT_CREATE_FILE //有此宏,函数 znFAT_Create_File() 参与编译//#define ZNFAT_DEL_FILE //有此宏,函数 znFAT_Del_File() 参与编译//#define ZNFAT_XCOPY_FILE //有此宏,函数 znFAT_XCopy_File() 参与编译//#define ZNFAT_RENAME_FILE //有此宏,函数 znFAT_Rename_File() 参与编译//#define ZNFAT_GET_TOTAL_SIZE //有此宏,函数 znFAT_Get_Total_Size() 参与编译//#define znFAT_GET_REMAIN_CAP //有此宏,函数 znFAT_Get_Remain_Cap() 参与编译#include "cj.h"#include "cj.h"//----------------------------------------------------------------------#define SOC(c) (((c-pArg->FirstDirClust)*(pArg->SectorsPerClust))+pArg->FirstDirSector) // 用于计算簇的开始扇区#define CONST const//设备表#define SDCARD 0 //SD卡#define UDISK 1 //U盘#define CFCARD 2 //CF卡#define OTHER 3 //其它//这里的存储设备表,可以灵活扩充,以实现对更多存储设备的支持//-------------------------------------------#define MAKE_FILE_TIME(h,m,s) ((((unsigned int)h)<<11)+(((unsigned int)m)<<5)+(((unsigned int)s)>>1))/* 生成指定时分秒的文件时间数据 */#define MAKE_FILE_DATE(y,m,d) (((((unsigned int)y)+20)<<9)+(((unsigned int)m)<<5)+((unsigned int)d))/* 生成指定年月日的文件日期数据 *///DPT:分区记录结构如下struct PartRecord{UINT8 Active; //0x80表示此分区有效UINT8 StartHead; //分区的开始磁头UINT8 StartCylSect[2];//开始柱面与扇区UINT8 PartType; //分区类型UINT8 EndHead; //分区的结束头UINT8 EndCylSect[2]; //结束柱面与扇区UINT8 StartLBA[4]; //分区的第一个扇区UINT8 Size[4]; //分区的大小//MBR:分区扇区(绝对0扇区)定义如下struct PartSector{UINT8 PartCode[446]; //MBR的引导程序struct PartRecord Part[4]; //4个分区记录UINT8 BootSectSig0; //55UINT8 BootSectSig1; //AA};//znFAT中对BPB的定义如下一共占用90个字节struct znFAT_BPB{UINT8 BS_jmpBoot[3]; //跳转指令 offset: 0 UINT8 BS_OEMName[8]; // offset: 3 UINT8 BPB_BytesPerSec[2];//每扇区字节数 offset:11 UINT8 BPB_SecPerClus[1]; //每簇扇区数 offset:13 UINT8 BPB_RsvdSecCnt[2]; //保留扇区数目 offset:14 UINT8 BPB_NumFATs[1]; //此卷中FAT表数 offset:16 UINT8 BPB_RootEntCnt[2]; //znFAT为0 offset:17 UINT8 BPB_TotSec16[2]; //znFAT为0 offset:19 UINT8 BPB_Media[1]; //存储介质 offset:21 UINT8 BPB_FATSz16[2]; //znFAT为0 offset:22 UINT8 BPB_SecPerTrk[2]; //磁道扇区数 offset:24 UINT8 BPB_NumHeads[2]; //磁头数 offset:26 UINT8 BPB_HiddSec[4]; //FAT区前隐扇区数 offset:28 UINT8 BPB_TotSec32[4]; //该卷总扇区数 offset:32 UINT8 BPB_FATSz32[4]; //一个FAT表扇区数 offset:36 UINT8 BPB_ExtFlags[2]; //znFAT特有 offset:40 UINT8 BPB_FSVer[2]; //znFAT特有 offset:42 UINT8 BPB_RootClus[4]; //根目录簇号 offset:44 UINT8 FSInfo[2]; //保留扇区FSINFO扇区数offset:48 UINT8 BPB_BkBootSec[2]; //通常为6 offset:50 UINT8 BPB_Reserved[12]; //扩展用 offset:52 UINT8 BS_DrvNum[1]; // offset:64 UINT8 BS_Reserved1[1]; // offset:65 UINT8 BS_BootSig[1]; // offset:66 UINT8 BS_VolID[4]; // offset:67 UINT8 BS_FilSysType[11]; // offset:71 UINT8 BS_FilSysType1[8]; //"znFAT " offset:82 };struct znFAT_FAT_Item{UINT8 Item[4];};struct znFAT_FAT{struct znFAT_FAT_Item Items[128];};struct direntryUINT8 deName[8]; // 文件名,不足部分以空格补充 UINT8 deExtension[3]; // 扩展名,不足部分以空格补充 UINT8 deAttributes; // 文件属性UINT8 deLowerCase; // 0UINT8 deCHundredth; // 世纪UINT8 deCTime[2]; // 创建时间UINT8 deCDate[2]; // 创建日期UINT8 deADate[2]; // 访问日期UINT8 deHighClust[2]; // 开始簇的高字UINT8 deMTime[2]; // 最近的修改时间UINT8 deMDate[2]; // 最近的修改日期UINT8 deLowCluster[2]; // 开始簇的低字UINT8 deFileSize[4]; // 文件大小};//znFAT初始化时初始参数装入如下结构体中struct znFAT_Init_Arg{UINT8 DEV_No;UINT8 BPB_Sector_No; //BPB所在扇区号UINT32 Total_Size; //磁盘的总容量UINT32 FirstDirClust; //根目录的开始簇UINT32 BytesPerSector; //每个扇区的字节数UINT32 FATsectors; //FAT表所占扇区数UINT32 SectorsPerClust; //每簇的扇区数UINT32 FirstFATSector; //第一个FAT表所在扇区UINT32 FirstDirSector; //第一个目录所在扇区};struct Date{UINT16 year;UINT8 month;UINT8 day;};struct Time{UINT8 hour;UINT8 min;UINT8 sec;};struct FileInfoStruct{UINT8 FileName[15]; //文件名UINT32 FileStartCluster; //文件的开始簇UINT32 FileCurCluster; //文件的当前簇UINT32 FileSize; //文件大小UINT32 FileCurSector; //文件的当前扇区UINT16 FileCurPos; //文件在当前扇区中的位置 UINT32 FileCurOffset; //文件的当前偏移量UINT32 Rec_Sec; //文件的文件/目录项所在的扇区UINT16 nRec; //文件的文件/目录项所在扇区中的位置UINT8 FileAttr; //文件属性struct Time FileCreateTime; //文件的创建时间struct Date FileCreateDate; //文件的创建日期struct Time FileMTime; //文件的修改时间struct Date FileMDate; //文件的修改日期struct Date FileADate; //文件的访问日期};struct FSInfo //znFAT的文件系统信息结构{UINT8 Head[4];UINT8 Resv1[480];UINT8 Sign[4];UINT8 Free_Cluster[4];UINT8 Last_Cluster[4];UINT8 Resv2[14];UINT8 Tail[2];};extern struct znFAT_Init_Arg *pArg; //初始化参数结构体指针,用以指向某一存储设备的初始化参数结构体,由外部提供extern UINT8 Dev_No;//设备号,外部变量//函数声明void znFAT_Device_Init();UINT32 znFAT_Get_Total_Size(void); //获取总容量UINT32 znFAT_Get_Remain_Cap(void); //获取剩余容量void znFAT_Init(void); //文件系统初始化UINT32 znFAT_Enter_Dir(CONST INT8 *path); //进入目录UINT8 znFAT_Open_File(struct FileInfoStruct *pfi,CONST INT8 *filepath,UINT32 item,UINT8 is_file); //打开文件,支持通配UINT8 znFAT_Seek_File(struct FileInfoStruct *pfi,UINT32 offset); //文件定位UINT32 znFAT_Read_File(struct FileInfoStruct *pfi,UINT32 offset,UINT32 len,UINT8 *pbuf); //读取文件数据UINT32 znFAT_Read_FileX(struct FileInfoStruct *pfi,UINT32 offset,UINT32 len,void (*pfun)(UINT8)); //读取文件数据并进行数据处理UINT32 znFAT_Add_Dat(struct FileInfoStruct *pfi,UINT32 len,UINT8 *pbuf); //向文件追加数据UINT8 znFAT_Create_Dir(CONST INT8 *dirpath,UINT8 *ptd); //创建目录,支持创建时间UINT8 znFAT_Create_File(struct FileInfoStruct *pfi,CONST INT8 *filepath,UINT8 *ptd); //创建文件,支持创建时间UINT8 znFAT_Del_File(CONST INT8 *filepath); //删除文件unsigned char znFAT_XCopy_File(struct znFAT_Init_Arg *pArg1,struct znFAT_Init_Arg *pArg2,CONST INT8*sfilename,CONST INT8 *tfilename,UINT8 *file_buf,UINT32 buf_size,unsigned char *pt); //文件拷贝,支持多设备中文件互拷UINT8 znFAT_File_Close(struct FileInfoStruct *pfi); //文件关闭UINT8 znFAT_Rename_File(CONST INT8 *filename,CONST INT8 *newfilename); //文件重命名#endif#include "znfat.h"#include "sd.h" //存储设备的扇区读写驱动,这里是SD卡//#include "ch375.h" //存储设备的扇区读写驱动,这里是U盘//#include "cf.h" //存储设备的扇区读写驱动,这里是CF盘#include "string.h"//全局变量定义struct direntry temp_rec;INT8 temp_dir_name[13];UINT32 temp_dir_cluster;UINT32 temp_last_cluster;UINT8 znFAT_Buffer[512]; //扇区数据读写缓冲区,由外部提供/****************************************************************** - 功能描述:znFAT的存储设备初始化函数- 隶属模块:znFAT文件系统模块- 函数属性:外部(用于对存储设备进行初始化)- 参数说明:无- 返回说明:无- 注:在调znFAT其它函数之前,必须先对存储设备进行成功的初始化。
基于stm32的fat32文件系统
Main.c/********************************************************************** ** STM32- 3.2寸TFT液晶屏字符和汉字显示程序** ************************************************************************/#include "stm32f10x_lib.h"#include "LCD_driver.h"#include "fat.h"#include "MMC.h"struct FA T32_Init_Arg Init_Arg_SD; //初始化参数结构体实体struct FA T32_Init_Arg *pArg;struct FileInfoStruct FileInfo; //文件信息结构体实体uchar file_buf[150]; //文件数据缓冲区,读取到的文件数据放在其中uchar Dev_No=0; //设备号,SDCARD的SD卡设备号的宏定义,根据设备号,znFA T会将底层存储设备驱动连接到相应的存储设备驱动//动态的切换设备号,就可以实现在各种存储设备之间进行切换,这也是znFA T实现多设备的重要手段。
比如,我//可以将SD卡上的文件拷贝到CF卡或U盘上,这就是多设备的最典型应用#define COLOR(r,g,b) (((((((uint)r)>>3)<<6)|(((uint)g)>>2))<<5)|(((uint)b)>>3)) //r红色分量0~31 g绿色分量0~63 b蓝色分量0~31#include "LCD.c"/******************************** 变量定义---------------------------------------------------------*/GPIO_InitTypeDef GPIO_InitStructure;ErrorStatus HSEStartUpStatus;unsigned char csd_data[16];unsigned char cid_data[16];unsigned char by;unsigned int c_size, c_size_mult, read_bl_len;unsigned long drive_size;unsigned long size_mb;/*********************************声明函数-----------------------------------------------*/ void RCC_Configuration(void);void NVIC_Configuration(void);void Delay(vu32 nCount);/****************************************************************************** *主函数******************************************************************************* /int main(void){uchar item;RCC_Configuration(); //系统时钟配置函数NVIC_Configuration(); //NVIC配置函数//启动GPIO模块时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);//把调试设置普通IO口GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;//所有GPIO为同一类型端口GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出的最大频率为50HZ GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA端口GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB端口GPIO_Write(GPIOA,0xffff); //将GPIOA 16个端口全部置为高电平GPIO_Write(GPIOB,0xffff); //将GPIOB 16个端口全部置为高电平GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //所有GPIO为同一类型端口GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出的最大频率为50HZ GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA端口LCD_Init();LCD_clear(2); // 这句是显示背景颜色。
详解FAT32文件系统
详解FAT32⽂件系统详解FAT32⽂件系统硬盘是⽤来存储数据的,为了使⽤和管理⽅便,这些数据以⽂件的形式存储在硬盘上。
任何操作系统都有⾃⼰的⽂件管理系统,不同的⽂件系统⼜有各⾃不同的逻辑组织⽅式。
例如:常见的⽂件系统有FAT,NTFS,EXT,UFS,HFS+等等。
下⾯就来学习⼀下基于Windows的FAT32⽂件系统。
FAT32⽂件系统由DBR及其保留扇区,FAT1,FAT2和DATA四个部分组成,其机构如下图:这些结构是在分区被格式化时创建出来的,含义解释如下:DBR及其保留扇区:DBR的含义是DOS引导记录,也称为操作系统引导记录,在DBR之后往往会有⼀些保留扇区。
FAT1:FAT的含义是⽂件分配表,FAT32⼀般有两份FAT,FAT1是第⼀份,也是主FAT。
FAT2:FAT2是FAT32的第⼆份⽂件分配表,也是FAT1的备份。
DATA:DATA也就是数据区,是FAT32⽂件系统的主要区域,其中包含⽬录区域。
⼀、分析FAT32⽂件系统的DBRFAT32⽂件系统的DBR有5部分组成,分别为跳转指令,OEM代号,BPB,引导程序和结束标志。
如下图是我U 盘上⼀个完整的FAT32⽂件系统的DBR。
E8 58 90 :(跳转指令) 本⾝占2字节它将程序执⾏流程跳转到引导程序处。
“EB 58 90″清楚地指明了OS引导代码的偏移位置。
jump 58H加上跳转指令所需的位移量,即开始于0x5A。
4D 53 57 49 4E 34 2E 31 :(OEM代号) 这部分占8字节,其内容由创建该⽂件系统的OEM⼚商具体安排。
跳转指令之后是8字节长的OEM ID,它是⼀个字符串, OEM ID标识了格式化该分区的操作系统的名称和版本号。
为了保留与MS-DOS的兼容性,通常Windows 2000格式化该盘是在FAT16和FAT32磁盘上的该字段中记录了“MSDOS 5.0”,在NTFS磁盘上(关于ntfs,另述),Windows 2000记录的是“NTFS”。
SD_FAT32文件系统接口源码
// 置ቤተ መጻሕፍቲ ባይዱ本次的检测状态。
//
extern int SD_CardInit(void);
//// SD_CardBusy ---- SD_CardBusy ---- SD_CardBusy ---- SD_CardBusy ---- SD_CardBusy ---- SD_CardBus
#define SD_CARD_DOOR_CLOSE (unsigned char)0x10
#define SD_CARD_IS_SD (unsigned char)0x08
#define SD_CARD_IS_MMC (unsigned char)0x04
// User To Select Target Device:
#define F2812 TARGET
#define F2810 0
//---------------------------------------------------------------------------
// Used for calculating delays in micro-seconds:
//
#define CPU_CLOCK_SPEED 6.6667L // for a 150MHz CPU clock speed
#define DELAY_US(A) DSP28x_usDelay(((((long double) A * 1000.0L) / (long double)CPU_CLOCK_SPEED) - 9.0L) / 5.0L)
#define M_INT11 0x0400
FAT32系统对照表
保留 创建时间 创建时间 时分秒 文件内容大小字节 接下 未使用 校验和 文件名第12-13个字符
说明:限于篇幅一下不做排列。在FAT32目录项里,如果文件名大于8个字符的,就使用长目录项+短目录项管理,长目录项是倒序排序的,即靠近短 目录项的是第一个长目录项,排完所有的长目录项 最后排的是短目录项。通俗说:就像楼层地基在最底下,层数是往上数的。短目录项就是楼层基 层,长目录项是叠加楼层 如下图
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
卷标目录项(卷标使用情况下) 短文件名目录项32字节 文件名 文件扩展名 属性 创建日期: 日 月 年 最后访问日期 文件内容起始簇高最后修改时间 最后修改日期 文件起始簇低 长目录项 文件名的第1-5个字符,未使用先填充2个字节的00,后续用0xff填充 序列号 0F属性 文件名的第6-11个字符 ,未使用先填充2个字节的00,后续用0xff填充 保留
低6位扇区号 低6位扇区号 低6位扇区号 低6位扇区号 0
柱面号C0高2位 分区标号 柱面号C0高2位 分区标号 柱面号C0高2位 分区标号 柱面号C0高2位 分区标号 1 2 扩展引导标志
分区结束地址 分区结束地址 分区结束地址 分区结束地址 3 4 5
6
物理扇区号 物理扇区号 物理扇区号 物理扇区号 7 8
长目录项…. 长目录项3 长目录项2 长目录项1 短目录项
F 留扇区数
磁头号
磁头号 磁头号 磁头号 AA F
AA F 标记
F
时间 时分பைடு நூலகம் 接下
即靠近短 项就是楼层基
MBR扇区前 446位引导 代码区接 下来64位 位分区表 后2位是标 志0号扇区
FAT32文件系统实现单片机MP3播放器 源代码
/* FAT32初始化时初始参数装入如下结构体中 */ struct FAT32_Init_Arg { unsigned char BPB_Sector_No; //BPB所在扇区号 unsigned long Total_Size; //磁盘的总容量 unsigned long FirstDirClust; //根目录的开始簇 unsigned long FirstDataSector; //文件数据开始扇区号 unsigned int BytesPerSector; //每个扇区的字节数 unsigned int FATsectors; //FAT表所占扇区数 unsigned int SectorsPerClust; //每簇的扇区数
return temp; } unsigned long FAT32_FindBPB() //寻找BPB所在的扇区号 { MMC_Init(); //SD卡初始化 FAT32_ReadSector(0,FAT32_Buffer); if(FAT32_Buffer[0]!=0xeb) return lb2bb(((((struct PartSector *)(FAT32_Buffer))->Part[0]).StartLBA),4); else return 0; } unsigned long FAT32_Get_Total_Size() //存储器的总容量,单位为M { MMC_Init(); //SD卡初始化 FAT32_ReadSector(Init_Arg.BPB_Sector_No,FAT32_Buffer); return ((float)(lb2bb((((struct FAT32_BPB *)(FAT32_Buffer))>BPB_TotSec32),4)))*0.0004883; } void FAT32_Init(struct FAT32_Init_Arg *arg) { struct FAT32_BPB *bpb; bpb=(struct FAT32_BPB *)(FAT32_Buffer); //将数据缓冲区指针转 为struct FAT32_BPB 型指针 arg->BPB_Sector_No =FAT32_FindBPB(); //FAT32_FindBPB()可以返回BPB所在的扇区号 arg->Total_Size =FAT32_Get_Total_Size(); //FAT32_Get_Total_Size()可以返回磁盘的总容量,单位是兆 arg->FATsectors =lb2bb((bpb->BPB_FATSz32) ,4); //装入FAT表 占用的扇区数到FATsectors中 arg->FirstDirClust =lb2bb((bpb->BPB_RootClus) ,4); //装入根目录簇 号到FirstDirClust中 arg->BytesPerSector =lb2bb((bpb->BPB_BytesPerSec),2); //装入每扇区 字节数到BytesPerSector中
利用MSP430在SD卡上实现FAT32文件系统
利用MSP430在SD卡上实现FAT32文件系统经过一周左右时间的摸索,终于明白了如何用msp30在SD卡实现FAT32文件系统,很开心~在学习的过程中,也发现一个问题,就是网上系统地讲SD卡的资料很少,而讲SDHC卡的资料则更少,所以决定写一篇博客与大家分享,由于SDHC卡大部分内容都与SD卡一样,所以下文除非是特别介绍SDHC卡,其余都会以SD卡代替SDHC卡。
如果发现文中存在问题,欢迎指正,谢谢。
首先,我们先说明一下本文的主要内容,本文的主要侧重点在于利用msp430(其它单片机应该类似)驱动SD卡。
驱动方式选用SPI方式,驱动成功之后,将FAT32文件系统移植过来。
所以如果想要仔细学习FAT32文件系统的,可以忽略本文了,想要快速地利用单片机在SD 卡上实现FAT32文件系统的,可以看一下。
大家可以交流一下。
一、开发之前的准备1、准备WinHex工具工欲善其事,必先利其器。
在开发之前,我们必须要先准备好需要的工具,除了相应的单片机开发平台,我们还需要一个很重要的工具,WinHex。
WinHex可以直接查看磁盘内部的16进制数据。
我们把SD卡用卡槽接到电脑上之后,打开WinHex,点击Tools--Open Disk,然后在Physical Media下选择自己的SD卡,即可打开自己的SD卡。
如下图所示。
这里需要注意的是,一定要在Physical Media下选自己的SD卡,这样看到才是物理地址,否则看到的是逻辑地址,可能会跟你的实际操作不一致,如你在地址为1024的地方写了一段数据,用WinHex在这里却看不到你写的数据。
2、SD卡和SDHC卡目前大家口头上经常说的是SD卡,但实际上,目前所用的大容量的卡其实均是SDHC卡。
SD的容量最大只能到2G,而SDHC卡的容量最小2G,最大32G。
所以,如果你的“SD卡”的容量超过2G了,那其实那是SDHC卡。
FAT32文件系统基本结构
FAT32文件系统基本结构见表1。
注:上表中的超过1字节的数据都以实际数据显示,就是按高位到地位的方式显示。
存储时是按低位到高位存储的。
两者表现不同,请仔细看清楚。
以后出现的表,图均同。
也可以在winhex中看到这些参数的意义:系统启动过程主要由一下几步组成(以硬盘启动为例):1.开机2.BIOS加电自检(Power On Self Test--POST),内存地址为0ffff:00003.将硬盘第一个扇区(0头0道1扇区,也就是BootSector)读入内存地址0000:7c00处.4.检查(WORD)0000:7dfe是否等于0xaa55,若不等于,则转去尝试其他启动介质,如果没有其他启动介质则显示"No ROM BASIC"然后死机.5.跳转到0000:7c00处执行MBR中的程序.6.MBR首先将自己复制到0000:0600处,然后继续执行.7.在主分区表中搜索标志为活动的分区.如果发现没有活动分区或有不止一个活动分区,则转停止.8.将活动分区的第一个扇区读入内存地址0000:7c00处.9.检查(WORD)0000:7dfe是否等于0xaa55,若不等于则显示"Missing Operating System"然后停止,或尝试软盘启动.10.跳转到0000:7c00处继续执行特定系统的启动程序.11.启动系统...以上步骤中2,3,4,5步是由BIOS的引导程序完成.6,7,8,9,10步由MBR中的引导程序完成.附:分区表类型标志如图4DBR区(DOS BOOT RECORD)即操作系统引导记录区的意思,通常占用分区的第0扇区共512个字节(特殊情况也要占用其它保留扇区,我们先说第0扇)。
在这512个字节中,其实又是由跳转指令,厂商标志和操作系统版本号,BPB(BIOS Parameter Block),扩展BPB,os引导程序,结束标志几部分组成。
FAT32文件系统 C语言源代码
//这是FAT32文件系统源代码#ifndef __FAT_H__#define __FAT_H__#define CHAR char#define BYTE unsigned char#define WORD unsigned int#define DWORD unsigned long#define FIX_DIRECTORY 0 /* 1 means use fix directory, 0 for any directory */#if FIX_DIRECTORY==0#define RECORD_ADDR_START 0 /* eeprom start address */#define RECORD_ADDR_END 512 /* eeprom end address *///#include<avr/eeprom.h>//#include<avr/pgmspace.h>//#include<stdio.h>#endif//#include "UART.H"#include <stdlib.h>//#include "gui.h"//声明外部器件读写函数//external hardware operating functionextern unsigned char MMC_SD_ReadSingleBlock(unsigned long sector, unsigned char* buffer); extern unsigned char MMC_SD_WriteSingleBlock(unsigned long sector, unsigned char* buffer); extern unsigned long MMC_SD_ReadCapacity(void);#define MSDOSFSROOT 0 // cluster 0 means the root dir#define CLUST_FREE 0 // cluster 0 also means a free cluster#define MSDOSFSFREE CLUST_FREE#define CLUST_FIRST 2 // first legal cluster number#define CLUST_RSRVD 0xfff6 // reserved cluster range#define CLUST_BAD 0xfff7 // a cluster with a defect#define CLUST_EOFS 0xfff8 // start of eof cluster range#define CLUST_EOFE 0xffff // end of eof cluster range#if 0struct partsector{/*char*/unsigned char psPartCode[/*512-64-2*/446]; // pad so struct is 512bunsigned char psPart[64]; // four partition records (64 bytes)unsigned char psBootSectSig0; // two signature bytes (2 bytes)unsigned char psBootSectSig1;#define BOOTSIG0 0x55#define BOOTSIG1 0xaa};struct extboot {CHAR exDriveNumber; // drive number (0x80)//0x00 for floopy disk 0x80 for hard diskCHAR exReserved1; // reserved should always set 0CHAR exBootSignature; // ext. boot signature (0x29)#define EXBOOTSIG 0x29CHAR exV olumeID[4]; // volume ID numberCHAR exV olumeLabel[11]; // volume label "NO NAME"CHAR exFileSysType[8]; // fs type (FAT12 or FAT)};struct bootsector50 {BYTE bsJump[3]; // jump inst E9xxxx or EBxx90CHAR bsOemName[8]; // OEM name and versionCHAR bsBPB[25]; // BIOS parameter blockCHAR bsExt[26]; // Bootsector ExtensionCHAR bsBootCode[448]; // pad so structure is 512bBYTE bsBootSectSig0; // boot sector signature byte 0x55BYTE bsBootSectSig1; // boot sector signature byte 0xAA#define BOOTSIG0 0x55#define BOOTSIG1 0xaa};struct bpb50 {WORD bpbBytesPerSec; // bytes per sector //512 1024 2048 or 4096BYTE bpbSecPerClust; // sectors per cluster // power of 2WORD bpbResSectors; // number of reserved sectors //1 is recommendBYTE bpbFATs; // number of FATs // 2 is recommendWORD bpbRootDirEnts; // number of root directory entriesWORD bpbSectors; // total number of sectorsBYTE bpbMedia; // media descriptor //0xf8 match the fat[0]WORD bpbFATsecs; // number of sectors per FATWORD bpbSecPerTrack; // sectors per trackWORD bpbHeads; // number of headsDWORD bpbHiddenSecs; // # of hidden sectorsDWORD bpbHugeSectors; // # of sectors if bpbSectors == 0};//MDR-DPT(Disk Partition Table)// length 16 bytes//struct partrecord{struct _DPT{bool bActive_Partition; /*=1:激活*/unsigned char cStart_Head; // starting head for partitionunsigned char cStart_Sector; // starting cylinder and sectorunsigned int iStart_Cylinder; //unsigned char ; // partition type (see above)unsigned char cFat_Index; // ending head for this partitionunsigned int iEnd_Sector; // ending cylinder and sectorunsigned long iEnd_Cylinder; // first LBA sector for this partition unsigned long lSector_Len; // size of this partition (bytes or sectors ?) };#endif//#define BOOTSIG0 0x55//#define BOOTSIG1 0xaa//#define BOOTSIG2 0x00//#define BOOTSIG3 0x00//512 bytes for DBR infostruct DBR{unsigned char cJump[3]; // jump inst E9xxxx or EBxx90unsigned char cOem_Name[8]; // OEM name and versionunsigned char cBpb[53]; // BIOS parameter blockunsigned char cExt_Bpb[26]; // Bootsector Extensionunsigned char cBoot_Code[420]; // pad so structure is 512bunsigned char cEnd_Flag[2]; // boot sector signature byte 0x00};#define FATNUM 0xf // mask for numbering active FAT#define FATMIRROR 0x80 // FAT is mirrored (like it always was)#define FSVERS 0 // currently only 0 is understood//BPB(BIOS Parameter Block)//53bytesstruct BPB {//bpb infounsigned int iBytes_Per_Sector; // bytes per sectorunsigned char cSectors_Per_Clust; // sectors per clusterunsigned int iRsv_Sectors; // number of reserved sectorsunsigned char cFats; // number of FATsunsigned int iRoot_Dir_Entries; // number of root directory entries(fat12/16 only;fat32=0)unsigned int iSmall_Sectors; // total number of sectorsunsigned char cMedia; // media descriptorunsigned int iSectors_Per_Fat16; // number of sectors per FATunsigned int iSectors_Per_Track; // sectors per trackunsigned int iHeads; // number of headsunsigned long lHidden_Sectors; // # of hidden sectorsunsigned long lBig_Sectors; // like bpbFATsecs for FAT32//FAT32特有(地址采用插入方式,FAT16后面的信息往后排)unsigned long lSectors_Per_Fat32;unsigned int iExt_Flag;unsigned int iFile_System_Ver; // filesystem versionunsigned long lRoot_Clust; // start cluster for root directoryunsigned int iFile_System_Info; // filesystem info structure sectorunsigned int iBackup_Boot_Sector; // backup boot sector// unsigned char cRsv_Fat32[12]; // There is a 12 byte filler here, but we ignore it//boot sector infounsigned char cDrv_Num; //(0=软;0x80=硬)// unsigned char cRsv_Fat16; //reservedunsigned char cBoot_Sig; //ext boot sig(0x29)unsigned long lVol_Id; //vol idunsigned char cV ol_Lab[11]; //vol labunsigned char cFile_System_Type[8]; //char for file system};#define SLOT_EMPTY 0x00 // slot has never been used#define SLOT_E5 0x05 // the real value is 0xE5#define SLOT_DELETED 0xE5 // file in this slot deleted#define SLOT_DIR 0x2E // a directorymmm#define ATTR_NORMAL 0x00 // normal file#define ATTR_READONL Y 0x01 // file is readonly#define ATTR_HIDDEN 0x02 // file is hidden#define ATTR_SYSTEM 0x04 // file is a system file#define ATTR_VOLUME 0x08 // entry is a volume label#define ATTR_LONG_FILENAME 0x0F // this is a long filename entry#define ATTR_DIRECTORY 0x10 // entry is a directory name#define ATTR_ARCHIVE 0x20 // file is new or modified#define LCASE_BASE 0x08 // filename base in lower case#define LCASE_EXT 0x10 // filename extension in lower case// Structure of a dos directory entry.//FDTstruct direntry{BYTE deName[8]; // filename, blank filledBYTE deExtension[3]; // extension, blank filledBYTE deAttributes; // file attributesBYTE deLowerCase; // NT VFAT lower case flags (set to zero) BYTE deCHundredth; // hundredth of seconds in CTimeBYTE deCTime[2]; // create timeBYTE deCDate[2]; // create dateBYTE deADate[2]; // access dateunsigned int deHighClust; // high bytes of cluster numberBYTE deMTime[2]; // last update timeBYTE deMDate[2]; // last update dateunsigned int deStartCluster; // starting cluster of fileunsigned long deFileSize; // size of file in bytes};// number of directory entries in one sector#define DIRENTRIES_PER_SECTOR 0x10 //when the bpbBytesPerSec=512// Structure of a Win95 long name directory entrystruct winentry {BYTE weCnt; //#define WIN_LAST 0x40#define WIN_CNT 0x3fBYTE wePart1[10];BYTE weAttributes;#define ATTR_WIN95 0x0fBYTE weReserved1;BYTE weChksum;BYTE wePart2[12];WORD weReserved2;BYTE wePart3[4];};#define WIN_ENTRY_CHARS 13 // Number of chars per winentry// Maximum filename length in Win95// Note: Must be < sizeof(dirent.d_name)#define WIN_MAXLEN 255// This is the format of the contents of the deTime field in the direntry// structure.// We don't use bitfields because we don't know how compilers for// arbitrary machines will lay them out.#define DT_2SECONDS_MASK 0x1F // seconds divided by 2#define DT_2SECONDS_SHIFT 0#define DT_MINUTES_MASK 0x7E0 // minutes#define DT_MINUTES_SHIFT 5#define DT_HOURS_MASK 0xF800 // hours#define DT_HOURS_SHIFT 11// This is the format of the contents of the deDate field in the direntry// structure.#define DD_DAY_MASK 0x1F // day of month#define DD_DAY_SHIFT 0#define DD_MONTH_MASK 0x1E0 // month#define DD_MONTH_SHIFT 5#define DD_YEAR_MASK 0xFE00 // year - 1980#define DD_YEAR_SHIFT 9// Stucturesstruct FileInfoStruct{unsigned long StartCluster; //< file starting cluster for last file accessed unsigned long Size; //< file size for last file accessedunsigned char Attr; //< file attr for last file accessed//unsigned short CreateTime; //< file creation time for last file accessed //unsigned short CreateDate; //< file creation date for last file accessed unsigned long Sector; //<file record placeunsigned int Offset; //<file record offset};extern unsigned char Disp_Bmp(void);extern unsigned char Disp_file_name(void);extern unsigned char FAT_Init();//初始化#if 0extern unsigned long FAT_NextCluster(unsigned long cluster);//查找下一簇号extern unsigned int FAT_FindItem(unsigned long cluster, BYTE *name, struct FileInfoStruct *FileInfo);//查找文件extern unsigned long FAT_OpenDir(BYTE * dir);//打开目录#if FIX_DIRECTORYextern unsigned char Search(BYTE *dir,struct direntry *MusicInfo,WORD *Count,BYTE *type);//查找音乐文件#elseextern BYTE SearchInit(void);extern unsigned char Search(struct direntry *MusicInfo,WORD *Count,BYTE *type);//查找音乐文件#endifextern unsigned char FAT_LoadPartCluster(unsigned long cluster,unsigned part,BYTE * buffer);//加载文件#endif#endif以下是FAT.C源代码/*Fat.c*//*磁盘结构:name size(sector) noteMBR/DPT sector 1 (jmp to DBR by DTP)xxx xDBR sector(BPB) 1 逻辑0扇区//FAT开始rsv sector x (get size by PBP)FAT1 x (get size by PBP)FATX... x (get FATS by PBP)DIR(FDT) 32 file root dir(FAT12/16 only)data all*//*init fat file system1:get MBR or DPT & jmp to DBR by DPTMBR:master boot record(主引导记录)+DPT:Disk Partition Table(磁盘分区表;和MBR同一扇区,跟在它后面)+0x55 0xaa......2.get BPB in DBR(DOS BOOT RECORD):逻辑0扇区,可以由DPT得到物理位置.3.get rsv sectors by BPB4.get fats by BPB5.get fat sectors by BPB6.get root dir sector by BPB(fat12/16 only)*//*每族字节数<=32k*//*根目录:1.根FDT中每32字节一个目录项,可以是文件和目录.2.固定占用32扇区;子目录:1.最前面为父/子目录项("."和"..");2.之后为子目录和文件,32字节1单位;*/#include "FAT.h"#include "tft.h"#include "MMC_SD.h"#include "char.h"unsigned long lFirst_Fat_Sector; // The first FAT sectorunsigned long lFat_Sectors; // The amount sector a FAT occupiedunsigned long lFirst_Dir_Sector; // The first Dir sectorunsigned long lFirst_Dir_Clust; //first directory clusterunsigned long lRoot_Dir_Sectors; // The sector number a Root dir occupiedunsigned long lFirst_Data_Sector; // The first sector number of dataunsigned char cSectors_Per_Clust;BYTE FAT32_Enable;BYTE (* FAT_ReadSector)(DWORD,BYTE *);BYTE (* FAT_WriteSector)(DWORD,BYTE *);//函数指针指向sd卡的读写函数//function pointer to the sd card read & write single block//wirte sector are not use in this playerunsigned char (* FAT_ReadSector)(unsigned long sector, unsigned char * buffer)=MMC_SD_ReadSingleBlock;//device readunsigned char (* FAT_WriteSector)(unsigned long sector, unsigned char * buffer)=MMC_SD_WriteSingleBlock;//device writestruct FileInfoStruct FileInfo;//temporarily buffer for file informationunsigned long lDbr_Sector = 0; /*DBR所在扇取*/unsigned long Capacity;struct BPB bpb;//get DBR(BPB)infovoid Get_Dbr_Info(unsigned char *p){unsigned char i,j;bpb.iBytes_Per_Sector = p[1]<<8 | p[0];bpb.cSectors_Per_Clust = p[2];bpb.iRsv_Sectors = p[4]<<8 | p[3];bpb.cFats = p[5];bpb.iRoot_Dir_Entries = p[7]<<8 | p[6];bpb.iSmall_Sectors = p[9]<<8 | p[8];bpb.cMedia = p[10];bpb.iSectors_Per_Fat16 = p[12]<<8 | p[11];bpb.iSectors_Per_Track = p[14]<<8 | p[13];bpb.iHeads = p[16]<<8 | p[15];bpb.lHidden_Sectors = p[20]<<24 | p[19]<<16 | p[18]<<8 | p[17];bpb.lBig_Sectors = p[24]<<24 | p[23]<<16 | p[22]<<8 | p[21];i = 25;//FAT32时插如信息,FAT16直接运行后面程序if(bpb.iSectors_Per_Fat16 == 0){bpb.lSectors_Per_Fat32 = p[28]<<24 | p[27]<<16 | p[26]<<8 | p[25];bpb.iExt_Flag = p[30]<<8 | p[29];bpb.iFile_System_Ver = p[32]<<8 | p[31];bpb.lRoot_Clust = p[36]<<24 | p[35]<<16 | p[34]<<8 | p[33];bpb.iFile_System_Info = p[38]<<8 | p[37];bpb.iBackup_Boot_Sector = p[40]<<8 | p[39];//12bytsi=53;}//boot sector(FAT16 & FAT32)bpb.cDrv_Num = p[i++];i++; //rsvbpb.cBoot_Sig = p[i++];bpb.lVol_Id = p[i+3]<<24 | p[i+2]<<16 | p[i+1]<<8 | p[i];i += 4;for(j=0; j<11; j++)bpb.cVol_Lab[j] = p[i++];for(j=0; j<8; j++)bpb.cFile_System_Type[j] = p[i++];}//Initialize of FAT need initialize SD firstunsigned char FAT_Init(){struct DBR * bs;unsigned char buffer[512];//1.memory sizeCapacity = MMC_SD_ReadCapacity();if(Capacity < 0xff)return 1;//2.read MBR or DBRif(FAT_ReadSector(0, buffer)) /*read MBR(有可能直接为DBR)*/ return 1;if((buffer[510] != 0x55) || (buffer[511] != 0xaa))return 1;//首扇区=DBR?if((buffer[0]!=0xE9) && (buffer[0]!=0xEB) ){//2.1读取MBR中的DPT(分区表)信息,用于跳到DBRlDbr_Sector = buffer[457]<<24 | buffer[456]<<16 | buffer[455]<<8 | buffer[454];if(lDbr_Sector >= Capacity/512){ /*>所有扇区?*/lDbr_Sector = 0;return 1;}else{//2.2read DBRif(FAT_ReadSector(lDbr_Sector, buffer)) //read DBRreturn 1;//read the bpb sectorif((buffer[510] != 0x55) || (buffer[511] != 0xaa))return 1;if((buffer[0]!=0xE9) && (buffer[0]!=0xEB))return 1;}}//DBR infobs = (struct DBR *)buffer;//3.get bpb infoGet_Dbr_Info(&(bs->cBpb[0])); /*读取DBR(BPB)信息*///4.if(bpb.iSectors_Per_Fat16){ //do not support FAT12FAT32_Enable = 0; //FAT16lFat_Sectors = bpb.iSectors_Per_Fat16; /*FAT占用的扇区数//the sectors number occupied by one fat talbe*/lFirst_Dir_Clust = 2;}else{FAT32_Enable = 1; //FAT32lFat_Sectors = bpb.lSectors_Per_Fat32; /*FAT占用的扇区数//the sectors number occupied by one fat talbe*/lFirst_Dir_Clust = bpb.lRoot_Clust;}//5.lFirst_Fat_Sector = lDbr_Sector + bpb.iRsv_Sectors; /*第一个FAT表扇区= DBR + 保留*///文件分配表≡DBR +保留扇区数lFirst_Dir_Sector = lFirst_Fat_Sector + (bpb.cFats * lFat_Sectors); /*第一个目录扇区= FAT + FAT_SIZE*///根目录≡保留扇区数+FAT的个数×每个FAT的扇区数lRoot_Dir_Sectors = (bpb.iRoot_Dir_Entries * 32) >> 9; /*根目录占用的扇区数= DIR_CNT * 32 / 512;FAT32此项=0*/lFirst_Data_Sector = lFirst_Dir_Sector + lRoot_Dir_Sectors; /*第一个数据扇区= DIR + DIR_SIZE*///数据区≡根目录逻辑扇区号+(32×根目录中目录项数)/ 每扇区字节数return 0;}//读一个簇中的一个扇区//read one sector of one cluster, parameter part indicate which sectorunsigned char FAT_LoadPartCluster(unsigned long cluster,unsigned part,BYTE * buffer){ DWORD sector;sector = lFirst_Data_Sector + (DWORD)(cluster - 2) * (DWORD)bpb.cSectors_Per_Clust;//calculate the actual sector number//逻辑扇区号=数据区起始逻辑扇区号+(簇号-2)×每簇扇区数if(FAT_ReadSector(sector+part, buffer))return 1;elsereturn 0;}//读下一簇簇号//Return the cluster number of next cluster of file//Suitable for system which has limited RAMunsigned long FAT_NextCluster(unsigned long cluster){BYTE buffer[512];DWORD sector;DWORD offset;if(cluster<2)return 0x0ffffff8;//FAT_PTR_SIZE = 2(FAT16); 4(FAT32)//setor offset = (N * FAT_PA T_SIZE) /512if(FAT32_Enable)offset = cluster/128;elseoffset = cluster/ 256;sector = lFirst_Fat_Sector + offset;//calculate the actual sectorif(FAT_ReadSector(sector, buffer))return 0x0ffffff8;//read fat table / return 0xfff8 when error occured//bytes offset = (N * FAT_PTR_SIZE) % 512if(FAT32_Enable){offset=cluster%128; //find the positionsector = ((unsigned long *)buffer)[offset+3]<<24;sector |= ((unsigned long *)buffer)[offset+2]<<16;sector |= ((unsigned long *)buffer)[offset+1]<<8;sector |= ((unsigned long *)buffer)[offset];}else{offset = cluster % 256;//find the positionsector =(buffer)[offset*2+1]<<8;sector |=(buffer)[offset*2];}return (unsigned long)sector; //return the cluste number}#if FIX_DIRECTORY#if 0//在给定目录下查找文件//Find a item in the directory which specify by the parameter "cluster"//Return the start cluster numberunsigned int FAT_FindItem(unsigned long cluster, BYTE *name, struct FileInfoStruct *FileInfo){ BYTE *buffer;DWORD tempclust;DWORD sector;unsigned char cnt;unsigned int offset;unsigned char i;struct direntry *item = 0;if((cluster==0) && (FAT32_Enable == 0)){// root directorybuffer=malloc(512);//apply memoryif(buffer==0)return 1;//if failedfor(cnt=0;cnt<lRoot_Dir_Sectors;cnt++){if(FAT_ReadSector(lFirst_Dir_Sector+cnt,buffer)){free(buffer);return 1;}for(offset=0;offset<512;offset+=32){item=(struct direntry *)(&buffer[offset]);if((item->deName[0] != 0x00) && (item->deName[0] != 0xe5) && (item->deAttributes != 0x0f)){for(i=0;i<11;i++){if(buffer[offset+i]!=name[i])break;}if(i==11){//return the parameter of the itemFileInfo->StartCluster = item->deStartCluster + (((unsigned long)item->deHighClust)<<16);//don't careFileInfo->Size = item->deFileSize;FileInfo->Attr = item->deAttributes;FileInfo->Sector = lFirst_Dir_Sector+cnt;FileInfo->Offset = offset;free(buffer);return 0;}}}}free(buffer);//release}else//other folders{tempclust=cluster;while(1){sector=lFirst_Data_Sector+(DWORD)(tempclust-2)*(DWORD)bpb.cSectors_Per_Clust;//cal culate the actual sector numberbuffer=malloc(512);//apply memoryif(buffer==0)return 1;//if failedfor(cnt=0; cnt<bpb.cSectors_Per_Clust; cnt++){if(FAT_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}for(offset=0;offset<512;offset+=32){item=(struct direntry *)(&buffer[offset]);if((item->deName[0] != 0x00) && (item->deName[0] != 0xe5) && (item->deAttributes != 0x0f)){for(i=0;i<11;i++){if(buffer[offset+i]!=name[i])break;}if(i==11){FileInfo->StartCluster = item->deStartCluster + (((unsigned long)item->deHighClust)<<16);//don't careFileInfo->Size = item->deFileSize;FileInfo->Attr = item->deAttributes;FileInfo->Sector = sector+cnt;FileInfo->Offset = offset;free(buffer);return 0;}}}}free(buffer);//releasetempclust=FAT_NextCluster(tempclust);//next clusterif(tempclust == 0x0fffffff || tempclust == 0x0ffffff8 || (FAT32_Enable == 0 && tempclust == 0xffff))break;}}return 1;}#endif#if 0// find a directory with the given pathunsigned long FAT_OpenDir(BYTE * dir){BYTE name[11];BYTE *p=dir;BYTE deep=0;BYTE i,j;DWORD cluster=0;if(FAT32_Enable)cluster = lFirst_Dir_Clust;if(*p != '\\')return 1;//invalid pathwhile(*p){if(*p == '\\'){deep++;}p++;}p=dir;for(i=0;i<deep-1;i++){p++;for(j=0;j<11;j++)name[j]=0x20;j=0;while(*p != '\\'){if((*p) >= 'a' && (*p) <= 'z')name[j] = (*p++)-0x20;else name[j] = *p++;j++;}if(FAT_FindItem(cluster,name, &FileInfo))return 1;//find the directorycluster = FileInfo.StartCluster;}p++;for(j=0;j<11;j++)name[j]=0x20;j=0;while(*p){if(*p>='a' && *p<='z')name[j]=(*p++)-0x20;else name[j]=*p++;j++;}if(j == 0)return cluster;if(FAT_FindItem(cluster,name, &FileInfo))return 1;//find the final directory cluster = FileInfo.StartCluster;return cluster;}#endif#endif#if 0//复制记录项信息//copy itemvoid CopyDirentruyItem(struct direntry *Desti,struct direntry *Source){BYTE i;for(i=0;i<8;i++)Desti->deName[i] = Source->deName[i];for(i=0;i<3;i++)Desti->deExtension[i] = Source->deExtension[i];Desti->deAttributes = Source->deAttributes;Desti->deLowerCase = Source->deLowerCase;Desti->deCHundredth = Source->deCHundredth;for(i=0;i<2;i++)Desti->deCTime[i] = Source->deCTime[i];for(i=0;i<2;i++)Desti->deCDate[i] = Source->deCDate[i];for(i=0;i<2;i++)Desti->deADate[i] = Source->deADate[i];Desti->deHighClust = Source->deHighClust;for(i=0;i<2;i++)Desti->deMTime[i] = Source->deMTime[i];for(i=0;i<2;i++)Desti->deMDate[i] = Source->deMDate[i];Desti->deStartCluster = Source->deStartCluster;Desti->deFileSize = Source->deFileSize;}#endif#if FIX_DIRECTORY#if 0//search the file , when *count = 0 it will bring the number whole songs, when *cout != 0 the *MusicInfo will bring the infomation of the fileBYTE Search(BYTE *dir,struct direntry *MusicInfo,WORD *Count,BYTE *type)//当COUNT 为零时,有它带回这个目录下总共有多少首音乐{ //不为零时有MusicInfo带回第Count首歌的详细文件信息BYTE *buffer;//BYTE buff[3];DWORD sector;DWORD cluster;DWORD tempclust;unsigned char cnt;unsigned int offset;unsigned int i=0;struct direntry *item = 0;cluster = FAT_OpenDir(dir);if(cluster == 1)return 1;if(cluster==0 && FAT32_Enable==0)// root directory{buffer=malloc(512);//apply memoryif(buffer==0)return 1;//if failedfor(cnt=0;cnt<lRoot_Dir_Sectors;cnt++){if(FAT_ReadSector(lFirst_Dir_Sector+cnt,buffer)){free(buffer);return 1;}for(offset=0;offset<512;offset+=32){item=(struct direntry *)(&buffer[offset]);//pointer convert//find a valid item and display itif((item->deName[0] != '.') && (item->deName[0] != 0x00) &&(item->deName[0] != 0xe5) && (item->deAttributes != 0x0f)){if((item->deExtension[0] == 'b')&&(item->deExtension[1] == 'm')&&(item->deExtension[2] == 'p')){CopyDirentruyItem(MusicInfo,item);*type=1;i++;if(i==*Count){free(buffer);return 0;}}}}}free(buffer);//release}else//other folders{tempclust=cluster;while(1){sector=lFirst_Data_Sector+(DWORD)(tempclust-2)*(DWORD)bpb.cSectors_Per_Clust;//cal culate the actual sector numberbuffer=malloc(512);//apply memoryif(buffer==0)return 1;//if failedfor(cnt=0;cnt<bpb.cSectors_Per_Clust;cnt++){if(FAT_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}for(offset=0;offset<512;offset+=32){item=(struct direntry *)(&buffer[offset]);if((item->deName[0] != '.') && (item->deName[0] != 0x00) && (item->deName[0] != 0xe5) && (item->deAttributes != 0x0f)){if((item->deExtension[0] == 'b')&&(item->deExtension[1] == 'm')&&(item->deExtension[2] == 'p')){CopyDirentruyItem(MusicInfo,item);*type=1;i++;if(i==*Count){free(buffer);return 0;}}}}}free(buffer);//releasetempclust=FAT_NextCluster(tempclust);//next clusterif(tempclust == 0x0fffffff || tempclust == 0x0ffffff8 || (FAT32_Enable == 0 && tempclust == 0xffff))break;}}if(*Count==0)*Count=i;return 0;}#endif#else#if 0void WriteFolderCluster(WORD addr,DWORD cluster){/*#if FAT_DEBUGprintf_P(PSTR("\r\nWrite EEPROM address:%d with value:%ld"),addr,cluster);#endifeeprom_write_byte(addr,cluster>>24);eeprom_write_byte(addr+1,cluster>>16);eeprom_write_byte(addr+2,cluster>>8);eeprom_write_byte(addr+3,cluster>>0);*/}DWORD GetFolderCluster(WORD addr){/* DWORD temp;temp = eeprom_read_byte(addr);temp <<= 8;temp += eeprom_read_byte(addr+1);temp <<= 8;temp += eeprom_read_byte(addr+2);temp <<= 8;temp += eeprom_read_byte(addr+3);#if FAT_DEBUGprintf_P(PSTR("\r\nRead EEPROM address: %d value is: %ld"),addr,temp);#endifreturn temp;*/}#endifstruct direntry fdt;void Get_Fdt_Info(unsigned char *p){unsigned char i;for(i=0; i<8; i++) fdt.deName[i] = p[i];for(i=0; i<3; i++) fdt.deExtension[i] = p[i+8];fdt.deAttributes = p[11];//2byts check :12, 13for(i=0; i<2; i++) fdt.deCTime[i] = p[i+14];for(i=0; i<2; i++) fdt.deCDate[i] = p[i+16];for(i=0; i<2; i++) fdt.deADate[i] = p[i+18];fdt.deHighClust = p[21]<<8;fdt.deHighClust |= p[20];for(i=0; i<2; i++) fdt.deMTime[i] = p[i+22];for(i=0; i<2; i++) fdt.deMDate[i] = p[i+24];fdt.deStartCluster = p[27]<<8;fdt.deStartCluster |= p[26];fdt.deFileSize = p[31]<<24;fdt.deFileSize |= p[30]<<16;fdt.deFileSize |= p[29]<<8;fdt.deFileSize |= p[28];}void delay(unsigned long p){unsigned long i,j,k=0;for(i=0; i<p; i++){for(j=0; j<100000; j++)k++;}}struct BMP_HEADER{unsigned int iFile_Type; // 0unsigned long lFile_Size; // 2//rsv 2bytes // 6//rsv 2bytes // 8unsigned long lBmp_Data_Offset; //offset=10};struct BMP_INFO{unsigned long lInfo_Size; // 14unsigned long lBmp_Width; // 18unsigned long lBmp_Height; // 22//2bytes //26unsigned int iBit_Count; // 28//2bytes // 30unsigned long lImage_Size; // 32unsigned long lXPels_Per_Meter; // 36unsigned long lYPels_Per_Meter; // 40//4bytes};struct BMP_HEADER bmp_header;struct BMP_INFO bmp_info;void Get_Bmp_Info(unsigned char *p){bmp_header.lBmp_Data_Offset = p[13]<<24;bmp_header.lBmp_Data_Offset |= p[12]<<16;bmp_header.lBmp_Data_Offset |= p[11]<<8;bmp_header.lBmp_Data_Offset |= p[10];bmp_info.lBmp_Width = p[21]<<24;bmp_info.lBmp_Width |= p[20]<<16;bmp_info.lBmp_Width |= p[19]<<8;bmp_info.lBmp_Width |= p[18];bmp_info.lBmp_Height = p[25]<<24;bmp_info.lBmp_Height |= p[24]<<16;bmp_info.lBmp_Height |= p[23]<<8;bmp_info.lBmp_Height |= p[22];bmp_info.iBit_Count = p[28];}//注:// 1.目前只做了24位BMP测试,其他没做.// 2.没做4字节对齐处理unsigned char Disp_Bmp(void){unsigned char i, k;unsigned int j;unsigned char cbuf[512];unsigned char cbmp[512];WORD count= 1;unsigned char type , rgb,first ,color_byte,byte1,byte2,byte3 ;unsigned int y,x;unsigned long p,color,tmp_color; //簇指示值//cluster//uint16 color_16bit = 0; //列地址自动加1时使用for(i=0; i<32; i++){ //32扇区根目录if(FAT_ReadSector(lFirst_Dir_Sector+i, cbuf))return 1;for(j=0; j<512; j+=32){Get_Fdt_Info(&(cbuf[j]));//.bpmif((fdt.deName[0] != '.') && (fdt.deName[0] != 0x00) && (fdt.deName[0] != 0xe5)){//if(fdt.deAttributes )if(((fdt.deExtension[0] == 'B') && (fdt.deExtension[1] == 'M') && (fdt.deExtension[2] == 'P'))\|((fdt.deExtension[0] == 'b') && (fdt.deExtension[1] == 'm') && (fdt.deExtension[2] == 'p'))){//Lcd_Fill(0,0,480,272,0);p = fdt.deStartCluster;x = 0 ;y = 0 ;rgb = 0 ;count = 0 ;first = 0 ;smallen_puts(0,0,fdt.deName);CLR_CS_CPLD();FAT_LoadPartCluster(p, k, cbmp);Get_Bmp_Info(cbmp);//read 1 bmp file//未做4bytes对齐转换,图象宽度须为4的倍数while(1){for(k=0; k<bpb.cSectors_Per_Clust; k++){。
51单片机FAT32文件系统程序
UINT8 deAttributes; // 文件属性 UINT8 deLowerCase; // 0 UINT8 deCHundredth; // 世纪 UINT8 deCTime[2]; // 创建时间 UINT8 deCDate[2]; // 创建日期 UINT8 deADate[2]; // 访问日期 UINT8 deHighClust[2]; // 开始簇的高字 UINT8 deMTime[2]; // 最近的修改时间 UINT8 deMDate[2]; // 最近的修改日期 UINT8 deLowCluster[2]; // 开始簇的低字 UINT8 deFileSize[4]; // 文件大小 }; //znFAT初始化时初始参数装入如下结构体中 struct znFAT_Init_Arg { UINT8 DEV_No; UINT8 BPB_Sector_No; //BPB所在扇区号 UINT32 Total_Size; //磁盘的总容量 UINT32 FirstDirClust; //根目录的开始簇 UINT32 BytesPerSector; //每个扇区的字节数 UINT32 FATsectors; //FAT表所占扇区数 UINT32 SectorsPerClust; //每簇的扇区数 UINT32 FirstFATSector; //第一个FAT表所在扇区 UINT32 FirstDirSector; //第一个目录所在扇区 }; struct Date { UINT16 year; UINT8 month; UINT8 day; }; struct Time { UINT8 hour; UINT8 min; UINT8 sec; }; struct FileInfoStruct { UINT8 FileName[15]; //文件名 UINT32 FileStartCluster; //文件的开始簇 UINT32 FileCurCluster; //文件的当前簇 UINT32 FileSize; //文件大小 UINT32 FileCurSector; //文件的当前扇区 UINT16 FileCurPos; //文件在当前扇区中的位置 UINT32 FileCurOffset; //文件的当前偏移量 UINT32 Rec_Sec; //文件的文件/目录项所在的扇区 UINT16 nRec; //文件的文件/目录项所在扇区中的位置 UINT8 FileAttr; //文件属性
(参考)基于stm32的fat32文件系统
(参考)基于stm32的fat32文件系统Main.c/******************************************************************* ** * * * STM32- 3.2寸TFT液晶屏字符和汉字显示程序 ** ********************************************************************* ***/#include "stm32f10x_lib.h"#include "LCD_driver.h"#include "fat.h"#include "MMC.h"struct FAT32_Init_Arg Init_Arg_SD; //初始化参数结构体实体struct FAT32_Init_Arg *pArg;struct FileInfoStruct FileInfo; //文件信息结构体实体uchar file_buf[150]; //文件数据缓冲区,读取到的文件数据放在其中uchar Dev_No=0; //设备号,SDCARD的SD卡设备号的宏定义,根据设备号,znFAT会将底层存储设备驱动连接到相应的存储设备驱动//动态的切换设备号,就可以实现在各种存储设备之间进行切换,这也是znFAT实现多设备的重要手段。
比如,我//可以将SD卡上的文件拷贝到CF卡或U盘上,这就是多设备的最典型应用#define COLOR(r,g,b)(((((((uint)r)>>3)<<6)|(((uint)g)>>2))<<5)|(((uint)b)>>3)) //r红色分量0~31 g绿色分量 0~63 b蓝色分量 0~31#include "LCD.c"/******************************** 变量定义---------------------------------------------------------*/GPIO_InitTypeDef GPIO_InitStructure;ErrorStatus HSEStartUpStatus;unsigned char csd_data[16];unsigned char cid_data[16];unsigned char by;unsigned int c_size, c_size_mult, read_bl_len; unsigned longdrive_size;unsigned long size_mb;/*********************************声明函数 -----------------------------------------------*/void RCC_Configuration(void);void NVIC_Configuration(void);void Delay(vu32 nCount);/******************************************************************* ************主函数******************************************************************** ***********/int main(void){uchar item;RCC_Configuration(); //系统时钟配置函数NVIC_Configuration(); //NVIC配置函数//启动GPIO模块时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);//把调试设置普通IO口GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //所有GPIO为同一类型端口GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出的最大频率为50HZGPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA端口GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB端口GPIO_Write(GPIOA,0xffff); //将GPIOA 16个端口全部置为高电平GPIO_Write(GPIOB,0xffff); //将GPIOB 16个端口全部置为高电平GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //所有GPIO为同一类型端口GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出的最大频率为50HZGPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA端口LCD_Init();LCD_clear(2); // 这句是显示背景颜色。
FAT32文件系统详细介绍(专业)资料
通过使用DiskEditor对硬盘的分析,现对硬盘的MBR区及FAT32文件系统做一个详细的介绍。
新硬盘->低格后变化:所有扇区中的字节数据填充为0x00低格后->分区后变化:写硬盘的MBR(主引导扇区)区分区后->格式华变化:写硬盘的FAT(文件分配表)区MBR区介绍:起始位置:0柱面0磁头1扇区(硬盘的第一个扇区)结束位置:0柱面0磁头1扇区大小:512(硬盘每个扇区的所占用的字节数)个字节000 ~ 1bd (446字节)executable code(我们不使用,固定填写0x00)1be ~ 1cd (16字节)1st partition entry(参数解释见下面)1ce ~ 1dd (16字节)2st partition entry(同第一个分区)1de ~ 1ed (16字节)3st partition entry(同第一个分区)1ee ~ 1fd (16字节)4st partition entry(同第一个分区)1fe ~ 1ff (2字节)boot record signature(固定值:55 aa)现以第一个分区的入口参数为例:80 分区状态(80H表示为激活分区,00H表示为非激活分区)01 分区的开始磁头01 00 分区的开始柱面和扇区(0 ~ 5位为扇区号、8 ~ 15位为柱面号的低8位,6 ~ 7位为柱面号的高两位)0c 分区的类型(0c表示为FAT32,用LBA方式)ff 分区的结束磁头ff fe 分区的结束柱面和扇区(表示同开始磁头)3f 00 00 00 从MBR到第一个分区扇区的扇区个数(一般为硬盘扇区的最大值)fc 8a 38 01 分区的总扇区数(可以计算扇区的总大小)FAT区介绍:起始位置:0柱面1磁头0扇区结束位置:根据硬盘参数不同有所不同大小:硬盘的总簇数×4字节FAT区中的BOOT:起始位置:0柱面1磁头0扇区结束位置:0柱面1磁头0扇区大小:512字节000 ~ 059 (60字节)各个参数(参数解释见下面)000 ~ 059 (420字节)executable code(初始值固定)000 ~ 059 (2字节)boot record signature(固定值:55 aa)现解释各个参数的含义:eb 58 90 跳转代码(固定值:eb 58 90)4d 53 57 49 4e 34 2e 31 OEM名字(固定值:表示MSWIN4.1)00 02 每扇区的字节数(512)08 每簇的扇区数20 00 保留的扇区数(通常固定为32)02 FAT表的个数(通常有2个)00 00 未使用(固定为0)00 00 未使用(固定为0)f8 介质类型(硬盘为f8)00 00 未使用(固定为0)3f 00 每磁道的最大扇区数(硬盘的参数)ff 00 最大磁头数(硬盘的参数)3f 00 00 00 分区中隐藏的扇区数(初始化时写入每磁道的最大扇区数)fc 8a 38 01 分区中的扇区总数(自己根据硬盘参数计算)fc 4d 00 00 每个FAT表占用的扇区数00 00 Flags(Bits 0-4 Indiate Active FAT Copy)(Bit 7 Indicates whether FATmirroring is enabled or disable <clear is enabled>)(if FAT mirroring isdisabled, the FAT information is only written to the copy indicated by bits 0-4)00 00 FAT32驱动版本(固定值:00 00)02 00 00 00 根目录区的开始簇号(00 01 两个簇号不使用)01 00 文件系统信息(后面有相关的说明)扇区所在位置的扇区号(此扇区号为相对位置)06 00 备份引导扇区所在位置的扇区号(此扇区号为相对位置)00 00 00 00 00 00 00 00 00 00 00 00 保留80 分区的逻辑驱动号(第一个分区固定为80,之后依次为81…ntfs分区固定为F6)00 未使用29 扩展标识(固定值:29)ab 0b 64 15 分区的串号(工控机硬盘为74 00 e6 f0)00 00 00 00 00 00 00 00 00 00 00 分区的名称(工控机硬盘为4e 4f 20 4e 41 4d 45 2020 20 20意思为“NO NAME”)46 41 54 33 32 20 20 20 FAT名称(固定值:表示“FAT32”)说明:隐藏扇区是MBR 到FAT BOOT 之间的扇区。
linux应用编程 区分tf卡exfat fat32 ntfs c代码
linux应用编程区分tf卡exfat fat32 ntfs c代码在Linux应用编程中,要区分TF卡(通常指的是microSD 卡)的文件系统类型(如exFAT、FAT32、NTFS),可以使用C语言和Linux系统调用来实现。
下面是一个简单的示例代码,展示了如何使用C语言来检查TF卡的文件系统类型:c复制代码:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/statfs.h>int main(int argc, char *argv[]) {struct statfs buf;if (argc != 2) {printf("Usage: %s <mount_point>\n", argv[0]);return 1;}if (statfs(argv[1], &buf) == -1) {perror("statfs");return 1;}switch (buf.f_type) {case ST_EXFAT:printf("File system is exFAT\n");break;case ST_MSDOS:printf("File system is FAT32\n");break;case ST_NTFS:printf("File system is NTFS\n");break;default:printf("Unknown file system type\n");break;}return 0;}这个示例代码使用statfs系统调用获取指定挂载点的文件系统信息,并根据f_type字段的值来判断文件系统类型。
FAT32文件系统详解
FAT32⽂件系统详解第⼋章FAT32⽂件系统详解Description:OS: Microsoft windows 7、Microsoft Professional xp sp3Software: winhex15.2 SR-10Hardware: Mega16、Kingston 2G sd cardAuthor: FGDTime: 200908088.1 Microsoft⽐尔·盖茨于2008年6⽉27⽇退休了,他在微软同事的⼼⽬中是⼀个什么形象呢?这个当属与他⼀起共同执掌了微软28年之久的CEO鲍尔默最有话语权了。
“他是⼀个⽐较内向的⼩伙⼦,不太爱说话,但浑⾝充满了活⼒,尤其是⼀到晚上就活跃起来。
当时的情况是,经常在我早上醒来时,他才准备睡觉。
”鲍尔默在最近接受《华尔街⽇报》采访时,如此形容⽐尔·盖茨。
鲍尔默说的对,也许只有活⼒才是成功的最关键因素,这是⽐尔·盖茨留给⼤家最好的礼物!1. Life is unfair, you want to adapt it.2. The world will not take your self-esteem, but for the self-satisfaction before you have success.3. Just returned from the school come out when you can not earn 60,000 U.S. dollars a month, but will not become any company vice president, also owned a car until you have won the hand of those that day.4. If you think school teachers is too harsh, then you have to think back to the boss.5. Selling hamburger and not detrimental to your dignity. Your grandparents had a different understanding to sell hamburger, they called it "opportunity".6. If you get into difficulties, it is not the fault of your parents, you should not be the responsibility onto others, and to learn to learn from it.7. Before you were born, your parents do not like so boring. They look into this today because these years have been for you to pay bills, to your laundry. So, in talking to parents, or whatever cleaning your own house?8. You may no longer host school hours and poor health themselves, but life is not the case. In some schools had not "fail" concept, the school will continue to give you the opportunity for you to progress, but real life is not like that.9. Unlike in the life out of school after a semester of the same school hours, nor that the summer. No boss to help you find some self-and you must rely on its own to complete.10. Many of the scenes on television is not real life. In real life, people must do their buried in his work, not like TV where my daily dwell in the case of coffee Lane.11. Treat your aversion to the people, because there days you will work for sucha person.8.2 先说说硬盘【笔者按:这部分知识基本是笔者对《数据重现》⼀书(作者:马林)读书笔记的整理,要了解详更详细的细节,可参考该书或求助互联⽹。
SD卡上建立FAT32文件系统
文件系统的建立1、插入SD卡,注意使用读卡器,尽量不要使用电脑自带的SD插口。
2、格式化SD卡。
注意各选项的设置。
3、点击开始。
格式化完成后,在SD卡中新建名为1.txt的文件,并写入测试数据,如:1234、打开WinHex.exe,选择:工具->打开磁盘,然后打开sd卡,点击确定。
这里可能会出现一些提示或者警告,可以直接无视。
5、选择1.txt,找到找到扇区16448。
6、打开FAT1,找到FF FF FF 0F,并在其后写入04 00 00 00 05 00 00 00 06 00 00 00 FF FF FF 0F。
这里有必要解释一下,因为每个簇我们规定有62个扇区,每个扇区512个字节,也就是说,每个簇是32KB。
在这里我们假定每个txt文件需要90KB,那么至少需要三个簇,这三个簇的标号是4,5,6(从4开始)。
但是如果只需要两个簇,那么只需要4,5就行了。
FF FF FF 0F是结束标识。
7、打开FAT2,并将其改成与FAT1一样。
8、打开Root directory,找到第六行从C列开始,写入00 00 02 00。
为什么呢?因为它表示文件大小。
我们刚才假设一个txt文件要存储90KB的值,这里可以写得稍微大一些,128KB。
00 00 02 00,因为第一个是低字节,所以翻转过来就是00 02 00 00,也就是2^17,即128KB。
9、选择保存并退出WinHex.exe。
10、打开SD卡,查看1.txt。
11、打开Create.bat,用记事本打开。
并照下图修改相应参数。
12、执行Create.bat。
最后打开SD卡,文件系统建立成功。
FAT32文件系统
FAT32文件系统该文档里添加了fat32文件系统的详细图解FAT32文件系统MBR (狭义) 主引导记录第1分区表项MBR (广义) 第2分区表项DPT 第3分区表项第4分区表项0x55AA 间隔63/2047扇区JMP指令及OEM BPB DBR DOS引导代码0x55AA 分区1 FAT FAT2 目录项FDT DATA 数据JMP指令及OEM BPB DBR DOS引导代码0x55AA 分区2 FAT FAT2 目录项FDT DATA 间隔4000多个扇区FAT1 480bits 11bits 19bits 间隔4000多个扇区FAT1 480bits 11bits 19bits16bits 16bits 446bits 16bits 16bitsFAT32文件系统该文档里添加了fat32文件系统的详细图解分区2DATA 数据JMP指令及OEM BPB DBR DOS引导代码0x55AA 分区3 FAT FAT2 目录项FDT DATA 数据扩展分区表EBR 0x55AA 间隔63/2047扇区JMP指令及OEM BPB DBR DOS引导代码扩展分区10x55AA 间隔4000多个扇区FAT1 FAT FAT2 目录项FDT DATA 数据扩展分区表EBR 0x55AA 间隔63/2047扇区64bits 480bits 11bits 19bits64bits 间隔4000多个扇区FAT1 480bits 11bits 19bits2该文档里添加了fat32文件系统的详细图解JMP指令及OEM BPB DBR DOS引导代码扩展分区2 0x55AA 间隔4000多个扇区FAT1 FAT FAT2 目录项FDT DATA 数据11bits 19bits 480bits扩展分区以此类推。
文件定位过程:1.通过BPB找到FAT1;2.通过FAT1定位具体文件所在簇。
文件定位过程:1.通过BPB找到FAT1;2.通过FAT1定位具体文件所在簇。
FAT文件源代码
FAT文件源代码#define IN_FAT#include "User.h"#include "UNICODE.H"#define MAX_DIR_NU_List 32#define MAX_CACHE_SIZE 544ShortFileDirTab *pF;extern INT8U MP3Handle;struct QueueDL{ShortFileDirTab SFDT[MAX_DIR_NU_List];INT8U front,frontE,rear,len,lenE,MaxSize;INT8U ListNu;}QuDirList;struct QueueDC{INT8U Buf[MAX_CACHE_SIZE];INT16U front,rear,len;INT16U MaxSize;}Disk_Cache;extern Disk_Info * GetDiskInfo(INT8U DriveID);void IintQueueDL(struct QueueDL *Q){INT8U i;Q->front = 0;Q->frontE = 0;Q->rear = 0;Q->len = 0;Q->lenE = 0;Q->ListNu = 0;Q->MaxSize = MAX_DIR_NU_List - 2;for(i=0; i<MAX_DIR_NU_List; i++){Q->SFDT[i].FDP.Len = 0;Q->SFDT[i].FDP.OfClu = 0;Q->SFDT[i].FDP.OfSec = 0;Q->SFDT[i].FDP.OfByte = 0;}}void EnQueueDL(struct QueueDL *Q, ShortFileDirTab *x){//向队列插入元素INT8U i;if((Q->rear == Q->frontE) && Q->lenE != 0){//队列满时将产生覆盖Q->frontE = (Q->frontE + 1) % Q->MaxSize; //使队首元素指向下一个位置}for(i=0; i<11; i++){Q->SFDT[Q->rear].SName[i] = x->SName[i];}Q->SFDT[Q->rear].Attr = x->Attr;Q->SFDT[Q->rear].FstClu = x->FstClu;Q->SFDT[Q->rear].FileSize = x->FileSize;Q->SFDT[Q->rear].FDP.OfClu = x->FstClu;Q->rear = (Q->rear + 1) % Q->MaxSize;//求出新队尾if(Q->len < Q->MaxSize)Q->len += 1;//队列长度加1if(Q->lenE < Q->MaxSize)Q->lenE += 1;}ShortFileDirTab * PeekQueueDL(struct QueueDL *Q){//取出队首元素ShortFileDirTab *pSFDT;pSFDT = &Q->SFDT[Q->front];Q->front = (Q->front + 1) % Q->MaxSize;//求出新队首位置if(Q->len >0)Q->len -= 1;//队列长度-1return(pSFDT);}ShortFileDirTab * GetElemQDL(struct QueueDL *Q,INT8U pos) {//读取POS位置的元素if((pos < 1) || (pos > Q->lenE)){return(NULL);}return(&Q->SFDT[(Q->frontE + pos - 1) % Q->MaxSize]); }INT8U GetSizeQDL(struct QueueDL *Q){if(Q != NULL)return(Q->len);elsereturn 0;}void InitQueueDC(struct QueueDC *Q){Q->front = 0;Q->rear = 0;Q->len = 0;Q->MaxSize = 544;}INT16U GetSizeDC(struct QueueDC *Q){if(Q != NULL)return(Q->len);elsereturn 0;}void EnQueueDC(struct QueueDC *Q,INT8U x){//不考虑队列满的情况,实际使用中不出现这种情况Q->Buf[Q->rear] = x;//新值赋给队尾Q->rear = (Q->rear + 1) % Q->MaxSize;//求出队尾的下一个位置if(Q->len < Q->MaxSize)Q->len += 1;//队列长度+1}INT8U PeekQueueDC(struct QueueDC *Q){//取出队首元素INT8U temp;if(Q->len == 0){return 0;}temp = Q->Buf[Q->front];Q->front = (Q->front + 1) % Q->MaxSize;//求出新队首位置if(Q->len >0)Q->len -= 1;//队列长度-1return(temp);}void Uincode_to_GB(INT16U * x){//UNICODE码转换为GB2313汉字编码INT16U a,b,c;if(((*x) >= 0x0020) && ((*x) <= 0x007E))if((*x) >= 'a' && (*x) <= 'z')(*x)-='a'-'A';*x+=0xA380;return;}if((*x)<Unicode[0][0]){*x=0x3F3F;return;}if((*x)>Unicode[UNICODE_MAX-1][0]) {*x=0x3F3F;return;}a=0;b=UNICODE_MAX-1;do //采用二分查表法,因为该表为顺序表{c=(a+b)/2;if((*x)==Unicode[c][0]){*x=Unicode[c][1];return;}if((*x)<Unicode[c][0]){b=(a+b)/2;else{a=(a+b+1)/2;}} while(a!=b);if((*x)==Unicode[a][0]){*x=Unicode[a][1];return;}*x=0x3F3F; //如果找不到,则显示??}ShortFileDirTab * OpenFile(INT8U DirListIndex) {ShortFileDirTab *pSFDT;pSFDT = GetElemQDL(&QuDirList, DirListIndex); return pSFDT;}INT8U CloseFile(ShortFileDirTab **ppSFDT) {if(*ppSFDT == NULL)return 1;(*ppSFDT)->FDP.Len = 0;(*ppSFDT)->FDP.OfClu = (*ppSFDT)->FstClu; (*ppSFDT)->FDP.OfSec = 0;(*ppSFDT)->FDP.OfByte = 0;*ppSFDT = NULL;return 0;}void PrintDir(void){INT8U i,j,tempa,tempb,tempc,len; ShortFileDirTab *pSFDT;len = GetSizeQDL(& QuDirList);for(i=0; i<len; i++){QuDirList.ListNu += 1;tempa = QuDirList.ListNu / 100 + 48; if(tempa > 48)UartPutchar(tempa);elseUartPutchar(' ');tempb = QuDirList.ListNu % 100; tempc = tempb % 10 + 48;tempb = tempb / 10 + 48;if(tempa > 48 || tempb > 48) UartPutchar(tempb);elseUartPutchar(' ');UartPutchar(tempc);UartPutchar('-');pSFDT = PeekQueueDL(&QuDirList); for(j=0; j<11; j++){if(j == 8){if(pSFDT->SName[j] != ' ')UartPutchar('.');}if(pSFDT->SName[j] != ' ')UartPutchar(pSFDT->SName[j]);}UartPutchar('\n');}}INT32U GetNextClu(INT32U Index, INT8U DiskID){INT32U FATOffset;INT32U NextClu; //下一个簇号INT32U ThisFATSceNum; //FAT表中包含该簇号N的扇区号INT16U ThisFATEntOffset; //该簇号N位于FAT表中FAT项的偏移量INT8U Data_Buf[512];Disk_Info *pDI;Disk_RW_Parameter DP;pDI = GetDiskInfo(DiskID);switch(pDI->FilSysType){case FAT16:FATOffset = Index * 2;ThisFATSceNum = FATOffset / pDI->BytsPerSec + pDI->RsvdSecCnt + pDI->RelaStaSect;DP.SectorIndex = ThisFATSceNum;DP.Buf = Data_Buf;(* pDI->DiskDrive)(ReadSec, &DP);ThisFATEntOffset = FATOffset % pDI->BytsPerSec;NextClu = (INT32U)Data_Buf[ThisFATEntOffset] | (INT32U)(Data_Buf[ThisFATEntOffset + 1] << 8);break;case FAT32:FATOffset = Index * 4;ThisFATSceNum = FATOffset / pDI->BytsPerSec + pDI->RsvdSecCnt + pDI->RelaStaSect;DP.SectorIndex = ThisFATSceNum;DP.Buf = Data_Buf;(* pDI->DiskDrive)(ReadSec, &DP);ThisFATEntOffset = FATOffset % pDI->BytsPerSec;NextClu = (INT32U)Data_Buf[ThisFATEntOffset] |(INT32U)(Data_Buf[ThisFATEntOffset + 1] <<8) |(INT32U)(Data_Buf[ThisFATEntOffset + 2] << 16) |(INT32U)(Data_Buf[ThisFATEntOffset + 3] << 24);break;}return(NextClu);}INT8U GetFDI(ShortFileDirTab *pSFDT, INT8U DiskID){INT8U i,k,temp,flag;INT8U Data_Buf[512];INT16U j;INT32U NextCluOfFAT; //文件簇链中下一个簇号INT32U FirstSectorOfCluster; //该簇号第一个扇区号INT32U FistRootDirSecNum; //根目录第一个扇区号Disk_Info *pDI;Disk_RW_Parameter DP;ShortFileDirTab SFDT;pDI = GetDiskInfo(DiskID);IintQueueDL(&QuDirList);if((pSFDT->Attr == 0xF0) && (pSFDT->FstClu == 0)){//该卷为FAT16且读的是根目录FistRootDirSecNum = pDI->RsvdSecCnt + (pDI->NumFATs * pDI->FATSz16) + pDI->RelaStaSect;FirstSectorOfCluster = FistRootDirSecNum;flag = 1;}else{FirstSectorOfCluster = ((pSFDT->FstClu - 2) * pDI->SecPerClus) + pDI->FirstDataSector;flag = 0;}DP.Buf = Data_Buf;DP.SectorIndex = FirstSectorOfCluster + pSFDT->FDP.OfSec;(* pDI->DiskDrive)(ReadSec, &DP);for(i=0; ; ){j = pSFDT->FDP.OfByte;SFDT.SName[0] = Data_Buf[j + OFSDIR_SName];SFDT.SName[1] = Data_Buf[j + OFSDIR_SName + 1];SFDT.Attr = Data_Buf[j + OFSDIR_Attr];if(((SFDT.Attr & ATTR_LONG_NAME_MASK) != ATTR_LONG_NAME) && (SFDT.SName[0] != 0xE5) && (SFDT.SName[0] != 0)){//找到一个活动的短目录项if((SFDT.Attr & ATTR_VOLUME) == 0){//找到一个文件或子目录for(k=2; k<11; k++){SFDT.SName[k] = Data_Buf[j + OFSDIR_SName + k];}SFDT.FstClu = ((INT32U)Data_Buf[j + OFSDIR_FstCluH + 1] << 24) |((INT32U)Data_Buf[j + OFSDIR_FstCluH] << 16) |((INT32U)Data_Buf[j + OFSDIR_FstCluL +1 ] << 8) |((INT32U)Data_Buf[j + OFSDIR_FstCluL]);SFDT.FileSize = ((INT32U)Data_Buf[j + OFSDIR_FileSize + 3] << 24) |((INT32U)Data_Buf[j + OFSDIR_FileSize + 2] << 16) |((INT32U)Data_Buf[j + OFSDIR_FileSize + 1] << 8) |((INT32U)Data_Buf[j + OFSDIR_FileSize]);if((SFDT.SName[0] == '.') && (SFDT.SName[1] == '.')){//是dotdot目录(指向上级目录)for(k=2; k<11; k++){QuDirList.SFDT[MAX_DIR_NU_List -1].SName[k] = SFDT.SName[k];}QuDirList.SFDT[MAX_DIR_NU_List -1].Attr = SFDT.Attr;QuDirList.SFDT[MAX_DIR_NU_List -1].FstClu = SFDT.FstClu;QuDirList.SFDT[MAX_DIR_NU_List -1].FileSize = SFDT.FileSize;}else if(SFDT.SName[0] == '.'){//是dot目录(指向该目录本身)for(k=2; k<11; k++){QuDirList.SFDT[MAX_DIR_NU_List -2].SName[k] = SFDT.SName[k];}QuDirList.SFDT[MAX_DIR_NU_List -2].Attr = SFDT.Attr;QuDirList.SFDT[MAX_DIR_NU_List -2].FstClu = SFDT.FstClu;QuDirList.SFDT[MAX_DIR_NU_List -2].FileSize = SFDT.FileSize;}else{//是普通子目录或文件EnQueueDL(&QuDirList, &SFDT);i ++;}}}else if(SFDT.SName[0] == 0x00){//此目录为空,并且后续的磁盘空间都为空pSFDT->FDP.OfClu = pSFDT->FstClu;pSFDT->FDP.Len = 0;pSFDT->FDP.OfByte = 0;PrintDir();return 0;}j += 32;if(j > (pDI->BytsPerSec - 32)){j = 0;pSFDT->FDP.OfSec += 1;if(flag == 0){if(pSFDT->FDP.OfSec >= pDI->SecPerClus){//读下一个簇pSFDT->FDP.OfSec = 0;pSFDT->FDP.OfClu = GetNextClu(pSFDT->FDP.OfClu, DiskID);NextCluOfFAT = pSFDT->FDP.OfClu;if(pDI->FilSysType == FAT16){if((NextCluOfFAT >= 0x0002) && (NextCluOfFAT <= 0xFFEF)) {FirstSectorOfCluster = ((NextCluOfFAT - 2) * pDI->SecPerClus) + pDI->FirstDataSector;}else{//所有簇已读完pSFDT->FDP.OfClu = pSFDT->FstClu;pSFDT->FDP.Len = 0;pSFDT->FDP.OfSec = 0;pSFDT->FDP.OfByte = 0;return 0;}}else if(pDI->FilSysType == FAT32){if((NextCluOfFAT >= 0x00000002) && (NextCluOfFAT <= 0xFFFFFFEF)){FirstSectorOfCluster = ((NextCluOfFAT - 2) * pDI->SecPerClus) + pDI->FirstDataSector;}else{//所有簇已读完pSFDT->FDP.OfClu = pSFDT->FstClu;pSFDT->FDP.Len = 0;pSFDT->FDP.OfSec = 0;pSFDT->FDP.OfByte = 0;return 0;}}}}else if(flag == 1){if(pSFDT->FDP.OfSec >= pDI->RootDirSectors){//所有簇已读完pSFDT->FDP.OfClu = pSFDT->FstClu;pSFDT->FDP.Len = 0;pSFDT->FDP.OfSec = 0;pSFDT->FDP.OfByte = 0;return 0;}}DP.SectorIndex = FirstSectorOfCluster + pSFDT->FDP.OfSec; (* pDI->DiskDrive)(ReadSec, &DP);//读下一个扇区}pSFDT->FDP.OfByte = j;pSFDT->FDP.Len += 32;temp = QuDirList.MaxSize - GetSizeQDL(&QuDirList);if(temp == 0){PrintDir();i = 0;}}}INT8U ChangeDir(INT8U DirListIndex, INT8U DriveID){Disk_Info *pDI;ShortFileDirTab *pSFDT;pDI = GetDiskInfo(DriveID);switch(DirListIndex){case '\\':if(pDI->FilSysType == FAT16){QuDirList.SFDT[MAX_DIR_NU_List - 1].Attr = 0xF0;QuDirList.SFDT[MAX_DIR_NU_List - 1].FstClu = 0;QuDirList.SFDT[MAX_DIR_NU_List - 1].FileSize = 0;GetFDI(&QuDirList.SFDT[MAX_DIR_NU_List - 1],DriveID);}else if(pDI->FilSysType == FAT32){QuDirList.SFDT[MAX_DIR_NU_List - 1].Attr = 0xF0;QuDirList.SFDT[MAX_DIR_NU_List - 1].FstClu = pDI->RootClus;QuDirList.SFDT[MAX_DIR_NU_List - 1].FileSize = 0;GetFDI(&QuDirList.SFDT[MAX_DIR_NU_List - 1],DriveID);}break;case '*':GetFDI(&QuDirList.SFDT[MAX_DIR_NU_List - 1], DriveID);break;case '.':GetFDI(&QuDirList.SFDT[MAX_DIR_NU_List - 2], DriveID);break;default:pSFDT = GetElemQDL(&QuDirList, DirListIndex);GetFDI(pSFDT, DriveID);}return 0;}INT8U ReadFile(ShortFileDirTab *pSFDT, INT16U Len, INT8U DiskID){INT8U Data_Buf[512];INT16U i;INT32U NextCluOfFAT; //文件簇链中下一个簇号INT32U FirstSectorOfCluster; //该簇号第一个扇区号Disk_Info *pDI;Disk_RW_Parameter DP;if(Len > 512){return PARAMETER_ERR;}pDI = GetDiskInfo(DiskID);DP.Buf = Data_Buf;if((pSFDT->FDP.Len + Len) <= pSFDT->FileSize){DP.Len = Len;}else{DP.Len = pSFDT->FileSize - pSFDT->FDP.Len;}FirstSectorOfCluster = ((pSFDT->FDP.OfClu - 2) * pDI->SecPerClus) + pDI->FirstDataSector;DP.SectorIndex = (FirstSectorOfCluster + pSFDT->FDP.OfSec) * 512 + pSFDT->FDP.OfByte;(* pDI->DiskDrive)(ReadBlock, &DP);pSFDT->FDP.Len = (pSFDT->FDP.Len + DP.Len) % pSFDT->FileSize;pSFDT->FDP.OfByte += Len;pSFDT->FDP.OfSec += pSFDT->FDP.OfByte / 512;pSFDT->FDP.OfByte %= 512;for(i=0; i<DP.Len; i++){EnQueueDC(&Disk_Cache, Data_Buf[i]);}if(pSFDT->FDP.OfSec >= pDI->SecPerClus){//取下一个簇号pSFDT->FDP.OfSec = 0;pSFDT->FDP.OfClu = GetNextClu(pSFDT->FDP.OfClu, DiskID);NextCluOfFAT = pSFDT->FDP.OfClu;if(pDI->FilSysType == FAT16){if((NextCluOfFAT < 0x0002) || (NextCluOfFAT > 0xFFEF)){//所有簇已读完pSFDT->FDP.OfClu = pSFDT->FstClu;pSFDT->FDP.Len = pSFDT->FileSize;pSFDT->FDP.OfSec = 0;pSFDT->FDP.OfByte = 0;return FILE_EOF;}}else if(pDI->FilSysType == FAT32){if((NextCluOfFAT < 0x00000002) || (NextCluOfFAT > 0xFFFFFFEF)){//所有簇已读完pSFDT->FDP.OfClu = pSFDT->FstClu;pSFDT->FDP.Len = pSFDT->FileSize;pSFDT->FDP.OfSec = 0;pSFDT->FDP.OfByte = 0;return FILE_EOF;}}}return 0;}INT32U GetFileSize(void){return pF->FileSize;}INT8U ReadFileByte(void){void FileOperation(INT8U List_NU);INT8U data;INT16U len;data = PeekQueueDC(&Disk_Cache);len = GetSizeDC(&Disk_Cache);if(len < 480)FileOperation('r');return data;}void FileOperation(INT8U List_NU) {INT8U temp,j;//INT16U flen;switch(List_NU){case '\\':case '*':case '.':ChangeDir(List_NU, 'A');break;case 'c':CloseFile(&pF);break;case 'r':if(pF != NULL){if(pF->FDP.Len < pF->FileSize) temp = ReadFile(pF, 32, 'A');elseCloseFile(&pF);/*flen = GetSizeDC(&Disk_Cache); if((temp = FILE_EOF) && (flen == 0)){UartPrint((void *)("\nfile end"));}elsefor(i=0; i<flen; i++){temp = PeekQueueDC(&Disk_Cache);UartPutchar(temp);}*/}break;default:if(List_NU > 0 && List_NU <= QuDirList.MaxSize){CloseFile(&pF);pF = OpenFile(List_NU);if((pF->Attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == 0x00) {//读取文件中数据InitQueueDC(&Disk_Cache);if(pF != NULL){temp = ReadFile(pF, 512, 'A');if(temp != FILE_EOF){if(pF->SName[8] == 'M' && pF->SName[9] == 'P' && pF->SName[10] == '3'){MP3Handle = MP3CMD_Play;UartPrint((void *)("\nPlaying "));for(j=0; j<11; j++){if(j == 8){if(pF->SName[j] != ' ')UartPutchar('.');}if(pF->SName[j] != ' ')UartPutchar(pF->SName[j]);}}}/*flen = GetSizeDC(&Disk_Cache);if((temp = FILE_EOF) && (flen == 0)){UartPrint((void *)("\nfile end"));}elsefor(i=0; i<flen; i++){temp = PeekQueueDC(&Disk_Cache);UartPutchar(temp);}*/}}else if((pF->Attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == ATTR_DIRECTORY){//改变当前目录ChangeDir(List_NU, 'A'); }}}}。
stm32sdiofatfs文件系统源码分析
、概述1、目的在移植之前,先将源代码大概的阅读一遍,主要是了解文件系统的结构、各个函数的功能和接口、与移植相关的代码等等。
2、准备工作在官方网站下载了0.07c 版本的源代码,利用记事本进行阅读。
二、源代码的结构1、源代码组成源代码压缩包解压后,共两个文件夹,doc是说明,src里就是代码。
src文件夹里共五个文件和一个文件夹。
文件夹是option,还有OOreadme.txt、diskio.c、diskio.h、ff.c、ff.h、integer.h。
对比网上的文章,版本已经不同了,已经没有所谓的tff.c 和tff.h 了,估计现在都采用条件编译解决这个问题了,当然文件更少,可能编译选项可能越复杂。
2、00readme.txt 的说明Low level disk I/O module is not included in this archive because the FatFsmodule is only a generic file system layer and not depend on any specificstorage device. You have to provide a low level disk I/O module that writtento control your storage device .主要是说不包含底层10代码,这是个通用文件系统可以在各种介质上使用。
我们移植时针对具体存储设备提供底层代码。
接下来做了版权声明-可以自由使用和传播。
然后对版本的变迁做了说明。
3、源代码阅读次序先读integer.h,了解所用的数据类型,然后是ff.h, 了解文件系统所用的数据结构和各种函数声明,然后是diskio.h,了解与介质相关的数据结构和操作函数。
再把ff.c和diskio.c两个文件所实现的函数大致扫描一遍。
最后根据用户应用层程序调用函数的次序仔细阅读相关代码。
FAT32文件格式示例解析
FAT32⽂件格式⽰例解析1.前⾔本⽂主要以⼀个⽰例来分析FAT32⽂件系统的格式,对FAT32⽂件系统的各个区域详细分析。
2.FAT32⽂件系统典型分区3.FAT32⽂件系统⽰例按如下步骤在ubuntu下创建FAT32⽂件系统:1.chenbo@chenbo-ThinkPad-R61:~$ cd /tmp/2.创建⽂件test.imgchenbo@chenbo-ThinkPad-R61:/tmp$ sudo dd if=/dev/zero of=test.img bs=512count=800003.创建FAT32⽂件系统chenbo@chenbo-ThinkPad-R61:/tmp$ sudo mkfs.vfat -F 32 test.img4.将test.img挂载在/mntchenbo@chenbo-ThinkPad-R61:/tmp$ sudo mount test.img /mnt5.创建test1 test2 test3三个⽬录chenbo@chenbo-ThinkPad-R61:/mnt$ sudo mkdir test1 test2 test36.在test1下创建test1-1 test1-1-1⽬录chenbo@chenbo-ThinkPad-R61:/mnt$ cd test1chenbo@chenbo-ThinkPad-R61:/mnt/test1$ sudo mkdir test1-1chenbo@chenbo-ThinkPad-R61:/mnt/test1$ cd test1-1/chenbo@chenbo-ThinkPad-R61:/mnt/test1/test1-1$ sudo mkdir test1-1-17.创建hello.txt⽂件,写⼊内容,拷贝到test1/test1-1/test1-1-1下chenbo@chenbo-ThinkPad-R61:/tmp$ touch hello.txtchenbo@chenbo-ThinkPad-R61:/tmp$ echo you are my friend! > hello.txtchenbo@chenbo-ThinkPad-R61:/tmp$ sudo cp hello.txt /mnt/test1/test1-1/test1-1-1/8.执⾏完如上步骤后,通过hexdump查看⽂件系统内容chenbo@chenbo-ThinkPad-R61:/tmp$ sudo umount /mntchenbo@chenbo-ThinkPad-R61:/tmp$ hexdump -C test.img00000000 eb 58 90 6d 6b 66 73 2e 66 61 74 00 02 01 20 00 |.X.mkfs.fat... .| 00000010 02 00 00 00 00 f8 00 00 20 00 40 00 00 00 00 00 |........ .@.....| 00000020 80 38 01 00 68 02 00 00 00 00 00 00 02 00 00 00 |.8..h...........| 00000030 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 80 00 29 80 73 bc 92 4e 4f 20 4e 41 4d 45 20 20 |..).s..NO NAME | 00000050 20 20 46 41 54 33 32 20 20 20 0e 1f be 77 7c ac | FAT32 ...w|.| 00000060 22 c0 74 0b 56 b4 0e bb 07 00 cd 10 5e eb f0 32 |".t.V.......^..2| 00000070 e4 cd 16 cd 19 eb fe 54 68 69 73 20 69 73 20 6e |.......This is n| 00000080 6f 74 20 61 20 62 6f 6f 74 61 62 6c 65 20 64 69 |ot a bootable di| 00000090 73 6b 2e 20 20 50 6c 65 61 73 65 20 69 6e 73 65 |sk. Please inse| 000000a0 72 74 20 61 20 62 6f 6f 74 61 62 6c 65 20 66 6c |rt a bootable fl| 000000b0 6f 70 70 79 20 61 6e 64 0d 0a 70 72 65 73 73 20 |oppy and..press | 000000c0 61 6e 79 20 6b 65 79 20 74 6f 20 74 72 79 20 61 |any key to try a| 000000d0 67 61 69 6e 20 2e 2e 2e 20 0d 0a 00 00 00 00 00 |gain ... .......| 000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|* 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| 00000200 52 52 61 41 00 00 00 00 00 00 00 00 00 00 00 00 |RRaA............| 00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|* 000003e0 00 00 00 00 72 72 41 61 89 33 01 00 08 00 00 00 |....rrAa.3......| 000003f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| 00000400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|* 00000c00 eb 58 90 6d 6b 66 73 2e 66 61 74 00 02 01 20 00 |.X.mkfs.fat... .| 00000c10 02 00 00 00 00 f8 00 00 20 00 40 00 00 00 00 00 |........ .@.....| 00000c20 80 38 01 00 68 02 00 00 00 00 00 00 02 00 00 00 |.8..h...........| 00000c30 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000c40 80 00 29 80 73 bc 92 4e 4f 20 4e 41 4d 45 20 20 |..).s..NO NAME | 00000c50 20 20 46 41 54 33 32 20 20 20 0e 1f be 77 7c ac | FAT32 ...w|.| 00000c60 22 c0 74 0b 56 b4 0e bb 07 00 cd 10 5e eb f0 32 |".t.V.......^..2| 00000c70 e4 cd 16 cd 19 eb fe 54 68 69 73 20 69 73 20 6e |.......This is n| 00000c80 6f 74 20 61 20 62 6f 6f 74 61 62 6c 65 20 64 69 |ot a bootable di| 00000c90 73 6b 2e 20 20 50 6c 65 61 73 65 20 69 6e 73 65 |sk. Please inse| 00000ca0 72 74 20 61 20 62 6f 6f 74 61 62 6c 65 20 66 6c |rt a bootable fl|00000cb0 6f 70 70 79 20 61 6e 64 0d 0a 70 72 65 73 73 20 |oppy and..press | 00000cc0 61 6e 79 20 6b 65 79 20 74 6f 20 74 72 79 20 61 |any key to try a| 00000cd0 67 61 69 6e 20 2e 2e 2e 20 0d 0a 00 00 00 00 00 |gain ... .......| 00000ce0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|* 00000df0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| 00000e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|* 00004000 f8 ff ff 0f ff ff ff 0f f8 ff ff 0f ff ff ff 0f |................|00004010 ff ff ff 0f ff ff ff 0f ff ff ff 0f ff ff ff 0f |................|00004020 ff ff ff 0f 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00004030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|* 00051000 f8 ff ff 0f ff ff ff 0f f8 ff ff 0f ff ff ff 0f |................|00051010 ff ff ff 0f ff ff ff 0f ff ff ff 0f ff ff ff 0f |................|00051020 ff ff ff 0f 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00051030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|* 0009e000 41 74 00 65 00 73 00 74 00 31 00 0f 00 2e 00 00 |At.e.s.t.1......| 0009e010 ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff |................|0009e020 54 45 53 54 31 20 20 20 20 20 20 10 00 00 ba 23 |TEST1 ....#| 0009e030 4d 4c 4d 4c 00 00 ba 23 4d 4c 03 00 00 00 00 00 |MLML...#ML......| 0009e040 41 74 00 65 00 73 00 74 00 32 00 0f 00 9a 00 00 |At.e.s.t.2......| 0009e050 ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff |................|0009e060 54 45 53 54 32 20 20 20 20 20 20 10 00 00 a1 23 |TEST2 ....#| 0009e070 4d 4c 4d 4c 00 00 a1 23 4d 4c 04 00 00 00 00 00 |MLML...#ML......| 0009e080 41 74 00 65 00 73 00 74 00 33 00 0f 00 76 00 00 |At.e.s.t.3...v..| 0009e090 ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff |................|0009e0a0 54 45 53 54 33 20 20 20 20 20 20 10 00 00 a1 23 |TEST3 ....#| 0009e0b0 4d 4c 4d 4c 00 00 a1 23 4d 4c 05 00 00 00 00 00 |MLML...#ML......| 0009e0c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|* 0009e200 2e 20 20 20 20 20 20 20 20 20 20 10 00 00 a1 23 |. ....#| 0009e210 4d 4c 4d 4c 00 00 a1 23 4d 4c 03 00 00 00 00 00 |MLML...#ML......| 0009e220 2e 2e 20 20 20 20 20 20 20 20 20 10 00 00 a1 23 |.. ....#| 0009e230 4d 4c 4d 4c 00 00 a1 23 4d 4c 00 00 00 00 00 00 |MLML...#ML......| 0009e240 41 74 00 65 00 73 00 74 00 31 00 0f 00 a7 2d 00 |At.e.s.t.1....-.| 0009e250 31 00 00 00 ff ff ff ff ff ff 00 00 ff ff ff ff |1...............|0009e260 54 45 53 54 31 2d 31 20 20 20 20 10 00 64 c3 23 |TEST1-1 ..d.#| 0009e270 4d 4c 4d 4c 00 00 c3 23 4d 4c 06 00 00 00 00 00 |MLML...#ML......|0009e280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*0009e400 2e 20 20 20 20 20 20 20 20 20 20 10 00 00 a1 23 |. ....#|0009e410 4d 4c 4d 4c 00 00 a1 23 4d 4c 04 00 00 00 00 00 |MLML...#ML......| 0009e420 2e 2e 20 20 20 20 20 20 20 20 20 10 00 00 a1 23 |.. ....#|0009e430 4d 4c 4d 4c 00 00 a1 23 4d 4c 00 00 00 00 00 00 |MLML...#ML......| 0009e440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*0009e600 2e 20 20 20 20 20 20 20 20 20 20 10 00 00 a1 23 |. ....#|0009e610 4d 4c 4d 4c 00 00 a1 23 4d 4c 05 00 00 00 00 00 |MLML...#ML......| 0009e620 2e 2e 20 20 20 20 20 20 20 20 20 10 00 00 a1 23 |.. ....#|0009e630 4d 4c 4d 4c 00 00 a1 23 4d 4c 00 00 00 00 00 00 |MLML...#ML......| 0009e640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*0009e800 2e 20 20 20 20 20 20 20 20 20 20 10 00 00 ba 23 |. ....#|0009e810 4d 4c 4d 4c 00 00 ba 23 4d 4c 06 00 00 00 00 00 |MLML...#ML......| 0009e820 2e 2e 20 20 20 20 20 20 20 20 20 10 00 00 ba 23 |.. ....#|0009e830 4d 4c 4d 4c 00 00 ba 23 4d 4c 03 00 00 00 00 00 |MLML...#ML......| 0009e840 41 74 00 65 00 73 00 74 00 31 00 0f 00 0e 2d 00 |At.e.s.t.1....-.|0009e850 31 00 2d 00 31 00 00 00 ff ff 00 00 ff ff ff ff |1.-.1...........|0009e860 54 45 53 54 31 2d 7e 31 20 20 20 10 00 64 45 24 |TEST1-~1 ..dE$| 0009e870 4d 4c 4d 4c 00 00 45 24 4d 4c 07 00 00 00 00 00 |MLML..E$ML......| 0009e880 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*0009ea00 2e 20 20 20 20 20 20 20 20 20 20 10 00 64 c3 23 |. ..d.#|0009ea10 4d 4c 4d 4c 00 00 c3 23 4d 4c 07 00 00 00 00 00 |MLML...#ML......| 0009ea20 2e 2e 20 20 20 20 20 20 20 20 20 10 00 64 c3 23 |.. ..d.#|0009ea30 4d 4c 4d 4c 00 00 c3 23 4d 4c 06 00 00 00 00 00 |MLML...#ML......| 0009ea40 41 68 00 65 00 6c 00 6c 00 6f 00 0f 00 f1 2e 00 |Ah.e.l.l.o......|0009ea50 74 00 78 00 74 00 00 00 ff ff 00 00 ff ff ff ff |t.x.t...........|0009ea60 48 45 4c 4c 4f 20 20 20 54 58 54 20 00 64 45 24 |HELLO TXT .dE$| 0009ea70 4d 4c 4d 4c 00 00 45 24 4d 4c 08 00 13 00 00 00 |MLML..E$ML......| 0009ea80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*0009ec00 79 6f 75 20 61 72 65 20 6d 79 20 66 72 69 65 6e |you are my frien| 0009ec10 64 21 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 |d!..............|0009ec20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*0271000044.⽰例解析对如上创建的⽂件系统进⾏解析如下。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
extern bdata bit fat_open_mode; /* READ or WRITE */
extern bdata bit fat_2_is_present; /* TRUE: 2 FATs - FALSE: 1 FAT */
extern bdata bit dir_is_root; /* TRUE: point the root directory */
extern bdata bit fat_is_fat16; /* TRUE: FAT16 - FALSE: FAT12 */
/* disk management */
extern data Uint32 fat_ptr_fats; /* address of the first byte of FAT */
extern data Uint32 fat_ptr_data; /* address of the first byte of data */
extern idata Uint32 fat_dir_current_sect; /* sector of selected entry in dir list */
extern xdata Uint32 fat_dir_current_offs; /* entry offset from fat_dir_current_sect */
extern pdata Byte gl_buffer[];
extern char pdata *lfn_name; /* long filename limited to MAX_FILENAME_LEN chars */
extern xdata Byte fat_buf_sector[]; /* 512 bytes buffer */
extern bdata bit fat_no_entries_free;
extern xdata Uint16 fat_total_clusters;
extern xdata Uint32 last_free_cluster;
/* Mode repeat A/B variables */
/* cluster chain for the current directory */
extern idata Uint16 fat_dclust_byte_count;/* byte counter in directory sector */
extern xdata Byte fat_last_dclust_index;/* index of the last cluster in directory chain */
extern xdata Uint16 fat_dir_list_index; /* index of current entry in dir list */
extern xdata Uint16 fat_dir_list_last; /* index of last entry in dir list */
extern xdata Uint32 fat_dir_start_sect; /* start sector of dir list */
extern idata Uint16 fat_fchain_nb_clust; /* the offset of the cluster from the first cluster
of the file fragment */
/*C**************************************************************************
* NAME: fat32.c
*----------------------------------------------------------------------------
extern bdata bit flag_end_disk_file;
extern xdata Uint32 fat_count_of_clusters;/* number of cluster - 2 */
extern xdata Union32 fat_file_size;
* Supports only 512 bytes sector size
* Supports only file fragmentation < MAX_FILE_FRAGMENT_NUMBER
* Supports only one file openned at a time
*
* Global Variables:
/* file management */
extern xdata fat_st_clust_chain fclusters[MAX_FILE_FRAGMENT_NUMBER];
/* cluster chain for the current file */
*----------------------------------------------------------------------------
* PURPOSE:
* FAT32 file-system basics functions
*
* NOTES:
* Supports only the first partition
extern idata Uint16 fat_dchain_index; /* the number of the fragment of the dir, in fact
the index of the table in the cluster chain */
extern xdata fat_st_cache fat_cache; /* The cache structure, see the .h for more info */
extern xdata char ext[3]; /* file extension (limited to 3 characters) */
extern idata Byte fat_fchain_index; /* the number of the fragment of the file, in fact
the index of the table in the cluster chain */
extern idata Byte fat_dchain_nb_clust; /* the offset of the cluster from the first cluster
of the dir fragment */
extern idata Byte fat_last_clust_index; /* index of the last cluster in file chain */
extern data Uint1来自 fat_fclust_byte_count;/* byte counter in file cluster */
#include "file.h" /* file function definition */
#include "fat32.h" /* fat32 file-system definition */
extern xdata Uint32 fat_current_file_size;
extern xdata Uint32 fat_rootclus_fat32; /* root cluster address */
extern bdata bit fat_last_dir_cluster_full;
extern xdata Uint32 fat_fat_size; /* FAT size in sector count */
/* directory management */
extern xdata fat_st_clust_chain dclusters[MAX_DIR_FRAGMENT_NUMBER];
extern data Byte fat_cluster_size; /* cluster size (sector count) */
extern idata Byte fat_cluster_mask; /* mask for end of cluster test */
/*_____ M A C R O S ________________________________________________________*/
/*_____ D E F I N I T I O N ________________________________________________*/
extern xdata Byte fat_fchain_index_save;
extern xdata Byte fat_fchain_nb_clust_save;
* - gl_buffer: array of bytes in pdata space
*****************************************************************************/
/*_____ I N C L U D E S ____________________________________________________*/
* Copyright (c) 2003 Atmel.