⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatfs.c

📁 基于ARM7的直流电机的驱动,还有FLASH驱动,LCD驱动等
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <avt.h>
#include "Defs.h"
#include "44b0x.h"
#include "usb.h"
#include "sl811.h"

//
// 最多打开文件数
//

#define	FILE_MAX		8

//
// 文件标志
//
#define	F_EOF			0x1	// 文件结束标志
#define	F_OPEN			0x2	// 文件已打开标志
#define	F_MODIF			0x4	// 文件内容被修改标志
#define	F_SZCHG			0x8	// 文件大小被修改标志
#define F_SHARE			0x10	// 文件被共享

//
// 文件类型(FAT系统相关)
//

#define	ATTR_NORMAL	0x00
#define	ATTR_READONLY	0x01	// 只读文件
#define	ATTR_HIDDEN	0x02	// 隐藏文件
#define	ATTR_SYSTEM	0x04	// 系统文件
#define	ATTR_VOLUMENAME	0x08	// 卷标
#define	ATTR_DIRECTORY	0x10	// 目录
#define	ATTR_ARCHIVE	0x20	// 普通文件
#define ATTR_LONG_NAME	(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUMENAME)

//
// FAT特殊值
//

#define	FAT_FREE		0x0000

// 文件标志(调试用)
#define FILE_MAGIC		0xDEEDFEE1

//
// 分区表项
//

typedef __packed struct {
	UCHAR		BootIndicator;	// 是否可引导
	UCHAR		StartHead;	// 起始磁头
	UCHAR		StartSector;	// 起始扇区
	UCHAR		StartCylinder;	// 起始柱面
	UCHAR		SystemIndicator;// 文件系统类型
	UCHAR		EndHead;	// 结束磁头
	UCHAR		EndSector;	// 结束扇区
	UCHAR		EndCylinder;	// 结束柱面
	ULONG		SectorCountBeforePartition;//分区起始扇区
	ULONG		PartitionSectorCount;	// 分区扇区数
} PART_ENTRY;

//
// FAT12/16/32文件系统结构
//

typedef __packed struct {
	UCHAR		JumpBoot[3];	// Jump instruction to boot code
	UCHAR		OemName[8];	// "MSWIN4.1" for MS formatted volumes
	USHORT		BytesPerSector;	// Bytes per sector
	UCHAR		SectorsPerCluster;// Number of sectors in a cluster
	USHORT		ReservedSectors;// Reserved sectors, usually 1 (the bootsector)
	UCHAR		NumberOfFats;	// Number of FAT tables
	USHORT		RootDirEntries;	// Number of root directory entries (fat12/16)
	USHORT		TotalSectors;	// Number of total sectors on the drive, 16-bit
	UCHAR		MediaDescriptor;// Media descriptor byte
	USHORT		SectorsPerFat;	// Sectors per FAT table (fat12/16)
	USHORT		SectorsPerTrack;// Number of sectors in a track
	USHORT		NumberOfHeads;	// Number of heads on the disk
	ULONG		HiddenSectors;	// Hidden sectors (sectors before the partition start like the partition table)
	ULONG		TotalSectorsBig;// This field is the new 32-bit total count of sectors on the volume
	ULONG		SectorsPerFatBig;// This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
	USHORT		ExtendedFlags;	// Extended flags (fat32)
	USHORT		FileSystemVersion;// File system version (fat32)
	ULONG		RootDirStartCluster;// Starting cluster of the root directory (fat32)
	USHORT		FsInfo;		// Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
	USHORT		BackupBootSector;// If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6.
	UCHAR		Reserved[12];	// Reserved for future expansion
	UCHAR		DriveNumber;	// Int 0x13 drive number (e.g. 0x80)
	UCHAR		Reserved1;	// Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
	UCHAR		BootSignature;	// Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
	ULONG		VolumeSerialNumber;// Volume serial number
	UCHAR		VolumeLabel[11];// Volume label. This field matches the 11-byte volume label recorded in the root directory
	UCHAR		FileSystemType[8];// Always set to the string "FAT32   "

	UCHAR		BootCodeAndData[420];// The remainder of the boot sector
	UCHAR		BootSectorMagic[2];// 0xAA55
} BOOTSECTOR;

//
// 主引导扇区结构
//

typedef __packed struct {
	UCHAR 		Misc[0x1be];
	PART_ENTRY	List[4];	// 分区表项
	UCHAR		BootSectorMagic[2]; // 0xAA55
} MBR;

/*
 * FAT文件目录项
 */
typedef __packed struct {
	char		FileName[11];	/* 文件名 */
	UCHAR		Attr;		/* 文件属性 */
	UCHAR		ReservedNT;	/* 保留 */
	UCHAR		TimeInTenths;	/* 文件创建时间世纪 */
	USHORT		CreateTime;	/* 文件创建时间 */
	USHORT		CreateDate;	/* 文件创建日期 */
	USHORT		LastAccessDate;	/* 文件访问时间 */
	USHORT		ClusterHigh;	/* 文件第一个簇的高16位 */
	USHORT		Time;		/* 文件修改时间 */
	USHORT		Date;		/* 文件创建日期 */
	USHORT		ClusterLow;	/* 文件第一个簇的低16位 */
	ULONG		Size;		/* 文件大小 */
} DIRENTRY;

