FAT 文件系统 创建


前言

FAT 文件系统 在嵌入式系统中常用.

这里提供使用FAT文件系统的说明.


一、嵌入式系统中使用FAT

本次详解的环境:

  • 物理磁盘是NORFLASH,容量大小是5M,扇区大小是4K
  • 使用的FAT是:FAT12

二、使用步骤

1.f_mkfs 来创建文件系统

调用方式:

	//先把物理逻辑磁盘号码,设定好.比如:1就是NORFLASH
    const TCHAR driverNumberBuffer[3U] = {1 + '0', ':', '/'};
    BYTE work[4*1024];	
  	//通过	f_mkfs在NOR上创建文件系统.
  	
	/*
	FRESULT f_mkfs (
	const TCHAR* path,	// 磁盘号 
	BYTE opt,			// 格式化的类型:FAT12 
	DWORD au,			// 格式化时,要设置的簇大小,以字节为单位 
	void* work,			// 用户提供的buffer 
	UINT len			// 用户提供的buffer的大小,以字节为单位 
	)

	#define FM_FAT		0x01
	#define FM_FAT32	0x02
	#define FM_EXFAT	0x04
	#define FM_ANY		0x07
	#define FM_SFD		0x08
	*/

	f_mkfs(driverNumberBuffer, FM_ANY, 0, work, sizeof(work));

代码详解

FRESULT f_mkfs (
	const TCHAR* path,	/* 磁盘号 Logical drive number */
	BYTE opt,			/* 格式化的类型 Format option */
	DWORD au,			/* 格式化时,要设置的簇大小,以字节为单位 Size of allocation unit (cluster) [byte] */
	void* work,			/* 用户提供的buffer Pointer to working buffer (null: use heap memory) */
	UINT len			/* 用户提供的buffer的大小,以字节为单位  Size of working buffer [byte] */
)
{
	//FAT区域大小
	const UINT n_fats = 1;		/* Number of FATs for FAT/FAT32 volume (1 or 2) */
	//默认目录个数
	const UINT n_rootdir = 512;	/* Number of root directory entries for FAT volume */
	//簇的大小.单位是4K.
	static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0};	/* Cluster size boundary for FAT volume (4Ks unit) */
	static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0};	/* Cluster size boundary for FAT32 volume (128Ks unit) */
	BYTE fmt, sys, *buf, *pte, pdrv, part;
	//扇区大小
	WORD ss;	/* Sector size */
	DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n;
	DWORD b_vol, b_fat, b_data;				/* Base LBA for volume, fat, data */
	DWORD sz_vol, sz_rsv, sz_fat, sz_dir;	/* Size for volume, fat, dir, data */
	UINT i;
	int vol;
	DSTATUS stat;
#if FF_USE_TRIM || FF_FS_EXFAT
	DWORD tbl[3];
#endif


	/* Check mounted drive and clear work area */
	//获取磁盘逻辑号码:1
	vol = get_ldnumber(&path);					/* Get target logical drive */
	if (vol < 0) return FR_INVALID_DRIVE;
	if (FatFs[vol]) FatFs[vol]->fs_type = 0;	/* Clear the volume if mounted */
	//计算磁盘号:pdrv=1
	pdrv = LD2PD(vol);	/* Physical drive */
	//part = 0
	part = LD2PT(vol);	/* Partition (0:create as new, 1-4:get from partition table) */

	/* Check physical drive status */
	//初始化:NOR磁盘
	stat = disk_initialize(pdrv);
	if (stat & STA_NOINIT) return FR_NOT_READY;
	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
	//获取块大小:sz_blk=1
	if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1;	/* Erase block to align data area */
#if FF_MAX_SS != FF_MIN_SS		/* Get sector size of the medium if variable sector size cfg. */
	//扇区大小:SS=4096
	if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;
	if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
#else
	//扇区大小:SS=4096
	//ss = FF_MAX_SS;
	ss = get_sector_size(vol);
