FATFS 库学习笔记(一)

1 基础概念:

1.1 关于字符集: 

OEM: 在ASCII标准之前,因为一个字节有8个比特,而现在只用了7个,于是很多人就想到"对呀,我们可以使用128-255的码字来表示其他东西"。麻烦来了,这么多人同时出现了这样的想法,而且将之付诸实践。于是IBM-PC上多了一个叫OEM字符集的东西

code pages: 在ASCII标准中,对于低128个码字大家都无异议,差不多就是ASCII了,但对于高128个码字, 根据你所在地的不同,会有不同的处理方式。我们称这样相异的编码系统为码页(code pages)。简体中文使用的是CP936。

Unicode: Unicode是一个编码方案,Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。Unicode 编码共有三种具体实现,分别为utf-8,utf-16,utf-32,其中utf-8占用一到四个字节,utf-16占用二或四个字节,utf-32占用四个字节。Unicode 码在全球范围的信息交换领域均有广泛的应用

1.2 FAT文件系统:

扇区: 一般512字节

簇: 由多个扇区构成(具体参考相关规范)

 

2 代码结构

ffconf.h   FatFs模块的配置文件
ff.h          FatFs的头文件,定义了几个关键的数据结构,并声明了很多函数
ff.c          FatFs模块的实现,包括f_open()、f_read()、f_write()和f_close()等函数的实现
diskio.h   底层磁盘I/O模块的头文件
diskio.c   这个文件实现了一个操作底层存储设备的接口层,ff.c会调用这个文件中提供的接口,实现文件的读写,我们在移植过程中的重点工作就是实现这个文件中的几个接口
integer.h 数据类型的定义
option     可选择的一些外部函数,既然是可选择的,也就不用太关心这部分代码

3 配置

FATS 的配置是由ffconfig.h文件,比较常用的如下:

#define _FFCONF 68020        /* Revision ID */            版本ID

#define _FS_READONLY    0                                    // 是否只支持只读, 0 : read/write, 1 read-only, 如果配置只读,

                                                                                  // 和写相关的API,如f_write, f_sysnc(), f_unlink()..  等都将被移除

#define _USE_LFN 1                                                  //对长文件名支持了

#define _MAX_LFN    255                                          //最大的长文件名

#define _FS_RPATH   2                                             //是否支持相对路径,0不支持, 

                                                                                   //   1: Enable relative path. f_chdir() and f_chdrive() are available.

                                                                                   //   2: f_getcwd() function is available in addition to 1.       

#define _FS_REENTRANT   1                                 // 是否支持文件系统可重入  ,如果支持,还需要配置

#define _CODE_PAGE                                           // Code pages  配置

#define _MULTI_PARTITION    0                            //多分区的支持

#define _MIN_SS     512                                        //扇区大小配置,一般都是512

#define _MAX_SS     512                                       /扇区大小配置,一般都是512

4 数据结构

FATS 的常用的数据结构定义在ff.h文件中,列出常用的如下:

#define LD2PD(vol) (BYTE)(vol)    /* 获得磁盘对应的物理磁盘

#define LD2PT(vol) 0                    /*获得磁盘对应的分区

FATFS结构体:描述文件系统对象的结构

/* File system object structure (FATFS) */

typedef struct {
	BYTE	fs_type;		/* File system type (0:N/A) */  FS_FAT12,FS_FAT16 FS_FAT32..
	BYTE	drv;			/* Physical drive number */   /*对应实际驱动号01--- */
	BYTE	n_fats;			/* Number of FATs (1 or 2) */   /* 文件分配表的数目 */
	BYTE	wflag;			/* win[] flag (b0:dirty) */
	BYTE	fsi_flag;		/* FSINFO flags (b7:disabled, b0:dirty) */
	WORD	id;				/* File system mount ID */
	WORD	n_rootdir;		/* Number of root directory entries (FAT12/16) */ 
                             /* 根目录区目录项的数目 */
	WORD	csize;			/* Cluster size [sectors] */   /* 每个簇的扇区数目 */
#if _MAX_SS != _MIN_SS
	WORD	ssize;			/* Sector size (512, 1024, 2048 or 4096) */
#endif
#if _USE_LFN != 0
	WCHAR*	lfnbuf;			/* LFN working buffer */
#endif
#if _FS_EXFAT
	BYTE*	dirbuf;			/* Directory entry block scratchpad buffer */
#endif
#if _FS_REENTRANT
	_SYNC_t	sobj;			/* Identifier of sync object */
#endif
#if !_FS_READONLY
	DWORD	last_clst;		/* Last allocated cluster */
	DWORD	free_clst;		/* Number of free clusters */

#if _FS_FAST_CHECK_NO_FREE_CLUSTER
	DWORD	no_free_clst;		/* no free clusters flag */
#endif

#endif
#if _FS_RPATH != 0
	DWORD	cdir;			/* Current directory start cluster (0:root) */
#if _FS_EXFAT
	DWORD	cdc_scl;		/* Containing directory start cluster (invalid when cdir is 0) */
	DWORD	cdc_size;		/* b31-b8:Size of containing directory, b7-b0: Chain status */
	DWORD	cdc_ofs;		/* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
	DWORD	n_fatent;		/* Number of FAT entries (number of clusters + 2) */
	DWORD	fsize;			/* Size of an FAT [sectors] */
	DWORD	volbase;		/* Volume base sector */
	DWORD	fatbase;		/* FAT base sector */        /*文件分配表开始扇区
	DWORD	dirbase;		/* Root directory base sector/cluster */   
                            /*  如果是FAT32,根目录开始扇区需要首先得到。
	DWORD	database;		/* Data base sector */
                            /* 数据区开始扇区
	DWORD	winsect;		/* Current sector appearing in the win[] */
	BYTE	win[_MAX_SS];	/* Disk access window for Directory, FAT (and file data at tiny cfg) */
                             //这是一个win[512]数组,存储着一个扇区,好像作为扇区缓冲使用。
} FATFS;

