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

📄 fatfs.c

📁 基于ARM7的直流电机的驱动,还有FLASH驱动,LCD驱动等
💻 C
📖 第 1 页 / 共 3 页
字号:
		
		// 如果文件大小被修改,将文件信息回写
		if(f->Flags & F_SZCHG) {
			DRIVE		*d;
			DIRENTRY	*pe;
			UCHAR		*tmpbuf;
			ULONG		tm;
			
			LockDrive(d);
			
			d = f->Drive;
			tmpbuf = d->tmpbuf;
			pe = (DIRENTRY *)(tmpbuf + f->DEOffst);
			if((*d->ReadSector)(d, f->DESt, tmpbuf)) {
				tm = GetTm();
			
				pe->Size = f->Size;
				pe->TimeInTenths = 0x57;
				pe->CreateTime = tm & 0xFFFF;
				pe->CreateDate = tm >> 16;
				pe->LastAccessDate = 0x3475;
				pe->Date = 0x3475;
				pe->Time = 0x7c11;
				(*d->WriteSector)(d, f->DESt, tmpbuf);
			}
			
			UnlockDrive(d);
		}
		if(f->Buffer) {
			kfree(f->Buffer);
			f->Buffer = 0;
		}
		if(f->Clus) {
			kfree(f->Clus);
			f->Clus = 0;
		}
		sm_delete(f->sm);
		f->Drive->Ref--;
		f->Drive = 0;
	}
}

//
// 如果文件内容被修改,将缓冲区内容回写
//

static int
FlushBuffer(FATFILE *f) {
	DRIVE	*drv;
	FATFILE	*raw;
	ULONG	offst;
	
	CHECK_PTR(f);
	CHECK_PTR(f->Drive);

	drv = f->Drive;
	if(!(drv->Flags & DRIVE_MOUNT))
		return -1;
	
	//DBG("FlushBuffer...\n");
	
	raw = (f->Flags & F_SHARE) ? f->sf : f;
	ASSERT(raw != NULL);

	f->Flags &= ~F_MODIF;
	if(f->Blk == raw->Blk)
		raw->Flags &= ~F_MODIF;
	
	offst = Clus2Sect(drv, raw->Clus[f->Blk]);
	if(!WriteCluster(drv, offst, f->Buffer))
		return -1;
	
	//LockDrive(drv);
	(*drv->Sync2)(drv, offst);
	//UnlockDrive(drv);
	
//	WriteFileCallback((int)(f - Files), f->Pos);
	
	return 0;
}

//
// 扩充文件大小
//

static int
ExtendFile(FATFILE *f) {
	CLNO	cl;
	CLNO	*ca;
	DRIVE	*drv;
	FATFILE *raw;
	
	CHECK_PTR(f);
	CHECK_PTR(f->Drive);
	
	drv = f->Drive;
	if(!(drv->Flags & DRIVE_MOUNT))
		return FALSE;
		
	//DBG("ExtendFile...\n");

	raw = (f->Flags & F_SHARE) ? f->sf : f;
	ASSERT(raw != NULL);

	//DBG("Allocate Cluster... ");
	
	// 申请一个簇
	if(!AllocCluster(drv, 1, &cl)) {
		DBG("DISK FULL!\n");
		return FALSE;
	}
	
	//DBG1("%u\n", cl);

	ca = (CLNO *)kmalloc((raw->Blks + 1) * sizeof(CLNO));

	Memcpy(ca, raw->Clus, raw->Blks * sizeof(CLNO));
	kfree(raw->Clus);

	// 连接簇
	ca[raw->Blks++] = cl;
	raw->Clus = ca;
	SetNextCluster(drv, ca[raw->Blks - 2], ca[raw->Blks - 1]);
	SetNextCluster(drv, ca[raw->Blks - 1], drv->FatEnd + 1);	// FAT_EOF
	
	f->Flags &= ~F_EOF;
	raw->Flags &= ~F_EOF;
	return TRUE;
}