#endif
	if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER;	/* Check if au is valid */
	//簇大小:几个扇区组成:=0
	au /= ss;	/* Cluster size in unit of sector */

	/* Get working buffer */
#if FF_USE_LFN == 3
	if (!work) {	/* Use heap memory for working buffer */
		//for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && !(buf = ff_memalloc(szb_buf)); szb_buf /= 2) ;
		  for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && !(get_szb_buf(&buf,szb_buf)); szb_buf /= 2) ;
		sz_buf = szb_buf / ss;		/* Size of working buffer (sector) */
	} else
#endif
	{
		buf = (BYTE*)work;		/* Working buffer */
		//工作buf是几个扇区组成  =1
		sz_buf = len / ss;		/* Size of working buffer (sector) */
		//工作buf是几个byte组成=4096
		szb_buf = sz_buf * ss;	/* Size of working buffer (byte) */
	}
	if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE;

	/* Determine where the volume to be located (b_vol, sz_vol) */
	if (FF_MULTI_PARTITION && part != 0) {
		/* Get partition information from partition table in the MBR */
		if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Load MBR */
		if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Check if MBR is valid */
		pte = buf + (MBR_Table + (part - 1) * SZ_PTE);
		if (pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED);	/* No partition? */
		b_vol = ld_dword(pte + PTE_StLba);		/* Get volume start sector */
		sz_vol = ld_dword(pte + PTE_SizLba);	/* Get volume size */
	} else {
		/* Create a single-partition in this function */
		//扇区个数:sz_vol:0x500= 256 *(5)
		if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
		//开始使用扇区位置b_vol:63=3F
		b_vol = (opt & FM_SFD) ? 0 : 63;		/* Volume start sector */
		if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);
		//剩余可以使用的容量(扇区个数):0x500-0x3F=0x4c1
		sz_vol -= b_vol;						/* Volume size */
	}
	if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Check if volume size is >=128s */

	/* Pre-determine the FAT type */
	//判断FAT 类型.默认判断是FAT16
	do {
		if (FF_FS_EXFAT && (opt & FM_EXFAT)) {	/* exFAT possible? */
			if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) {	/* exFAT only, vol >= 64Ms or au > 128s ? */
				fmt = FS_EXFAT; break;
			}
		}
		if (au > 128) LEAVE_MKFS(FR_INVALID_PARAMETER);	/* Too large au for FAT/FAT32 */
		if (opt & FM_FAT32) {	/* FAT32 possible? */
			if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) {	/* FAT32 only or no-FAT? */
				fmt = FS_FAT32; break;
			}
		}
		if (!(opt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER);	/* no-FAT? */
		fmt = FS_FAT16;
	} while (0);

	{	/* Create an FAT/FAT32 volume */
		do {
			//pau = au = 1
			pau = au;
			/* Pre-determine number of clusters and FAT sub-type */
			//判断出簇 大小
			if (fmt == FS_FAT32) {	/* FAT32 volume */
				if (pau == 0) {	/* au auto-selection */
					n = sz_vol / 0x20000;	/* Volume size in unit of 128KS */
					for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ;	/* Get from table */
				}
				n_clst = sz_vol / pau;	/* Number of clusters */
				sz_fat = (n_clst * 4 + 8 + ss - 1) / ss;	/* FAT size [sector] */
				sz_rsv = 32;	/* Number of reserved sectors */
				sz_dir = 0;		/* No static directory */
				if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED);
			} else {				/* FAT volume */
				//pau是0的时候,自动计算出pau值.结果是pau =1
				if (pau == 0) {	/* au auto-selection */
					n = sz_vol / 0x1000;	/* Volume size in unit of 4KS */
					for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ;	/* Get from table */
				}
				//簇个数=扇区大小/个数  = n_clst = 4c1
				n_clst = sz_vol / pau;
				//计算出需要几个簇来存储FAT信息 
				if (n_clst > MAX_FAT12) {
					n = n_clst * 2 + 4;		/* FAT size [byte] */
				} else {
					//FAT12;需要1.5个byte来基础磁盘使用情况
					fmt = FS_FAT12;
					//n=1 一个簇就可以表示完剩余的磁盘容量情况 n=0x725
					n = (n_clst * 3 + 1) / 2 + 3;	/* FAT size [byte] */
				}
				//fat需要几个扇区 sz_fat =1
				sz_fat = (n + ss - 1) / ss;		/* FAT size [sector] */
				//fat 个数
				sz_rsv = 1;						/* Number of reserved sectors */
				//文件数量(目录个数默认值0x200个)需要的扇区个数:sz_dir = 4个
				sz_dir = (DWORD)n_rootdir * SZDIRE / ss;	/* Rootdir size [sector] */
			}
			//b_fat:fat扇区位置b_vol:3f sz_rsv:1 =b_fat = 0x40
			b_fat = b_vol + sz_rsv;						/* FAT base */
			//保存数据扇区位置:b_data = 0x40 +1 +4 =0x45
			b_data = b_fat + sz_fat * n_fats + sz_dir;	/* Data base */

			/* Align data base to erase block boundary (for flash memory media) */
			//扇区/簇 对齐 . 由于擦除是按块来的,所以在此进行调整:需要让保留区、fat表的要占完整的一个块 
			n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data;	/* Next nearest erase block from current data base */
			if (fmt == FS_FAT32) {		/* FAT32: Move FAT base */
				sz_rsv += n; b_fat += n;
			} else {					/* FAT: Expand FAT size */
				sz_fat += n / n_fats;  /* 单位为扇区 */
			}

			/* Determine number of clusters and final check of validity of the FAT sub-type */
			if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume */
			//n_clst = 0x4bb =(0x4c1 - 1 - 1*1 -4) / 1 
			n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau;
			if (fmt == FS_FAT32) {
				if (n_clst <= MAX_FAT16) {	/* Too few clusters for FAT32 */
					if (au == 0 && (au = pau / 2) != 0) continue;	/* Adjust cluster size and retry */
					LEAVE_MKFS(FR_MKFS_ABORTED);
				}
			}
			if (fmt == FS_FAT16) {
				if (n_clst > MAX_FAT16) {	/* Too many clusters for FAT16 */
					if (au == 0 && (pau * 2) <= 64) {
						au = pau * 2; continue;		/* Adjust cluster size and retry */
					}
					if ((opt & FM_FAT32)) {
						fmt = FS_FAT32; continue;	/* Switch type to FAT32 and retry */
					}
					if (au == 0 && (au = pau * 2) <= 128) continue;	/* Adjust cluster size and retry */
					LEAVE_MKFS(FR_MKFS_ABORTED);
				}
				if  (n_clst <= MAX_FAT12) {	/* Too few clusters for FAT16 */
					if (au == 0 && (au = pau * 2) <= 128) continue;	/* Adjust cluster size and retry */
					LEAVE_MKFS(FR_MKFS_ABORTED);
				}
			}
			if (fmt == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too many clusters for FAT12 */

			/* Ok, it is the valid cluster configuration */
			break;
		} while (1);


		/* Create FAT VBR .创建分区的DBR.保存在0x3f扇区中*/
		mem_set(buf, 0, ss);
		mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */
		st_word(buf + BPB_BytsPerSec, ss);				/* Sector size [byte] */
		buf[BPB_SecPerClus] = (BYTE)pau;				/* Cluster size [sector] */
		st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv);	/* Size of reserved area */
		buf[BPB_NumFATs] = (BYTE)n_fats;				/* Number of FATs */
		st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir));	/* Number of root directory entries */
		if (sz_vol < 0x10000) {
			st_word(buf + BPB_TotSec16, (WORD)sz_vol);	/* Volume size in 16-bit LBA */
		} else {
			st_dword(buf + BPB_TotSec32, sz_vol);		/* Volume size in 32-bit LBA */
		}
		buf[BPB_Media] = 0xF8;							/* Media descriptor byte */
		st_word(buf + BPB_SecPerTrk, 63);				/* Number of sectors per track (for int13) */
		st_word(buf + BPB_NumHeads, 255);				/* Number of heads (for int13) */
		st_dword(buf + BPB_HiddSec, b_vol);				/* Volume offset in the physical drive [sector] */
		if (fmt == FS_FAT32) {
			st_dword(buf + BS_VolID32, GET_FATTIME());	/* VSN */
			st_dword(buf + BPB_FATSz32, sz_fat);		/* FAT size [sector] */
			st_dword(buf + BPB_RootClus32, 2);			/* Root directory cluster # (2) */
			st_word(buf + BPB_FSInfo32, 1);				/* Offset of FSINFO sector (VBR + 1) */
			st_word(buf + BPB_BkBootSec32, 6);			/* Offset of backup VBR (VBR + 6) */
			buf[BS_DrvNum32] = 0x80;					/* Drive number (for int13) */
			buf[BS_BootSig32] = 0x29;					/* Extended boot signature */
			mem_cpy(buf + BS_VolLab32, "NO NAME    " "FAT32   ", 19);	/* Volume label, FAT signature */
		} else {
			st_dword(buf + BS_VolID, GET_FATTIME());	/* VSN */
			st_word(buf + BPB_FATSz16, (WORD)sz_fat);	/* FAT size [sector] */
			buf[BS_DrvNum] = 0x80;						/* Drive number (for int13) */
			buf[BS_BootSig] = 0x29;						/* Extended boot signature */
			mem_cpy(buf + BS_VolLab, "NO NAME    " "FAT     ", 19);	/* Volume label, FAT signature */
		}
		st_word(buf + BS_55AA, 0xAA55);					/* Signature (offset is fixed here regardless of sector size) */
		if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it to the VBR sector */

		/* Create FSINFO record if needed */
		if (fmt == FS_FAT32) {
			disk_write(pdrv, buf, b_vol + 6, 1);		/* Write backup VBR (VBR + 6) */
			mem_set(buf, 0, ss);
			st_dword(buf + FSI_LeadSig, 0x41615252);
			st_dword(buf + FSI_StrucSig, 0x61417272);
			st_dword(buf + FSI_Free_Count, n_clst - 1);	/* Number of free clusters */
			st_dword(buf + FSI_Nxt_Free, 2);			/* Last allocated cluster# */
			st_word(buf + BS_55AA, 0xAA55);
			disk_write(pdrv, buf, b_vol + 7, 1);		/* Write backup FSINFO (VBR + 7) */
			disk_write(pdrv, buf, b_vol + 1, 1);		/* Write original FSINFO (VBR + 1) */
		}

		/* Initialize FAT area */
		//保存FAT信息(磁盘使用信息)初始化fat表
		mem_set(buf, 0, (UINT)szb_buf);
		sect = b_fat;		/* FAT start sector */
		//n_fats=1 初始化FAT扇区.  如果是需要备份的话需要循环的
		for (i = 0; i < n_fats; i++) {			/* Initialize FATs each */
			if (fmt == FS_FAT32) {
				st_dword(buf + 0, 0xFFFFFFF8);	/* Entry 0 */
				st_dword(buf + 4, 0xFFFFFFFF);	/* Entry 1 */
				st_dword(buf + 8, 0x0FFFFFFF);	/* Entry 2 (root directory) */
			} else {
				st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8);	/* 目录项0 .Entry 0 and 1 */
			}
			//sz_fat=1=FAT表的大小
			nsect = sz_fat;		/* Number of FAT sectors */
			do {	/* Fill FAT sectors */
				//FAT扇区的个数(大小)
				n = (nsect > sz_buf) ? sz_buf : nsect;
				//对FAT 0x40 进行初始化
				if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
				mem_set(buf, 0, ss);
				//获取下一个FAT的扇区位置 
				sect += n; nsect -= n;
			} while (nsect);
		}

		/* Initialize root directory (fill with zero) */
		//初始化 目录扇区 nsect = 4
		nsect = (fmt == FS_FAT32) ? pau : sz_dir;	/* Number of root directory sectors */
		do {
			n = (nsect > sz_buf) ? sz_buf : nsect;
			if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
			sect += n; nsect -= n;
		} while (nsect);
	}

	/* Determine system ID in the partition table */	
	/* 5.在分区的第0号扇区写入MBR */
	if (FF_FS_EXFAT && fmt == FS_EXFAT) {
		sys = 0x07;			/* HPFS/NTFS/exFAT */
	} else {
		if (fmt == FS_FAT32) {
			sys = 0x0C;		/* FAT32X */
		} else {
			if (sz_vol >= 0x10000) {
				sys = 0x06;	/* FAT12/16 (large) */
			} else {
				sys = (fmt == FS_FAT16) ? 0x04 : 0x01;	/* FAT16 : FAT12 */
			}
		}
	}

	/* Update partition information */
	if (FF_MULTI_PARTITION && part != 0) {	/* Created in the existing partition */
		/* Update system ID in the partition table */
		if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Read the MBR */
		buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys;		/* Set system ID */
		if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it back to the MBR */
	} else {								/* Created as a new single partition */
		if (!(opt & FM_SFD)) {	/* Create partition table if in FDISK format */
			mem_set(buf, 0, ss);
			st_word(buf + BS_55AA, 0xAA55);		/* MBR signature */
			pte = buf + MBR_Table;				/* Create partition table for single partition in the drive */
			pte[PTE_Boot] = 0;					/* Boot indicator */
			pte[PTE_StHead] = 1;				/* Start head */
			pte[PTE_StSec] = 1;					/* Start sector */
			pte[PTE_StCyl] = 0;					/* Start cylinder */
			pte[PTE_System] = sys;				/* System type */
			n = (b_vol + sz_vol) / (63 * 255);	/* (End CHS may be invalid) */
			pte[PTE_EdHead] = 254;				/* End head */
			pte[PTE_EdSec] = (BYTE)(((n >> 2) & 0xC0) | 63);	/* End sector */
			pte[PTE_EdCyl] = (BYTE)n;			/* End cylinder */
			st_dword(pte + PTE_StLba, b_vol);	/* Start offset in LBA */
			st_dword(pte + PTE_SizLba, sz_vol);	/* Size in sectors */
			if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it to the MBR */
		}
	}

	if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);

	LEAVE_MKFS(FR_OK);
}

