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

📄 ff.c

📁 收集了单片机对SD卡读写源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	/* Root directory start cluster */
	else
	{
		fs->dirbase = fs->fatbase + fatsize;
	}			/* Root directory start sector (lba) */
	fs->database = fs->fatbase + fatsize + fs->n_rootdir / (S_SIZ / 32);	/* Data start sector (lba) */

#if !_FS_READONLY
	fs->free_clust = 0xFFFFFFFF;
#if _USE_FSINFO
	/* Load fsinfo sector if needed */
	if (fmt == FS_FAT32)
	{
		fs->fsi_sector = bootsect + LD_WORD(&fs->win[BPB_FSInfo]);
		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
#endif
	fs->id = ++fsid;									/* File system mount ID */
	return FR_OK;
}




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

static
FRESULT validate(/* FR_OK(0): The object is valid, !=0: Not valid */
	const FATFS *fs, /* Pointer to the file system object */
	WORD id				/* id member of the target object to be checked */)
{
	if (!fs || fs->id != id)
	{
		return FR_INVALID_OBJECT;
	}
	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 drv, /* Logical drive number to be mounted/unmounted */
	FATFS *fs		/* Pointer to new file system object (NULL for unmount)*/)
{
	FATFS *fsobj;


	if (drv >= _DRIVES)
	{
		return FR_INVALID_DRIVE;
	}
	fsobj = FatFs[drv];
	FatFs[drv] = fs;
	if (fsobj)
	{
		memset(fsobj, 0, sizeof(FATFS));
	}
	if (fs)
	{
		memset(fs, 0, sizeof(FATFS));
	}

	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;
	BYTE *dir;
	DIR dirobj;
	char fn[8 + 3 + 1];
	FATFS *fs;


	fp->fs = NULL;
#if !_FS_READONLY
	mode &= (FA_READ |
			 FA_WRITE |
			 FA_CREATE_ALWAYS |
			 FA_OPEN_ALWAYS |
			 FA_CREATE_NEW);
	res = auto_mount(&path,
					 &fs,
					 (BYTE)
					 (mode & (FA_WRITE |
							  FA_CREATE_ALWAYS |
							  FA_OPEN_ALWAYS |
							  FA_CREATE_NEW)));
#else
	mode &= FA_READ;
	res = auto_mount(&path, &fs, 0);
#endif
	if (res != FR_OK)
	{
		return res;
	}
	dirobj.fs = fs;

	/* Trace the file path */
	res = trace_path(&dirobj, fn, path, &dir);
#if !_FS_READONLY
	/* Create or Open a file */
	if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW))
	{
		DWORD ps, rs;
		if (res != FR_OK)
		{
			/* No file, create new */
			if (res != FR_NO_FILE)
			{
				return res;
			}
			res = reserve_direntry(&dirobj, &dir);
			if (res != FR_OK)
			{
				return res;
			}
			memset(dir, 0, 32);						/* Initialize the new entry with open name */
			memcpy(&dir[DIR_Name], fn, 8 + 3);
			dir[DIR_NTres] = fn[11];
			mode |= FA_CREATE_ALWAYS;
		}
		else
		{
			/* Any object is already existing */
			if (mode & FA_CREATE_NEW)			/* Cannot create new */
			{
				return FR_EXIST;
			}
			if (dir == NULL || (dir[DIR_Attr] & (AM_RDO | AM_DIR)))	/* Cannot overwrite it (R/O or DIR) */
			{
				return FR_DENIED;
			}
			if (mode & FA_CREATE_ALWAYS)
			{
				/* Resize it to zero if needed */
				rs = ((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 */
				fs->winflag = 1;
				ps = fs->winsect;				/* Remove the cluster chain */
				if (!remove_chain(fs, rs) || !move_window(fs, ps))
				{
					return FR_RW_ERROR;
				}
				fs->last_clust = rs - 1;		/* Reuse the cluster hole */
			}
		}
		if (mode & FA_CREATE_ALWAYS)
		{
			dir[DIR_Attr] = AM_ARC;				/* New attribute */
			ps = get_fattime();
			ST_DWORD(&dir[DIR_WrtTime], ps);	/* Updated time */
			ST_DWORD(&dir[DIR_CrtTime], ps);	/* Created time */
			fs->winflag = 1;
		}
	}
	/* Open an existing file */
	else
	{
#endif /* !_FS_READONLY */
		if (res != FR_OK)
		{
			return res;
		}		/* Trace failed */
		if (dir == NULL || (dir[DIR_Attr] & AM_DIR))	/* It is a directory */
		{
			return FR_NO_FILE;
		}
#if !_FS_READONLY
		if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
		{
			return FR_DENIED;
		}
	}

	fp->dir_sect = fs->winsect;			/* Pointer to the directory entry */
	fp->dir_ptr = 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;						/* File ptr */
	fp->sect_clust = 1;					/* Sector counter */
	fp->fs = fs; fp->id = fs->id;		/* Owner file system object of the file */

	return FR_OK;
}




/*-----------------------------------------------------------------------*/
/* Read File															 */
/*-----------------------------------------------------------------------*/

FRESULT f_read(FIL *fp, /* Pointer to the file object */
	void *buff, /* Pointer to data buffer */
	UINT btr, /* Number of bytes to read */
	UINT *br		/* Pointer to number of bytes read */)
{
	DWORD clust, sect, remain;
	UINT rcnt, cc;
	BYTE *rbuff = buff;
	FRESULT res;
	FATFS *fs = fp->fs;


	*br = 0;
	res = validate(fs, fp->id);						/* Check validity of the object */
	if (res != FR_OK)
	{
		return res;
	}
	if (fp->flag & FA__ERROR)
	{
		return FR_RW_ERROR;
	}	/* Check error flag */
	if (!(fp->flag & FA_READ))
	{
		return FR_DENIED;
	}	/* Check access mode */
	remain = fp->fsize - fp->fptr;
	if (btr > remain)
	{
		btr = (WORD) remain;
	}			/* Truncate read count by number of bytes left */

	for (;
		 btr; /* Repeat until all data transferred */
		 rbuff += rcnt, fp->fptr += rcnt,*br += rcnt, btr -= rcnt)
	{
		if ((fp->fptr & (S_SIZ - 1)) == 0)
		{
			/* On the sector boundary */
			if (--fp->sect_clust)
			{
				/* Decrement left sector counter */
				sect = fp->curr_sect + 1;			/* Get current sector */
			}
			else
			{
				/* On the cluster boundary, get next cluster */
				clust = (fp->fptr == 0) ?
						fp->org_clust :
						get_cluster(fs,
									fp->curr_clust);
				if (clust < 2 || clust >= fs->max_clust)
				{
					goto fr_error;
				}
				fp->curr_clust = clust;				/* Current cluster */
				sect = clust2sect(fs, clust);		/* Get current sector */
				fp->sect_clust = fs->sects_clust;	/* Re-initialize the left sector counter */
			}
#if !_FS_READONLY
			if (fp->flag & FA__DIRTY)
			{
				/* Flush file I/O buffer if needed */
				if (disk_write(fs->drive, fp->buffer, fp->curr_sect, 1) !=
					RES_OK)
				{
					goto fr_error;
				}
				fp->flag &= ~FA__DIRTY;
			}
#endif
			fp->curr_sect = sect;					/* Update current sector */
			cc = btr / S_SIZ;						/* When left bytes >= S_SIZ, */
			if (cc)
			{
				/* Read maximum contiguous sectors directly */
				if (cc > fp->sect_clust)
				{
					cc = fp->sect_clust;
				}
				if (disk_read(fs->drive, rbuff, sect, (BYTE) cc) != RES_OK)
				{
					goto fr_error;
				}
				fp->sect_clust -= (BYTE) (cc - 1);
				fp->curr_sect += cc - 1;
				rcnt = cc * S_SIZ;
				continue;
			}
			if (disk_read(fs->drive, fp->buffer, sect, 1) != RES_OK)	/* Load the sector into file I/O buffer */
			{
				goto fr_error;
			}
		}
		rcnt = S_SIZ - ((WORD) fp->fptr & (S_SIZ - 1));				/* Copy fractional bytes from file I/O buffer */
		if (rcnt > btr)
		{
			rcnt = btr;
		}
		memcpy(rbuff, &fp->buffer[fp->fptr & (S_SIZ - 1)], rcnt);
	}

	return FR_OK;

	fr_error:	/* Abort this file due to an unrecoverable error */
	fp->flag |= FA__ERROR;
	return FR_RW_ERROR;
}




#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Write File   														 */
/*-----------------------------------------------------------------------*/

FRESULT f_write(FIL *fp, /* Pointer to the file object */
	const void *buff, /* Pointer to the data to be written */
	UINT btw, /* Number of bytes to write */
	UINT *bw			/* Pointer to number of bytes written */)
{
	DWORD clust, sect;
	UINT wcnt, cc;
	const BYTE *wbuff = buff;
	FRESULT res;
	FATFS *fs = fp->fs;


	*bw = 0;
	res = validate(fs, fp->id);						/* Check validity of the object */
	if (res != FR_OK)
	{
		return res;
	}
	if (fp->flag & FA__ERROR)
	{
		return FR_RW_ERROR;
	}	/* Check error flag */
	if (!(fp->flag & FA_WRITE))
	{
		return FR_DENIED;
	}	/* Check access mode */
	if (fp->fsize + btw < fp->fsize)
	{
		return FR_OK;
	}	/* File size cannot reach 4GB */

	for (;
		 btw; /* Repeat until all data transferred */
		 wbuff += wcnt, fp->fptr += wcnt,*bw += wcnt, btw -= wcnt)
	{
		if ((fp->fptr & (S_SIZ - 1)) == 0)
		{
			/* On the sector boundary */
			if (--fp->sect_clust)
			{
				/* Decrement left sector counter */
				sect = fp->curr_sect + 1;			/* Get current sector */
			}
			else
			{
				/* On the cluster boundary, get next cluster */
				if (fp->fptr == 0)
				{
					/* Is top of the file */
					clust = fp->org_clust;
					if (clust == 0)					/* No cluster is created yet */
					{
						fp->org_clust = clust = create_chain(fs, 0);
					}	/* Create a new cluster chain */
				}
				else
				{
					/* Middle or end of file */
					clust = create_chain(fs, fp->curr_clust);			/* Trace or streach cluster chain */
				}
				if (clust == 0)
				{
					break;
				}				/* Disk full */
				if (clust == 1 || clust >= fs->max_clust)
				{
					goto fw_error;
				}
				fp->curr_clust = clust;				/* Current cluster */
				sect = clust2sect(fs, clust);		/* Get current sector */
				fp->sect_clust = fs->sects_clust;	/* Re-initialize the left sector counter */
			}
			if (fp->flag & FA__DIRTY)
			{
				/* Flush file I/O buffer if needed */
				if (disk_write(fs->drive, fp->buffer, fp->curr_sect, 1) !=
					RES_OK)
				{
					goto fw_error;
				}
				fp->flag &= ~FA__DIRTY;
			}
			fp->curr_sect = sect;					/* Update current sector */
			cc = btw / S_SIZ;						/* When left bytes >= S_SIZ, */
			if (cc)
			{
				/* Write maximum contiguous sectors directly */
				if (cc > fp->sect_clust)
				{
					cc = fp->sect_clust;
				}
				if (disk_write(fs->drive, wbuff, sect, (BYTE) cc) != RES_OK)
				{
					goto fw_error;
				}
				fp->sect_clust -= (BYTE) (cc - 1);
				fp->curr_sect += cc - 1;
				wcnt = cc * S_SIZ;
				continue;
			}
			if (fp->fptr <
				fp->fsize &&   			/* Fill sector buffer with file data if needed */
				disk_read(fs->drive, fp->buffer, sect, 1) !=
				RES_OK)
			{
				goto fw_error;
			}
		}
		wcnt = S_SIZ - ((WORD) fp->fptr & (S_SIZ - 1));	/* Copy fractional bytes to file I/O buffer */
		if (wcnt > btw)
		{
			wcnt = btw;
		}
		memcpy(&fp->buffer[fp->fptr & (S_SIZ - 1)], wbuff, wcnt);
		fp->flag |= FA__DIRTY;
	}

	if (fp->fptr > fp->fsize)
	{
		fp->fsize = fp->fptr;
	}	/* Update file size if needed */
	fp->flag |= FA__WRITTEN;						/* Set file changed flag */
	return FR_OK;

	fw_error:	/* Abort this file due to an unrecoverable error */
	fp->flag |= FA__ERROR;
	return FR_RW_ERROR;
}




/*-----------------------------------------------------------------------*/
/* Synchronize the file object  										 */
/*-----------------------------------------------------------------------*/

FRESULT f_sync(FIL *fp		/* Pointer to the file object */)
{
	DWORD tim;
	BYTE *dir;
	FRESULT res;
	FATFS *fs = fp->fs;

⌨️ 快捷键说明

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