//
// 将文件当前簇的内容导入缓冲区
//

static int
FillBuffer(FATFILE *f, UINT lblk, int New) {
	UINT	csz;
	DRIVE * drv;
	UCHAR *	buf;
	//UCHAR * acc;
	FATFILE	*raw;
	
	CHECK_PTR(f);
	raw = (f->Flags & F_SHARE) ? f->sf : f;
	ASSERT(raw != NULL);

	if(f->Blk >= raw->Blks)
		DbgOut("f->Blk = %u, raw->Blks = %u\n", f->Blk, raw->Blks);
	ASSERT(f->Blk < raw->Blks);

	if(lblk > raw->Blks)
		DbgOut("lblk = %u, f->Blks = %u\n", lblk, raw->Blks);
	ASSERT(lblk <= raw->Blks);

	if(lblk == f->Blk)
		return TRUE;

	if(lblk >= raw->Blks) {
		f->Flags |= F_EOF;
		return FALSE;
	}

	drv = f->Drive;
	if(!(drv->Flags & DRIVE_MOUNT))
		return FALSE;
	
	csz = drv->ClusterSize;
	buf = f->Buffer;

	// 申请缓冲区空间
	if(!buf) {
		f->Buffer = buf = (UCHAR *)kmalloc(csz);
	}
	
	// 当前缓冲区内容被修改,回写它
	if(f->Flags & F_MODIF)
		FlushBuffer(f);
	
	// 如果是新建的文件,清空缓冲区
	if(New) {
		Memset(f->Buffer, 0, csz);
	}
	else {
		if(!ReadCluster(drv, Clus2Sect(drv, raw->Clus[lblk]), f->Buffer))
			return FALSE;
	}
	f->Blk = lblk;			// Logic block
	return TRUE;
}

//
// 读文件
// fd: 文件号 
// buf:数据指针
// sz: 字节数
//

ULONG
ReadFile(int fd, void *buf, ULONG sz) {
	ULONG	offst, brd;
	UINT	bsz, csz;
	FATFILE	*f, *raw;
	
	ASSERT((UINT)fd < FILE_MAX);
	CHECK_PTR(buf);
	ASSERT(Files[fd].Flags & F_OPEN);

	f = &Files[fd];
	brd = 0;
	if((UINT)fd >= FILE_MAX || !(f->Flags & F_OPEN))
		goto ret;
	
	ASSERT(f->Magic == FILE_MAGIC);

	if(!(f->Drive->Flags & DRIVE_MOUNT))
		goto ret;
	
	raw = (f->Flags & F_SHARE) ? f->sf : f;
	ASSERT(raw != NULL);
	
	//sm_p(raw->sm, FOREVER);
	
	csz = f->Drive->ClusterSize;
	offst = f->Pos;
	if(offst + sz > raw->Size)
		sz = raw->Size - offst;
	while(sz != 0 && !(f->Flags & F_EOF)) {
		// 调入当前簇
		if(!FillBuffer(f, offst / csz, FALSE))
			break;
		
		bsz = csz - (offst & (csz - 1));
		if(bsz > sz)
			bsz = sz;
		
		Memcpy(buf, f->Buffer + (offst & (csz - 1)), bsz);
		
		// 移动数据指针
		sz -= bsz;
		brd += bsz;
		offst += bsz;
		buf = (UCHAR *)buf + bsz;
	}
	if(offst >= raw->Size)
		f->Flags |= F_EOF;
	f->Pos = offst;
	
	//sm_v(raw->sm);
ret:
	return brd;
}

//
// 写文件
// fd: 文件号 
// buf:数据指针
// sz: 字节数
//

ULONG
WriteFile(int fd, void *buf, ULONG sz) {
	ULONG	offst, bwr;
	UINT	bsz, csz;
	FATFILE	*f, *raw;
	
	ASSERT((UINT)fd < FILE_MAX);
	CHECK_PTR(buf);
	ASSERT(Files[fd].Flags & F_OPEN);

	f = &Files[fd];
	bwr = 0;
	if((UINT)fd >= FILE_MAX || !(f->Flags & F_OPEN))
		goto ret;
	
	ASSERT(f->Magic == FILE_MAGIC);

	if(!(f->Drive->Flags & DRIVE_MOUNT))
		return 0;

	raw = (f->Flags & F_SHARE) ? f->sf : f;
	ASSERT(raw != NULL);
	
	//if(f->Drive->ms != NULL)
	//	DBG3("WriteFile(%d, %08X, %u)\n", fd, buf, sz);
	
	//sm_p(raw->sm, FOREVER);
	
	csz = f->Drive->ClusterSize;
	offst = f->Pos;
	while(sz != 0) {
		// 调入当前簇
		if(!FillBuffer(f, offst / csz, FALSE)) {
			// 扩充文件大小
			if(!ExtendFile(f))
				break;
			
			// 再次调入新簇
			if(!FillBuffer(f, offst / csz, TRUE))
				break;	// ???
		}
		bsz = csz - (offst & (csz - 1));
		if(bsz > sz)
			bsz = sz;
		Memcpy(f->Buffer + (offst & (csz - 1)), buf, bsz);
		
		// 移动数据指针
		f->Flags |= F_MODIF;
		sz -= bsz;
		bwr += bsz;
		offst += bsz;
		buf = (UCHAR *)buf + bsz;
	}
	if(offst > raw->Size) {
		// 文件大小被修改
		f->Flags |= F_EOF | F_SZCHG;
		raw->Size = offst;
	}
	f->Pos = offst;
	
	//sm_v(raw->sm);
ret:
	return bwr;
}

//
// 移动文件访问指针
//
// fd: 文件号
// offst: 偏移
// orig: 移动方式
//

ULONG
SeekFile(int fd, long offst, int orig) {
	long	pos;
	FATFILE	*f, *raw;
	
	ASSERT((UINT)fd < FILE_MAX);
	ASSERT(orig == 0 || orig == 1 || orig == 2);
	ASSERT(Files[fd].Flags & F_OPEN);

	f = &Files[fd];
	if((UINT)fd >= FILE_MAX || !(f->Flags & F_OPEN))
		return -1;

	ASSERT(f->Magic == FILE_MAGIC);

	if(!(f->Drive->Flags & DRIVE_MOUNT))
		return 0;

	raw = (f->Flags & F_SHARE) ? f->sf : f;
	ASSERT(raw != NULL);
	
	
	sm_p(raw->sm, FOREVER);
	
	pos = f->Pos;
	switch(orig) {
	case FILE_BEGIN: pos = offst; break; // 从文件头开始
	case FILE_CUR:	pos += offst; break; // 从当前位置开始
	case FILE_END:	pos = (long)raw->Size - offst;	break; // 从文件尾开始
	}
	if(pos < 0)	pos = 0;
	if(pos >= (long)raw->Size) {
		pos = (long)raw->Size;
		f->Flags |= F_EOF;  // 文件结束标志
	}
	f->Pos = pos;
	
	sm_v(raw->sm);
	
	return pos;
}

//
// 卸载驱动器
//
int
FatUnmount(DRIVE *d) {
	
	CHECK_PTR(d);
	CHECK_PTR(d->sm);
	ASSERT(d->Flags & DRIVE_MOUNT);
	
	d->Flags = 0;
	sm_delete(d->sm);
	d->sm = 0;
	return 0;
}