2.f_mount 挂在文件系统

f_mount函数就是读出MBR扇区的内容放入FATFS结构图中,供以后使用。
从f_mount函数分析中可知,find_volume()函数才是挂载的核心代码,

FRESULT f_mount (
	FATFS* fs,			/* Pointer to the filesystem object (NULL:unmount)*/
	const TCHAR* path,	/* Logical drive number to be mounted/unmounted */
	BYTE opt			/* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */
)
{
	FATFS *cfs;
	int vol;
	FRESULT res;
	const TCHAR *rp = path;


	/* Get logical drive number */
	//vol = 1
	vol = get_ldnumber(&rp);
	if (vol < 0) return FR_INVALID_DRIVE;
	//cfs = 00
	cfs = FatFs[vol];					/* Pointer to fs object */

	if (cfs) {

		cfs->fs_type = 0;				/* Clear old fs object */
	}

	if (fs) {
		fs->fs_type = 0;				/* Clear new fs object */
	}
	//保存	FatFs[1] = fs 文件系统
    /* 把用户分配的FATFS结构图放入全局数组指针中 */
	FatFs[vol] = fs;					/* Register new fs object */

	if (opt == 0) return FR_OK;			/* Do not mount now, it will be mounted later */

    /* 这个函数才是挂载时的关键所在 */
	res = find_volume(&path, &fs, 0);	/* Force mounted the volume */
	LEAVE_FF(fs, res);
}

