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

📄 ff.c

📁 STM32_电子相框.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (nxt == 0) break;				/* Empty cluster? */
			if (nxt == 1) { res = FR_INT_ERR; break; }	/* Internal error? */
			if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }	/* Disk error? */
			res = put_cluster(fs, clst, 0);		/* Mark the cluster "empty" */
			if (res != FR_OK) break;
			if (fs->free_clust != 0xFFFFFFFF) {	/* Update FSInfo */
				fs->free_clust++;
				fs->fsi_flag = 1;
			}
			clst = nxt;	/* Next cluster */
		}
	}

	return res;
}
#endif




/*-----------------------------------------------------------------------*/
/* Stretch or create a cluster chain                                     */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
static
DWORD create_chain (	/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
	FATFS *fs,			/* File system object */
	DWORD clst			/* Cluster# to stretch. 0 means create a new chain. */
)
{
	DWORD cs, ncl, scl, mcl;


	mcl = fs->max_clust;
	if (clst == 0) {		/* Create new chain */
		scl = fs->last_clust;			/* Get suggested start point */
		if (scl == 0 || scl >= mcl) scl = 1;
	}
	else {					/* Stretch existing chain */
		cs = get_cluster(fs, clst);		/* Check the cluster status */
		if (cs < 2) return 1;			/* It is an invalid cluster */
		if (cs < mcl) return cs;		/* It is already followed by next cluster */
		scl = clst;
	}

	ncl = scl;				/* Start cluster */
	for (;;) {
		ncl++;							/* Next cluster */
		if (ncl >= mcl) {				/* Wrap around */
			ncl = 2;
			if (ncl > scl) return 0;	/* No free custer */
		}
		cs = get_cluster(fs, ncl);		/* Get the cluster status */
		if (cs == 0) break;				/* Found a free cluster */
		if (cs == 0xFFFFFFFF || cs == 1)/* An error occured */
			return cs;
		if (ncl == scl) return 0;		/* No free custer */
	}

	if (put_cluster(fs, ncl, 0x0FFFFFFF))	/* Mark the new cluster "in use" */
		return 0xFFFFFFFF;
	if (clst != 0) {						/* Link it to previous one if needed */
		if (put_cluster(fs, clst, ncl))
			return 0xFFFFFFFF;
	}

	fs->last_clust = ncl;				/* Update FSINFO */
	if (fs->free_clust != 0xFFFFFFFF) {
		fs->free_clust--;
		fs->fsi_flag = 1;
	}

	return ncl;		/* Return new cluster number */
}
#endif /* !_FS_READONLY */




/*-----------------------------------------------------------------------*/
/* Get sector# from cluster#                                             */
/*-----------------------------------------------------------------------*/

static
DWORD clust2sect (	/* !=0: sector number, 0: failed - invalid cluster# */
	FATFS *fs,		/* File system object */
	DWORD clst		/* Cluster# to be converted */
)
{
	clst -= 2;
	if (clst >= (fs->max_clust - 2)) return 0;		/* Invalid cluster# */
	return clst * fs->csize + fs->database;
}




/*-----------------------------------------------------------------------*/
/* Seek directory index                                                  */
/*-----------------------------------------------------------------------*/

static
FRESULT dir_seek (
	DIR *dj,		/* Pointer to directory object */
	WORD idx		/* Directory index number */
)
{
	DWORD clst;
	WORD ic;


	dj->index = idx;
	clst = dj->sclust;
	if (clst == 1 || clst >= dj->fs->max_clust)	/* Check start cluster range */
		return FR_INT_ERR;

	if (clst == 0) {	/* Static table */
		if (idx >= dj->fs->n_rootdir)		/* Index is out of range */
			return FR_INT_ERR;
		dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / 32);
	}
	else {				/* Dynamic table */
		ic = SS(dj->fs) / 32 * dj->fs->csize;	/* Indexes per cluster */
		while (idx >= ic) {	/* Follow cluster chain */
			clst = get_cluster(dj->fs, clst);			/* Get next cluster */
			if (clst == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error */
			if (clst < 2 || clst >= dj->fs->max_clust)	/* Reached to end of table or int error */
				return FR_INT_ERR;
			idx -= ic;
		}
		dj->clust = clst;
		dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / 32);
	}
	dj->dir = dj->fs->win + (idx % (SS(dj->fs) / 32)) * 32;

	return FR_OK;	/* Seek succeeded */
}




/*-----------------------------------------------------------------------*/
/* Move directory index next                                             */
/*-----------------------------------------------------------------------*/

