前后看了大概有一个星期,现在是有一个模糊的整体概念。
参考链接:https://wenku.baidu.com/view/7f6610481711cc7931b716a4.html FATFS文件系统剖析(全)
https://blog.csdn.net/xiaoluoshan/article/details/51685632 FatFS文件系统介绍及使用例程
https://blog.csdn.net/fanwenjieok/article/details/34601901 1. FATFS 分析之——数据结构
https://wenku.baidu.com/view/a2c861661fb91a37f111f18583d049649b660ec5.html FatFs文件系统及其接口函数详解
fatfs主要看diskio.c,ff.c,ff.h,下图就比较直观了,disk磁盘,diskio.c为底层,看懂就行,用不着我们调用,ff.c为API,使用fatfs会经常调用内部函数,ff.h主要放相关的结构体。
diskio.c看源程序比较好理解。ff.c和ff.h看了很长的时间。
一.ff.h
需要理解一些基本的概念,比如卷(Volume),簇(cluster ),扇区(Sectors )
/* File system object structure (FATFS) */
1.FATFS
typedef struct {
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */每个簇有几个扇区
BYTE n_fats; /* Number of FAT copies (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) */
#if _MAX_SS != _MIN_SS
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clust; /* Last allocated cluster */
DWORD free_clust; /* Number of free clusters */
#endif
#if _FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#endif
DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */
DWORD fsize; /* Sectors per FAT */ FAT file allocation table 文件分配表
DWORD volbase; /* Volume start sector */ 卷起始扇区
DWORD fatbase; /* FAT start sector */ 文件分配表起始扇区
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ 引导目录起始扇区,如果是FAT32,根目录开始扇区需要首先得到
DWORD database; /* Data start 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) *///扇区操作缓存
} FATFS;
2.FIL
/* File object structure (FIL) */ 文件对象结构体
typedef struct {
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
WORD id; /* Owner file system mount ID (**do not change order**) */
BYTE flag; /* Status flags */
BYTE err; /* Abort flag (error code) */
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */ 文件起始簇
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
DWORD dsect; /* 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 file open) */
#endif
#if _FS_LOCK
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
3.DIR
/* Directory object structure (DIR) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */
WORD id; /* Owner file system mount ID (**do not change order**) */
WORD index; /* Current read/write index number */
DWORD sclust; /* Table start cluster (0:Root dir) */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _FS_LOCK
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
#endif
#if _USE_LFN
WCHAR* lfn; /* Pointer to the LFN working buffer */
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
#if _USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
4.FILINFO
typedef struct {
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
BYTE fattrib; /* Attribute */
TCHAR fname[13]; /* Short file name (8.3 format) */
#if _USE_LFN //ÎļþÃû¹ý³¤
TCHAR* lfname; /* Pointer to the LFN buffer */
UINT lfsize; /* Size of LFN buffer in TCHAR */
#endif
} FILINFO;
二、main()
FATFS_Init(); //为fatfs相关变量申请内存
f_mount(fs[0],"0:",1); //挂在SD卡
f_mount(fs[1],"1:",1); //挂载SD卡
/*-----------------------------------------------------------------------*/
/* Mount/Unmount a Logical Drive 安装一个逻辑驱动 */
/*-----------------------------------------------------------------------*/
FRESULT f_mount (
FATFS* fs, /* Pointer to the file system object (NULL:unmount)*/
const TCHAR* path, /* Logical drive number to be mounted/unmounted */
BYTE opt /* 0:Do not mount (delayed mount), 1:Mount immediately */
)
参数:通过path路径,安装逻辑驱动,把fs内部参数设置好,opt为选择路径
{
内部程序省略,只看重点部分
vol = get_ldnumber(&rp);通过路径找到是哪个卷,如{"0:/图片"},先找到:,再根据冒号的位置找到0,得到是哪个路径是哪个卷
res = find_volume(&fs, &path, 0); 安装卷就是通过这个函数,下面看这个函数
}
/*Find logical drive and check if the volume is mounted */
static FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
FATFS** rfs, /* Pointer to pointer to the found file system object */
const TCHAR** path, /* Pointer to pointer to the path name (drive number) */
BYTE wmode /* !=0: Check write protection for write access */
)
{
如上一样,先vol = get_ldnumber(path);得到卷号,
接下来就是对fs结构体进行赋值,省略,需要参考fatfs文件系统存储机制
}
FATFS_ScanFiles(dat, filename); 通过路径找到卷,再把卷内的文件信息存入filename
BMP_ShowPicture(picFile);filename的信息提取到picfile
{
res = f_open(&fsrc, (const TCHAR*)dir, FA_READ); 打开目录 通过目录dir把相关信息存入fsrc
res = f_read(&fsrc, buffer, sizeof(buffer), &br); //通过得到的fsrc把信息存入buffer
BMP_ReadHeader(buffer, &bmpHeader); 按照图片信息的规则把buffer转化成bmpHeader
}