DIR结构体,描述目录对象结构


typedef struct {
	_FDID	obj;			/* Object identifier */ 
	DWORD	dptr;			/* Current read/write offset */
	DWORD	clust;			/* Current cluster */
	DWORD	sect;			/* Current sector */
	BYTE*	dir;			/* Pointer to the directory item in the win[] */
	BYTE	fn[12];			/* SFN (in/out) {body[8],ext[3],status[1]} */
#if _USE_LFN != 0
	DWORD	blk_ofs;		/* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if _USE_FIND
	const TCHAR* pat;		/* Pointer to the name matching pattern */
#endif
} DIR;

FIL结构体,描述文件对象的结构

/* File object structure (FIL) */

typedef struct {
	_FDID	obj;			/* Object identifier (must be the 1st member to detect invalid object pointer) */
	BYTE	flag;			/* File status flags */
	BYTE	err;			/* Abort flag (error code) */
	FSIZE_t	fptr;			/* File read/write pointer (Zeroed on file open) */
	DWORD	clust;			/* Current cluster of fpter (invalid when fprt is 0) */
	DWORD	sect;			/* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
	DWORD	dir_sect;		/* Sector number containing the directory entry */
	BYTE*	dir_ptr;		/* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
	DWORD*	cltbl;			/* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !_FS_TINY
	BYTE	buf[_MAX_SS];	/* File private data read/write window */ /文件读写缓冲
#endif
} FIL;

5 编程接口

/* FatFs module application interface                           */

FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode);				/* Open or create a file */
FRESULT f_close (FIL* fp);											/* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br);			/* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw);	/* Write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs);								/* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp);										/* Truncate the file */
FRESULT f_sync (FIL* fp);											/* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path);						/* Open a directory */
FRESULT f_closedir (DIR* dp);										/* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno);							/* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern);	/* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno);							/* Find next file */
FRESULT f_mkdir (const TCHAR* path);								/* Create a sub directory */
FRESULT f_unlink (const TCHAR* path);								/* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new);	/* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno);					/* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask);			/* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno);			/* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path);								/* Change current directory */
FRESULT f_chdrive (const TCHAR* path);								/* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len);							/* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs);	/* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn);	/* Get volume label */
FRESULT f_setlabel (const TCHAR* label);							/* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf);	/* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt);					/* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt);			/* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len);	/* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work);			/* Divide a physical drive into some partitions */
FRESULT f_map (FIL* fp,void** addr);								/* map file addr */
int f_putc (TCHAR c, FIL* fp);										/* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp);								/* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...);						/* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp);						/* Get a string from the file */
FRESULT f_disk_detect(const TCHAR* path, BYTE *state);			/* disk detect */

6 核心代码实现(ff.c)

sync_window      同步窗口,讲fs->win[512] cache窗口中的数据与磁盘数据同步,即将win buffer中数据回写到扇区中去

move_window     切换窗口,改变文件系统的当前工作扇区,如果想要操作的扇区就是当前扇区,什么事不做;

                             如果不是,则将原扇区写回;如果是FAT表,还得写入备份区。

sync_fs                同步文件系统与设备, 从代码上看,主要是针对FAT32 的FSI

get_fat                    

 

 

 

 

7 移植相关:

关键文件: 源码中最关键的两个文件是ff.cdiskio.c

关键函数:

 

DSTATUS disk_initialize (BYTE pdrv);                                    //

DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);

DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);

// disk_status()和disk_ioctl()在仅要求文件系统有读写文件的功能时可以不用实现,在移植时返回0即可。

DSTATUS disk_status (BYTE pdrv);

DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
 

 

3 参考资料

http://www.voidcn.com/article/p-hxmdtdah-uk.html

https://blog.csdn.net/x805433354/article/details/41448057

你可能感兴趣的:(fat)