find_volume:
1)读取第一个扇区的信息(就是MBR) ,进行验证是否正常
2)读取第0x3F扇区的信息 ,反映到FAT结构体信息中去.

static
FRESULT find_volume (	/* FR_OK(0): successful, !=0: any error occurred */
	const TCHAR** path,	/* Pointer to pointer to the path name (drive number) */
	FATFS** rfs,		/* Pointer to pointer to the found filesystem object */
	BYTE mode			/* !=0: Check write protection for write access */
)
{
	BYTE fmt, *pt;
	int vol;
	DSTATUS stat;
	DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4];
	WORD nrsv;
	FATFS *fs;
	UINT i;


	/* Get logical drive number */
	*rfs = 0;
	vol = get_ldnumber(path);
	if (vol < 0) return FR_INVALID_DRIVE;

	/* Check if the filesystem object is valid or not */
	/* 1.找到用户分配的FATFS结构体 */
	fs = FatFs[vol];					/* Get pointer to the filesystem object */
	if (!fs) return FR_NOT_ENABLED;		/* Is the filesystem object available? */

	*rfs = fs;							/* Return pointer to the filesystem object */

	mode &= (BYTE)~FA_READ;				/* Desired access mode, write access or not */
	
    /* 判定磁盘当前状态,如果磁盘被初始化过,那么就判定是挂载过了,直接返回OK */
	if (fs->fs_type != 0) {				/* If the volume has been mounted */
		stat = disk_status(fs->pdrv);
		if (!(stat & STA_NOINIT)) {		/* and the physical drive is kept initialized */
			if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) {	/* Check write protection if needed */
				return FR_WRITE_PROTECTED;
			}
			return FR_OK;				/* The filesystem object is valid */
		}
	}

	/* The filesystem object is not valid. */
	/* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */


    /* 2.进行FATFS结构体填充 */
	fs->fs_type = 0;					/* Clear the filesystem object */
	fs->pdrv = LD2PD(vol);				/* Bind the logical drive and a physical drive */
	
    /* 2.1初始化磁盘 */
	stat = disk_initialize(fs->pdrv);	/* Initialize the physical drive */
	if (stat & STA_NOINIT) { 			/* Check if the initialization succeeded */
		return FR_NOT_READY;			/* Failed to initialize due to no medium or hard error */
	}
	if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
		return FR_WRITE_PROTECTED;
	}


	/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */
	bsect = 0;
	
    /* 2.2 check_fs()函数会把磁盘的第1个扇区(就是MBR)读入到fs->win[]数组中, 判断MBR是否是合法的MBR*/
	fmt = check_fs(fs, bsect);			/* Load sector 0 and check if it is an FAT-VBR as SFD */
	if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) {	/* Not an FAT-VBR or forced partition number */
		for (i = 0; i < 4; i++) {		/* Get partition offset */
			pt = fs->win + (MBR_Table + i * SZ_PTE);
			br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0;
		}
		i = LD2PT(vol);					/* Partition number: 0:auto, 1-4:forced */
		if (i != 0) i--;
		do {							/* Find an FAT volume */
			bsect = br[i];
			//check_fs(fs, 0x3f): 读取第0x3f扇区数据
			fmt = bsect ? check_fs(fs, bsect) : 3;	/* Check the partition */
		} while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4);
	}
	if (fmt == 4) return FR_DISK_ERR;		/* An error occured in the disk I/O layer */
	if (fmt >= 2) return FR_NO_FILESYSTEM;	/* No FAT volume is found */

	/* An FAT volume is found (bsect). Following code initializes the filesystem object */
	{
		//验证 第一个扇区的内容是否是正常的.
		//读取第0x3F扇区的信息 ,反映到FAT结构体中.
		if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_BytsPerSec must be equal to the physical sector size) */

		fasize = ld_word(fs->win + BPB_FATSz16);		/* Number of sectors per FAT */
		if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);
		//同时会把第一个扇区的部分信息,反映到FAT结构体中.
		fs->fsize = fasize;

		fs->n_fats = fs->win[BPB_NumFATs];				/* Number of FATs */
		if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM;	/* (Must be 1 or 2) */
		fasize *= fs->n_fats;							/* Number of sectors for FAT area */

		fs->csize = fs->win[BPB_SecPerClus];			/* Cluster size */
		if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM;	/* (Must be power of 2) */

		fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt);	/* Number of root directory entries */
		if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM;	/* (Must be sector aligned) */

		tsect = ld_word(fs->win + BPB_TotSec16);		/* Number of sectors on the volume */
		if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);

		nrsv = ld_word(fs->win + BPB_RsvdSecCnt);		/* Number of reserved sectors */
		if (nrsv == 0) return FR_NO_FILESYSTEM;			/* (Must not be 0) */

		/* Determine the FAT sub type */
		sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE);	/* RSV + FAT + DIR */
		if (tsect < sysect) return FR_NO_FILESYSTEM;	/* (Invalid volume size) */
		nclst = (tsect - sysect) / fs->csize;			/* Number of clusters */
		if (nclst == 0) return FR_NO_FILESYSTEM;		/* (Invalid volume size) */
		fmt = 0;
		if (nclst <= MAX_FAT32) fmt = FS_FAT32;
		if (nclst <= MAX_FAT16) fmt = FS_FAT16;
		if (nclst <= MAX_FAT12) fmt = FS_FAT12;
		if (fmt == 0) return FR_NO_FILESYSTEM;

		/* Boundaries and Limits */
		fs->n_fatent = nclst + 2;						/* Number of FAT entries */
		fs->volbase = bsect;							/* Volume start sector */
		fs->fatbase = bsect + nrsv; 					/* FAT start sector */
		fs->database = bsect + sysect;					/* Data start sector */
		if (fmt == FS_FAT32) {
			if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM;	/* (Must be FAT32 revision 0.0) */
			if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM;	/* (BPB_RootEntCnt must be 0) */
			fs->dirbase = ld_dword(fs->win + BPB_RootClus32);	/* Root directory start cluster */
			szbfat = fs->n_fatent * 4;					/* (Needed FAT size) */
		} else {
			if (fs->n_rootdir == 0)	return FR_NO_FILESYSTEM;	/* (BPB_RootEntCnt must not be 0) */
			fs->dirbase = fs->fatbase + fasize;			/* Root directory start sector */
			szbfat = (fmt == FS_FAT16) ?				/* (Needed FAT size) */
				fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
		}
		if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_FATSz must not be less than the size needed) */