//
// 文件结构(自定义)
//

typedef struct _FILE {
	char		Name[12];// 文件名
	DRIVE		*Drive;	// 驱动器
	ULONG		Size;	// 文件大小
	int		Blks;	// 文件簇数
	int		Blk;	// 文件当前簇
	ULONG		Pos;	// 文件读写位置
	ULONG		Flags;	// 文件标志
	ULONG		Time;	// 文件时间
	CLNO		Start;	// 起始簇号
	CLNO		*Clus;	// 簇数组
	UCHAR		*Buffer;// 簇缓冲区
	ULONG		DEOffst;// 文件目录项扇区内偏移
	ULONG		DESt;	// 文件目录项扇区
	UINT		Ref;	// 文件引用计数
	UINT		sm;	// 文件访问信号量
	UINT		Magic;	// 标志
	struct _FILE	*sf;	// 共享文件
} FATFILE;

//
// 打开文件数组
//

static FATFILE	Files[FILE_MAX];

static int	FlushBuffer(FATFILE *);
static int	FillBuffer(FATFILE *f, UINT lblk, int New);

UINT mylog2(ULONG x);
ULONG mktime(USHORT year, USHORT mon, USHORT day, USHORT hour, USHORT min, USHORT sec);
//void WriteFileCallback(int fd, UINT pos);

// 簇号转换为扇区号
#define Clus2Sect(d, c) d->DataStart + ((c - 2) << d->SectorsPerClusterShift)

// 锁驱动器(调试用)
void
LockDrive(DRIVE *d) {
	
	CHECK_PTR(d);
	CHECK_PTR(d->sm);
	
	//sm_p(d->sm, FOREVER);
}

// 解锁驱动器(调试用)
void
UnlockDrive(DRIVE *d) {
	
	CHECK_PTR(d);
	CHECK_PTR(d->sm);
	
	//sm_v(d->sm);
}

// 读簇
// 
// d:  驱动器
// st: 簇起始扇区
// buf: 数据指针
//
static int
ReadCluster(DRIVE *d, ULONG st, UCHAR *buf) {
	UINT	i;
	int		rc = TRUE;

	CHECK_PTR(d);
	CHECK_PTR(buf);
	ASSERT(st < d->Sectors);
	
	LockDrive(d);
	
	//if(d->ms != NULL)
	//	DBG1("ReadCluster(%u)...\n", st);

	// 每簇扇区数:1,2,4,8,16...
	for(i = 0; i < d->SectorsPerCluster; i++) {
		if(!(*d->ReadSector)(d, st, buf)) {
			rc = FALSE;
			break;
		}
		
		st++;
		buf += d->BytesPerSector;
	}
	
	UnlockDrive(d);
	
	return rc;
}


// 写簇
// 
// d:  驱动器
// st: 簇起始扇区
// buf: 数据指针
static int
WriteCluster(DRIVE *d, ULONG st, UCHAR *buf) {
	UINT	i;
	int		rc = TRUE;

	CHECK_PTR(d);
	CHECK_PTR(buf);
	ASSERT(st < d->Sectors);
	
	LockDrive(d);
	
	//if(d->ms != NULL)
	//	DBG1("WriteCluster(%u)...\n", st);

	// 每簇扇区数:1,2,4,8,16...
	for(i = 0; i < d->SectorsPerCluster; i++) {
		if(!(*d->WriteSector)(d, st, buf)) {
			rc = FALSE;
			break;
		}
		
		st++;
		buf += d->BytesPerSector;
	}
	
	UnlockDrive(d);
	
	return rc;
}


// 获取某簇的下一簇
//
// d: 驱动器
// cl: 簇号
//
static CLNO
GetNextCluster(DRIVE *d, CLNO cl) {
	UCHAR	*b;
	ULONG	off;
	UINT	st;
	CLNO	rc = 0xFFFFFFFF;
	
	CHECK_PTR(d);
	ASSERT(cl < d->NumClusters);
	
	//if(d->ms != NULL)
	//	DBG1("GetNextCluster(%u)...\n", cl);
	
	LockDrive(d);

	// 每个FAT项大小
	// FAT32: 4字节
	// FAT16: 2字节
	//
	off = cl * (d->Fat32 ? 4 : 2);
	st = off / 512;
	if(st != d->fatst) {
		// FAT缓冲失败
		d->fatst = st;
		if(!(*d->ReadSector)(d, d->Fat1 + st, d->fatbuf))
			goto ret;
	}
	// 下一个簇的簇号
	b = d->fatbuf + (off & 511);
	if(d->Fat32)
		rc = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
	else
		rc = (b[1] << 8) | b[0];
ret:

	UnlockDrive(d);

	return rc;
}