//
// 挂载驱动器
//
// d: 驱动器
// Name: 驱动器名称
//
int
FatMount(DRIVE *d, const char *Name) {
	MBR			*mbr;
	BOOTSECTOR	*bs;
	int			i, ismbr;
	UCHAR		*tmpbuf;
	
	ASSERT(d);
	
	DBG1("Mount %s... ", Name);

	// 读入FAT12/16/32文件系统结构
	tmpbuf = d->tmpbuf;
	if(!(*d->ReadSector)(d, 0, tmpbuf)) {
err:	DBG("FAILURE!\n");
		return FALSE;
	}

	// 判读文件系统的有效性
	mbr = (MBR *)tmpbuf;
	if(mbr->BootSectorMagic[0] != 0x55 || mbr->BootSectorMagic[1] != 0xaa)
		goto err;
	
	// 有的U盘有分区表
	ismbr = TRUE;
	for(i = 0; i < 4; i++)
	if(mbr->List[i].BootIndicator != 0x80 &&
		mbr->List[i].BootIndicator != 0x00)
		ismbr = FALSE;
	
	bs = (BOOTSECTOR *)mbr;
	if((bs->BytesPerSector % 512) || bs->NumberOfFats > 2)
		ismbr = TRUE;

	if(!ismbr) {
		d->Fat32 = bs->TotalSectors == 0 && bs->SectorsPerFat == 0;
	} else {
		ULONG		st;
		// 查找分区表中的FAT12/16/32分区
		for(i = 0; i < 4; i++) {
			if(mbr->List[i].SystemIndicator == 0x4 ||
				mbr->List[i].SystemIndicator == 0x6 ||
				mbr->List[i].SystemIndicator == 0xe) {
				
				d->Fat32 = FALSE;
				break;
			}
			if(mbr->List[i].SystemIndicator == 0xB ||
				mbr->List[i].SystemIndicator == 0xC) {
				
				d->Fat32 = TRUE;
				break;
			}
		}
		if(i == 4)
			return FALSE;

		// 读入真正的FAT12/16/32文件系统结构
		st = mbr->List[i].SectorCountBeforePartition;
		if(!(*d->ReadSector)(d, st, (void *)bs))
			goto err;

		if(bs->BootSectorMagic[0] != 0x55 || bs->BootSectorMagic[1] != 0xaa)
			goto err;
	}
	
	//if(d->Fat32)
	//	DBG("File system: FAT32\n");
	//else
	//	DBG("File system: FAT16\n");

	// 获取文件系统信息
	d->BytesPerSector = bs->BytesPerSector;
	d->BytesPerSectorShift = mylog2(d->BytesPerSector);
	d->SectorsPerCluster = bs->SectorsPerCluster;
	d->SectorsPerClusterShift = mylog2(d->SectorsPerCluster);
	d->ClusterSizeShift = mylog2(d->ClusterSize =
			bs->BytesPerSector << d->SectorsPerClusterShift);
	
	d->NumSectors = bs->TotalSectors ? bs->TotalSectors : bs->TotalSectorsBig;
	d->NumClusters = d->NumSectors >> d->SectorsPerClusterShift;
	d->Fat2 = 0;
	d->FatStart = bs->ReservedSectors + bs->HiddenSectors;
	d->FatLength = bs->SectorsPerFat ? bs->SectorsPerFat : bs->SectorsPerFatBig;

	if(d->Fat32) {
		d->DataStart = d->FatStart + bs->NumberOfFats * bs->SectorsPerFatBig;
		d->RootStart = bs->RootDirStartCluster;
		d->FatEnd = 0x0FFFFFF7;
	}
	else {
		d->RootEntries = bs->RootDirEntries;
		d->RootStart = d->FatStart + bs->NumberOfFats * d->FatLength;
		d->DataStart = d->RootStart + ((d->RootEntries * 32) >> d->BytesPerSectorShift);
		d->FatEnd = 0xFFF7;
	}
	d->Fat1 = d->FatStart;
	if(bs->NumberOfFats > 1)
		d->Fat2 = d->FatStart + d->FatLength;
	d->Ref = 0;
	d->fatst = -3;
	d->Flags = DRIVE_MOUNT;
	d->fatgoal = 2;

	
	sm_create(Name, 1, 0, &d->sm);
	
	ASSERT((d->BytesPerSector % 512) == 0);
	ASSERT((d->SectorsPerCluster % 2) == 0);
	
	DBG("OK!\n");
	return TRUE;
}

⌨️ 快捷键说明

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