#if !FF_FS_READONLY
		/* Get FSInfo if available */
		fs->last_clst = fs->free_clst = 0xFFFFFFFF;		/* Initialize cluster allocation information */
		fs->fsi_flag = 0x80;
#if (FF_FS_NOFSINFO & 3) != 3
		if (fmt == FS_FAT32				/* Allow to update FSInfo only if BPB_FSInfo32 == 1 */
			&& ld_word(fs->win + BPB_FSInfo32) == 1
			&& move_window(fs, bsect + 1) == FR_OK)
		{
			fs->fsi_flag = 0;
			if (ld_word(fs->win + BS_55AA) == 0xAA55	/* Load FSInfo data if available */
				&& ld_dword(fs->win + FSI_LeadSig) == 0x41615252
				&& ld_dword(fs->win + FSI_StrucSig) == 0x61417272)
			{
#if (FF_FS_NOFSINFO & 1) == 0
				fs->free_clst = ld_dword(fs->win + FSI_Free_Count);
#endif
#if (FF_FS_NOFSINFO & 2) == 0
				fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free);
#endif
			}
		}
#endif	/* (FF_FS_NOFSINFO & 3) != 3 */
#endif	/* !FF_FS_READONLY */
	}

	fs->fs_type = fmt;		/* FAT sub-type */
	fs->id = ++Fsid;		/* Volume mount ID */

#if FF_FS_RPATH != 0
	fs->cdir = 0;			/* Initialize current directory */
#endif

	return FR_OK;
}

总结

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值