// 设置某簇的下一簇
//
// d: 驱动器
// cl: 簇号
// val: 下一簇的簇号
//
static int
SetNextCluster(DRIVE *d, CLNO cl, CLNO val) {
	UCHAR	*b;
	ULONG	off;
	UCHAR	*fatbuf;
	int		rc;
	
	CHECK_PTR(d);
	ASSERT(cl < d->NumClusters);
	
	LockDrive(d);
	
	fatbuf = d->fatbuf;

	// 每个FAT项大小
	// FAT32: 4字节
	// FAT16: 2字节
	//
	off = cl * (d->Fat32 ? 4 : 2);
	d->fatst = off / 512;
	//if(d->ms != NULL)
	//	DBG2("SetNextCluster(%u, %u)@", (UINT)cl, (UINT)val);
	//if(d->ms != NULL)
	//	DBG3("%u, FAT1: %u, FAT2:%u\n", d->fatst, d->Fat1, d->Fat2);

	if(!(*d->ReadSector)(d, d->Fat1 + d->fatst, fatbuf)) {
		DBG("ReadSector FAILED!\n");
		rc = FALSE;
		goto ret;
	}

	// 下一个簇的簇号
	b = fatbuf + (off & 511);
	if(d->Fat32) {
		//
		// FAT32文件系统
		//
		b[0] = val;
		b[1] = val >> 8;
		b[2] = val >> 16;
		b[3] = val >> 24;
		if(!(*d->WriteSector)(d, d->Fat1 + d->fatst, fatbuf)) {
			DBG("WriteSector FAILED!\n");
			rc = FALSE;
			goto ret;
		}
		// 更新FAT2
		if(d->Fat2 != 0) {
			//DBG1("Rewrite FAT2(%u)...\n", d->Fat2 + d->fatst);
			if(!(*d->ReadSector)(d, d->Fat2 + d->fatst, fatbuf)) {
				DBG("ReadSector FAILED!\n");
				rc = FALSE;
				goto ret;
			}

			b[0] = val;
			b[1] = val >> 8;
			b[2] = val >> 16;
			b[3] = val >> 24;
			
			if(!(*d->WriteSector)(d, d->Fat2 + d->fatst, fatbuf)) {
				DBG("WriteSector FAILED!\n");
				rc = FALSE;
				goto ret;
			}
		}
	}
	else {
		//
		// FAT16文件系统
		//
		b[0] = val;
		b[1] = val >> 8;
		if(!(*d->WriteSector)(d, d->Fat1 + d->fatst, fatbuf)) {
			DBG("WriteSector FAILED!\n");
			rc = FALSE;
			goto ret;
		}

		// 更新FAT2
		if(d->Fat2 != 0) {
			//DBG1("Rewrite FAT2(%u)...\n", d->Fat2 + d->fatst);
			if(!(*d->ReadSector)(d, d->Fat2 + d->fatst, fatbuf)) {
				DBG("ReadSector FAILED!\n");
				rc = FALSE;
				goto ret;
			}
			
			b[0] = val;
			b[1] = val >> 8;

			if(!(*d->WriteSector)(d, d->Fat2 + d->fatst, fatbuf)) {
				DBG("WriteSector FAILED!\n");
				rc = FALSE;
				goto ret;
			}
		}
	}
	rc = TRUE;
ret:

	UnlockDrive(d);

	return rc;
}

//
// 分配簇
//
// drv: 驱动器
// nr:  簇数
// arr: 簇数组
//
static int
AllocCluster(DRIVE *drv, int nr, CLNO *arr) {
	CLNO	new, c, i;
	
	CHECK_PTR(drv);
	CHECK_PTR(arr);

	i = 0;
	for(c = drv->fatgoal; c < drv->NumClusters; c++) {
		new = GetNextCluster(drv, c);
		// 磁盘满
		if(new == 0xFFFFFFFF)
			return 0;
		
		// 簇空闲
		if(new == FAT_FREE) {
			
			arr[i++] = c;
			if(i == nr) {
				drv->fatgoal = c + 1;
				return 1;	// OK!
			}
		}
	}
	
	drv->fatgoal = c;
	return 0;	// DISK FULL
}


// 字符大写
static __inline char
UPPER(char c) {
	return c >= 'a' && c <= 'z' ? c ^ 0x20 : c;
}


// 文件名转换成8.3格式
//
// in:  输入参数
// out: 输出参数
//
// 例如:
// 
// foo.bar  -->  "FOO     BAR"
//
static void
Convert (const char * in, char * out) {
	int    len;
	char * str = out;

	for(len = 0; len < 8 && *in && *in != '.'; len++)
		*str++ = UPPER(*in++);
	for(; len < 8; len++)
		*str++ = ' ';

	if(*in == '.')  in++;
	for(; *in && len < 11; len++)
		*str++ = UPPER(*in++);
	for(; len < 11; len++)
		*str++ = ' ';
	*str = '\0';
}

//
// 分配一个文件结构
//
static int
allocf(void) {
	int		i;
	int		psw;
	
	psw = interrupts_disable();
	for(i = 0; i < FILE_MAX; i++)
	if(!Files[i].Drive)
		break;
	
	interrupts_enable(psw);
	return i == FILE_MAX ? -1 : i;
}

//
// 取得当前时间
//
ULONG
GetTm(void) {
	//struct tm	t;
				
	//GetTime(&t);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -