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

📄 ff.c

📁 STM32_电子相框.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (c == 0x05) c = 0xE5;
			if ((nt & 0x08) && IsUpper(c)) c += 0x20;
			*p++ = c;
		}
		if (dir[8] != ' ') {		/* Copy file name extension */
			*p++ = '.';
			for (i = 8; i < 11; i++) {
				c = dir[i];
				if (c == ' ') break;
				if ((nt & 0x10) && IsUpper(c)) c += 0x20;
				*p++ = c;
			}
		}
		fno->fattrib = dir[DIR_Attr];				/* Attribute */
		fno->fsize = LD_DWORD(dir+DIR_FileSize);	/* Size */
		fno->fdate = LD_WORD(dir+DIR_WrtDate);		/* Date */
		fno->ftime = LD_WORD(dir+DIR_WrtTime);		/* Time */
	}
	*p = 0;

#if _USE_LFN
	p = fno->lfname;
	if (p) {
		WCHAR wchr, *lfn;

		i = 0;
		if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */
			lfn = dj->lfn;
			while ((wchr = *lfn++) != 0) {		/* Get an LFN char */
				wchr = ff_convert(wchr, 0);		/* Unicode -> OEM code */
				if (!wchr) { i = 0; break; }	/* Conversion error, no LFN */
				if (_DF1S && wchr >= 0x100)		/* Put 1st byte if it is a DBC */
					p[i++] = (char)(wchr >> 8);
				p[i++] = (char)wchr;
				if (i >= fno->lfsize) { i = 0; break; }	/* Buffer overrun, no LFN */
			}
		}
		p[i] = 0;	/* Terminator */
	}
#endif
}
#endif /* _FS_MINIMIZE <= 1 */




/*-----------------------------------------------------------------------*/
/* Follow a file path                                                    */
/*-----------------------------------------------------------------------*/

static
FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
	DIR *dj,			/* Directory object to return last directory and found object */
	const char *path	/* Full-path string to find a file or directory */
)
{
	FRESULT res;
	BYTE *dir, last;


	if (*path == '/' || *path == '\\' ) path++;	/* Strip heading separator */

	dj->sclust =						/* Set start directory (root dir) */
		(dj->fs->fs_type == FS_FAT32) ? dj->fs->dirbase : 0;

	if ((BYTE)*path < ' ') {			/* Null path means the root directory */
		res = dir_seek(dj, 0);
		dj->dir = NULL;

	} else {							/* Follow path */
		for (;;) {
			res = create_name(dj, &path);	/* Get a segment */
			if (res != FR_OK) break;
			res = dir_find(dj);				/* Find it */
			last = *(dj->fn+11) & 4;
			if (res != FR_OK) {				/* Could not find the object */
				if (res == FR_NO_FILE && !last)
					res = FR_NO_PATH;
				break;
			}
			if (last) break;				/* Last segment match. Function completed. */
			dir = dj->dir;					/* There is next segment. Follow the sub directory */
			if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
				res = FR_NO_PATH; break;
			}
			dj->sclust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO);
		}
	}

	return res;
}




/*-----------------------------------------------------------------------*/
/* Load boot record and check if it is an FAT boot record                */
/*-----------------------------------------------------------------------*/

static
BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	FATFS *fs,	/* File system object */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	if (disk_read(fs->drive, fs->win, sect, 1) != RES_OK)	/* Load boot record */
		return 3;
	if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55)				/* Check record signature (always placed at offset 510 even if the sector size is >512) */
		return 2;

	if (!mem_cmp(&fs->win[BS_FilSysType], "FAT", 3))		/* Check FAT signature */
		return 0;
	if (!mem_cmp(&fs->win[BS_FilSysType32], "FAT32", 5) && !(fs->win[BPB_ExtFlags] & 0x80))
		return 0;

	return 1;
}




/*-----------------------------------------------------------------------*/
/* Make sure that the file system is valid                               */
/*-----------------------------------------------------------------------*/

static
FRESULT auto_mount (	/* FR_OK(0): successful, !=0: any error occured */
	const char **path,	/* Pointer to pointer to the path name (drive number) */
	FATFS **rfs,		/* Pointer to pointer to the found file system object */
	BYTE chk_wp			/* !=0: Check media write protection for write access */
)
{
	FRESULT res;
	BYTE vol, fmt, *tbl;
	DSTATUS stat;
	DWORD bsect, fsize, tsect, mclst;
	const char *p = *path;
	FATFS *fs;


	/* Get logical drive number from the path name */
	vol = p[0] - '0';			/* Is there a drive number? */
	if (vol <= 9 && p[1] == ':') {
		p += 2;					/* Found a drive number, get and strip it */
		*path = p;				/* Return pointer to the path name */
	} else {
		vol = 0;				/* No drive number is given, use drive number 0 as default */
	}

	/* Check if the logical drive number is valid or not */
	if (vol >= _DRIVES) return FR_INVALID_DRIVE;	/* Is the drive number valid? */
	*rfs = fs = FatFs[vol];					/* Returen pointer to the corresponding file system object */
	if (!fs) return FR_NOT_ENABLED;			/* Is the file system object registered? */

	ENTER_FF(fs);				/* Lock file system */

	if (fs->fs_type) {						/* If the logical drive has been mounted */
		stat = disk_status(fs->drive);
		if (!(stat & STA_NOINIT)) {			/* and physical drive is kept initialized (has not been changed), */
#if !_FS_READONLY
			if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */
				return FR_WRITE_PROTECTED;
#endif
			return FR_OK;					/* The file system object is valid */
		}
	}

	/* The logical drive must be re-mounted. Following code attempts to mount the volume */

	fs->fs_type = 0;					/* Clear the file system object */
	fs->drive = LD2PD(vol);				/* Bind the logical drive and a physical drive */
	stat = disk_initialize(fs->drive);	/* Initialize low level disk I/O layer */
	if (stat & STA_NOINIT)				/* Check if the drive is ready */
		return FR_NOT_READY;
#if _MAX_SS != 512						/* Get disk sector size if needed */
	if (disk_ioctl(fs->drive, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS)
		return FR_NO_FILESYSTEM;
#endif
#if !_FS_READONLY
	if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */
		return FR_WRITE_PROTECTED;
#endif
	/* Search FAT partition on the drive */
	fmt = check_fs(fs, bsect = 0);		/* Check sector 0 as an SFD format */
	if (fmt == 1) {						/* Not an FAT boot record, it may be patitioned */
		/* Check a partition listed in top of the partition table */
		tbl = &fs->win[MBR_Table + LD2PT(vol) * 16];	/* Partition table */
		if (tbl[4]) {									/* Is the partition existing? */
			bsect = LD_DWORD(&tbl[8]);					/* Partition offset in LBA */
			fmt = check_fs(fs, bsect);					/* Check the partition */
		}
	}
	if (fmt == 3) return FR_DISK_ERR;
	if (fmt || LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs))	/* No valid FAT patition is found */
		return FR_NO_FILESYSTEM;

	/* Initialize the file system object */
	fsize = LD_WORD(fs->win+BPB_FATSz16);				/* Number of sectors per FAT */
	if (!fsize) fsize = LD_DWORD(fs->win+BPB_FATSz32);
	fs->sects_fat = fsize;
	fs->n_fats = fs->win[BPB_NumFATs];					/* Number of FAT copies */
	fsize *= fs->n_fats;								/* (Number of sectors in FAT area) */
	fs->fatbase = bsect + LD_WORD(fs->win+BPB_RsvdSecCnt); /* FAT start sector (lba) */
	fs->csize = fs->win[BPB_SecPerClus];				/* Number of sectors per cluster */
	fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt);	/* Nmuber of root directory entries */
	tsect = LD_WORD(fs->win+BPB_TotSec16);				/* Number of sectors on the file system */
	if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32);
	fs->max_clust = mclst = (tsect						/* Last cluster# + 1 */
		- LD_WORD(fs->win+BPB_RsvdSecCnt) - fsize - fs->n_rootdir / (SS(fs)/32)
		) / fs->csize + 2;

	fmt = FS_FAT12;										/* Determine the FAT sub type */
	if (mclst >= 0xFF7) fmt = FS_FAT16;				/* Number of clusters >= 0xFF5 */
	if (mclst >= 0xFFF7) fmt = FS_FAT32;			/* Number of clusters >= 0xFFF5 */

	if (fmt == FS_FAT32)
		fs->dirbase = LD_DWORD(fs->win+BPB_RootClus);	/* Root directory start cluster */
	else
		fs->dirbase = fs->fatbase + fsize;				/* Root directory start sector (lba) */
	fs->database = fs->fatbase + fsize + fs->n_rootdir / (SS(fs)/32);	/* Data start sector (lba) */

#if !_FS_READONLY
	/* Initialize allocation information */
	fs->free_clust = 0xFFFFFFFF;
	fs->wflag = 0;
	/* Get fsinfo if needed */
	if (fmt == FS_FAT32) {
		fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo);
		fs->fsi_flag = 0;
		if (disk_read(fs->drive, fs->win, fs->fsi_sector, 1) == RES_OK &&
			LD_WORD(fs->win+BS_55AA) == 0xAA55 &&
			LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 &&
			LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) {
			fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free);
			fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count);
		}
	}
#endif
	fs->winsect = 0;
	fs->fs_type = fmt;			/* FAT syb-type */
	fs->id = ++Fsid;			/* File system mount ID */
	res = FR_OK;

	return res;
}




/*-----------------------------------------------------------------------*/
/* Check if the file/dir object is valid or not                          */
/*-----------------------------------------------------------------------*/

static
FRESULT validate (	/* FR_OK(0): The object is valid, !=0: Invalid */
	FATFS *fs,		/* Pointer to the file system object */
	WORD id			/* Member id of the target object to be checked */
)
{
	if (!fs || !fs->fs_type || fs->id != id)
		return FR_INVALID_OBJECT;

	ENTER_FF(fs);		/* Lock file system */

	if (disk_status(fs->drive) & STA_NOINIT)
		return FR_NOT_READY;

	return FR_OK;
}




/*--------------------------------------------------------------------------

   Public Functions

--------------------------------------------------------------------------*/



/*-----------------------------------------------------------------------*/
/* Mount/Unmount a Locical Drive                                         */
/*-----------------------------------------------------------------------*/

FRESULT f_mount (
	BYTE vol,		/* Logical drive number to be mounted/unmounted */
	FATFS *fs		/* Pointer to new file system object (NULL for unmount)*/
)
{
	FATFS *rfs;


	if (vol >= _DRIVES)				/* Check if the drive number is valid */
		return FR_INVALID_DRIVE;
	rfs = FatFs[vol];				/* Get current state */

	if (rfs) {
#if _FS_REENTRANT					/* Discard sync object of the current volume */
		if (!ff_del_syncobj(fs->sobj)) return FR_INT_ERR;
#endif
		rfs->fs_type = 0;			/* Clear old fs object */
	}

	if (fs) {
		fs->fs_type = 0;			/* Clear new fs object */
#if _FS_REENTRANT					/* Create sync object for the new volume */
		if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
#endif
	}
	FatFs[vol] = fs;				/* Register new fs object */

	return FR_OK;
}




/*-----------------------------------------------------------------------*/
/* Open or Create a File                                                 */
/*-----------------------------------------------------------------------*/

FRESULT f_open (
	FIL *fp,			/* Pointer to the blank file object */
	const char *path,	/* Pointer to the file name */
	BYTE mode			/* Access mode and file open mode flags */
)
{
	FRESULT res;
	DIR dj;
	NAMEBUF(sfn, lfn);
	BYTE *dir;


	fp->fs = NULL;		/* Clear file object */
#if !_FS_READONLY
	mode &= (FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW);
	res = auto_mount(&path, &dj.fs, (BYTE)(mode & (FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)));
#else
	mode &= FA_READ;
	res = auto_mount(&path, &dj.fs, 0);
#endif
	if (res != FR_OK) LEAVE_FF(dj.fs, res);
	INITBUF(dj, sfn, lfn);
	res = follow_path(&dj, path);	/* Follow the file path */

#if !_FS_READONLY
	/* Create or Open a file */
	if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
		DWORD ps, cl;

		if (res != FR_OK) {		/* No file, create new */
			if (res == FR_NO_FILE)
				res = dir_register(&dj);
			if (res != FR_OK) LEAVE_FF(dj.fs, res);
			mode |= FA_CREATE_ALWAYS;
			dir = dj.dir;
		}
		else {					/* Any object is already existing */
			if (mode & FA_CREATE_NEW)			/* Cannot create new */
				LEAVE_FF(dj.fs, FR_EXIST);
			dir = dj.dir;
			if (!dir || (dir[DIR_Attr] & (AM_RDO | AM_DIR)))	/* Cannot overwrite it (R/O or DIR) */
				LEAVE_FF(dj.fs, FR_DENIED);
			if (mode & FA_CREATE_ALWAYS) {		/* Resize it to zero if needed */
				cl = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO);	/* Get start cluster */
				ST_WORD(dir+DIR_FstClusHI, 0);	/* cluster = 0 */
				ST_WORD(dir+DIR_FstClusLO, 0);
				ST_DWORD(dir+DIR_FileSize, 0);	/* size = 0 */
				dj.fs->wflag = 1;
				ps = dj.fs->winsect;			/* Remove the cluster chain */
				if (cl) {
					res = remove_chain(dj.fs, cl);
					if (res) LEAVE_FF(dj.fs, res);
					dj.fs->last_clust = cl - 1;	/* Reuse the cluster hole */
				}
				res = move_window(dj.fs, ps);
				if (res != FR_OK) LEAVE_FF(dj.fs, res);
			}
		}
		if (mode & FA_CREATE_ALWAYS) {
			dir[DIR_Attr] = 0;					/* Reset attribute */
			ps = get_fattime();
			ST_DWORD(dir+DIR_CrtTime, ps);		/* Created time */
			dj.fs->wflag = 1;
			mode |= FA__WRITTEN;				/* Set file changed flag */
		}
	}
	/* Open an existing file */
	else {
#endif /* !_FS_READONLY */
		if (res != FR_OK) LEAVE_FF(dj.fs, res);	/* Follow failed */
		dir = dj.dir;
		if (!dir || (dir[DIR_Attr] & AM_DIR))	/* It is a directory */
			LEAVE_FF(dj.fs, FR_NO_FILE);
#if !_FS_READONLY
		if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
			LEAVE_FF(dj.fs, FR_DENIED);
	}
	fp->dir_sect = dj.fs->winsect;		/* Pointer to the directory entry */
	fp->dir_ptr = dj.dir;
#endif
	fp->flag = mode;					/* File access mode */
	fp->org_clust =						/* File start cluster */
		((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO);
	fp->fsize = LD_DWORD(dir+DIR_FileSize);	/* File size */
	fp->fptr = 0; fp->csect = 255;		/* File pointer */

⌨️ 快捷键说明

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