static
FRESULT dir_next (	/* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not streach */
	DIR *dj,		/* Pointer to directory object */
	BOOL streach	/* FALSE: Do not streach table, TRUE: Streach table if needed */
)
{
	DWORD clst;
	WORD i;


	i = dj->index + 1;
	if (!i || !dj->sect)	/* Report EOT when index has reached 65535 */
		return FR_NO_FILE;

	if (!(i % (SS(dj->fs) / 32))) {	/* Sector changed? */
		dj->sect++;					/* Next sector */

		if (dj->sclust == 0) {	/* Static table */
			if (i >= dj->fs->n_rootdir)	/* Report EOT when end of table */
				return FR_NO_FILE;
		}
		else {					/* Dynamic table */
			if (((i / (SS(dj->fs) / 32)) & (dj->fs->csize - 1)) == 0) {	/* Cluster changed? */
				clst = get_cluster(dj->fs, dj->clust);			/* Get next cluster */
				if (clst <= 1) return FR_INT_ERR;
				if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
				if (clst >= dj->fs->max_clust) {				/* When it reached end of dinamic table */
#if !_FS_READONLY
					BYTE c;
					if (!streach) return FR_NO_FILE;			/* When do not streach, report EOT */
					clst = create_chain(dj->fs, dj->clust);		/* Streach cluster chain */
					if (clst == 0) return FR_DENIED;			/* No free cluster */
					if (clst == 1) return FR_INT_ERR;
					if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
					/* Clean-up streached table */
					if (move_window(dj->fs, 0)) return FR_DISK_ERR;	/* Flush active window */
					mem_set(dj->fs->win, 0, SS(dj->fs));			/* Clear window buffer */
					dj->fs->winsect = clust2sect(dj->fs, clst);	/* Cluster start sector */
					for (c = 0; c < dj->fs->csize; c++) {		/* Fill the new cluster with 0 */
						dj->fs->wflag = 1;
						if (move_window(dj->fs, 0)) return FR_DISK_ERR;
						dj->fs->winsect++;
					}
					dj->fs->winsect -= c;						/* Rewind window address */
#else
					return FR_NO_FILE;			/* Report EOT */
#endif
				}
				dj->clust = clst;				/* Initialize data for new cluster */
				dj->sect = clust2sect(dj->fs, clst);
			}
		}
	}

	dj->index = i;
	dj->dir = dj->fs->win + (i % (SS(dj->fs) / 32)) * 32;

	return FR_OK;
}




/*-----------------------------------------------------------------------*/
/* Test/Pick/Fit an LFN segment from/to directory entry                  */
/*-----------------------------------------------------------------------*/
#if _USE_LFN
static
const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30};	/* Offset of LFN chars in the directory entry */


static
BOOL test_lfn (			/* TRUE:Matched, FALSE:Not matched */
	WCHAR *lfnbuf,		/* Pointer to the LFN to be compared */
	BYTE *dir			/* Pointer to the directory entry containing a part of LFN */
)
{
	int i, s;
	WCHAR wc1, wc2;


	i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13;	/* Offset in the LFN buffer */
	s = 0;
	do {
		if (i >= _MAX_LFN) return FALSE;	/* Out of buffer range? */
		wc1 = LD_WORD(dir+LfnOfs[s]);		/* Get both characters to compare */
		wc2 = lfnbuf[i++];
		if (IsLower(wc1)) wc1 -= 0x20;		/* Compare it (ignore case) */
		if (IsLower(wc2)) wc2 -= 0x20;
		if (wc1 != wc2) return FALSE;
	} while (++s < 13 && wc1);				/* Repeat until last char or a NUL char is processed */

	return TRUE;							/* The LFN entry matched */
}



static
BOOL pick_lfn (			/* TRUE:Succeeded, FALSE:Buffer overflow */
	WCHAR *lfnbuf,		/* Pointer to the Unicode-LFN buffer */
	BYTE *dir			/* Pointer to the directory entry */
)
{
	int i, s;
	WCHAR wchr;


	i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13;	/* Offset in the LFN buffer */
	s = 0;
	do {
		wchr = LD_WORD(dir+LfnOfs[s]);		/* Get an LFN char */
		if (!wchr) break;					/* End of LFN? */
		if (i >= _MAX_LFN) return FALSE;	/* Buffer overflow */
		lfnbuf[i++] = wchr;					/* Store it */
	} while (++s < 13);						/* Repeat until last char is copied */
	if (dir[LDIR_Ord] & 0x40) lfnbuf[i] = 0;	/* Put terminator if last LFN entry */

	return TRUE;
}


#if !_FS_READONLY
static
void fit_lfn (
	const WCHAR *lfnbuf,	/* Pointer to the LFN buffer */
	BYTE *dir,				/* Pointer to the directory entry */
	BYTE ord,				/* LFN order (1-20) */
	BYTE sum				/* SFN sum */
)
{
	int i, s;
	WCHAR wchr;


	dir[LDIR_Chksum] = sum;			/* Set check sum */
	dir[LDIR_Attr] = AM_LFN;		/* Set attribute. LFN entry */
	dir[LDIR_Type] = 0;
	ST_WORD(dir+LDIR_FstClusLO, 0);

	i = (ord - 1) * 13;				/* Offset in the LFN buffer */
	s = wchr = 0;
	do {
		if (wchr != 0xFFFF) wchr = lfnbuf[i++];	/* Get an effective char */
		ST_WORD(dir+LfnOfs[s], wchr);	/* Put it */
		if (!wchr) wchr = 0xFFFF;	/* Padding chars following last char */
	} while (++s < 13);
	if (wchr == 0xFFFF || !lfnbuf[i]) ord |= 0x40;/* Bottom LFN part is the start of LFN sequence */
	dir[LDIR_Ord] = ord;			/* Set the LFN order */
}

#endif
#endif



/*-----------------------------------------------------------------------*/
/* Create numbered name                                                  */
/*-----------------------------------------------------------------------*/
#if _USE_LFN
void gen_numname (
	BYTE *dst,			/* Pointer to genartated SFN */
	const BYTE *src,	/* Pointer to source SFN to be modified */
	const WCHAR *lfn,	/* Pointer to LFN */
	WORD num			/* Sequense number */
)
{
	char ns[8];
	int i, j;


	mem_cpy(dst, src, 11);

	if (num > 5) {	/* On many collisions, generate a hash number instead of sequencial number */
		do num = (num >> 1) + (num << 15) + (WORD)*lfn++; while (*lfn);
	}

	/* itoa */
	i = 7;
	do {
		ns[i--] = (num % 10) + '0';
		num /= 10;
	} while (num);
	ns[i] = '~';

	/* Append the number */
	for (j = 0; j < i && dst[j] != ' '; j++) {
		if (IsDBCS1(dst[j])) {
			if (j == i - 1) break;
			j++;
		}
	}
	do {
		dst[j++] = (i < 8) ? ns[i++] : ' ';
	} while (j < 8);
}
#endif




/*-----------------------------------------------------------------------*/
/* Calculate sum of an SFN                                               */
/*-----------------------------------------------------------------------*/
#if _USE_LFN
static
BYTE sum_sfn (
	const BYTE *dir		/* Ptr to directory entry */
)
{
	BYTE sum = 0;
	int n = 11;

	do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n);
	return sum;
}
#endif




/*-----------------------------------------------------------------------*/
/* Find an object in the directory                                       */
/*-----------------------------------------------------------------------*/

static
FRESULT dir_find (
	DIR *dj			/* Pointer to the directory object linked to the file name */
)
{
	FRESULT res;
	BYTE a, c, lfen, ord, sum, *dir;


	res = dir_seek(dj, 0);			/* Rewind directory object */
	if (res != FR_OK) return res;

	ord = sum = 0xFF; lfen = *(dj->fn+11) & 1;
	do {
		res = move_window(dj->fs, dj->sect);
		if (res != FR_OK) break;
		dir = dj->dir;					/* Ptr to the directory entry of current index */
		c = dir[DIR_Name];
		if (c == 0) { res = FR_NO_FILE; break; }	/* Reached to end of table */
		a = dir[DIR_Attr] & AM_MASK;
#if _USE_LFN	/* LFN configuration */
		if (c == 0xE5 || c == '.' || ((a & AM_VOL) && a != AM_LFN)) {	/* An entry without valid data */
			ord = 0xFF;
		} else {
			if (a == AM_LFN) {			/* An LFN entry is found */
				if (dj->lfn) {
					if (c & 0x40) {		/* Is it start of LFN sequence? */
						sum = dir[LDIR_Chksum];
						c &= 0xBF; ord = c;		/* LFN start order */
						dj->lfn_idx = dj->index;
					}
					/* Check LFN validity. Compare LFN if it is out of 8.3 format */
					ord = (c == ord && sum == dir[LDIR_Chksum] && (!lfen || test_lfn(dj->lfn, dir))) ? ord - 1 : 0xFF;
				}
			} else {					/* An SFN entry is found */
				if (ord || sum != sum_sfn(dir)) {	/* Did not LFN match? */
					dj->lfn_idx = 0xFFFF;
					ord = 0xFF;

⌨️ 快捷键说明

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