📄 ff.c
字号:
return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
}
static
int enq_lock ( /* Check if an entry is available for a new file */
FATFS* fs /* File system object */
)
{
UINT i;
for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
return (i == _FS_SHARE) ? 0 : 1;
}
static
UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */
DIR* dj, /* Directory object pointing the file to register or increment */
int acc /* Desired access mode (0:Read, !0:Write) */
)
{
UINT i;
for (i = 0; i < _FS_SHARE; i++) { /* Find the file */
if (Files[i].fs == dj->fs &&
Files[i].clu == dj->sclust &&
Files[i].idx == dj->index) break;
}
if (i == _FS_SHARE) { /* Not opened. Register it as new. */
for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
if (i == _FS_SHARE) return 0; /* No space to register (int err) */
Files[i].fs = dj->fs;
Files[i].clu = dj->sclust;
Files[i].idx = dj->index;
Files[i].ctr = 0;
}
if (acc && Files[i].ctr) return 0; /* Access violation (int err) */
Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */
return i + 1;
}
static
FRESULT dec_lock ( /* Decrement file open counter */
UINT i /* Semaphore index */
)
{
WORD n;
FRESULT res;
if (--i < _FS_SHARE) {
n = Files[i].ctr;
if (n == 0x100) n = 0;
if (n) n--;
Files[i].ctr = n;
if (!n) Files[i].fs = 0;
res = FR_OK;
} else {
res = FR_INT_ERR;
}
return res;
}
static
void clear_lock ( /* Clear lock entries of the volume */
FATFS *fs
)
{
UINT i;
for (i = 0; i < _FS_SHARE; i++) {
if (Files[i].fs == fs) Files[i].fs = 0;
}
}
#endif
/*-----------------------------------------------------------------------*/
/* Change window offset */
/*-----------------------------------------------------------------------*/
static
FRESULT move_window (
FATFS *fs, /* File system object */
DWORD sector /* Sector number to make appearance in the fs->win[] */
) /* Move to zero only writes back dirty window */
{
DWORD wsect;
wsect = fs->winsect;
if (wsect != sector) { /* Changed current window */
#if !_FS_READONLY
if (fs->wflag) { /* Write back dirty window if needed */
if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK)
return FR_DISK_ERR;
fs->wflag = 0;
if (wsect < (fs->fatbase + fs->fsize)) { /* In FAT area */
BYTE nf;
for (nf = fs->n_fats; nf > 1; nf--) { /* Reflect the change to all FAT copies */
wsect += fs->fsize;
disk_write(fs->drv, fs->win, wsect, 1);
}
}
}
#endif
if (sector) {
if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK)
return FR_DISK_ERR;
fs->winsect = sector;
}
}
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* Clean-up cached data */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
static
FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */
FATFS *fs /* File system object */
)
{
FRESULT res;
res = move_window(fs, 0);
if (res == FR_OK) {
/* Update FSInfo sector if needed */
if (fs->fs_type == FS_FAT32 && fs->fsi_flag) {
fs->winsect = 0;
mem_set(fs->win, 0, 512);
ST_WORD(fs->win+BS_55AA, 0xAA55);
ST_DWORD(fs->win+FSI_LeadSig, 0x41615252);
ST_DWORD(fs->win+FSI_StrucSig, 0x61417272);
ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust);
ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust);
disk_write(fs->drv, fs->win, fs->fsi_sector, 1);
fs->fsi_flag = 0;
}
/* Make sure that no pending write process in the physical drive */
if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK)
res = FR_DISK_ERR;
}
return res;
}
#endif
/*-----------------------------------------------------------------------*/
/* Get sector# from cluster# */
/*-----------------------------------------------------------------------*/
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->n_fatent - 2)) return 0; /* Invalid cluster# */
return clst * fs->csize + fs->database;
}
/*-----------------------------------------------------------------------*/
/* FAT access - Read value of a FAT entry */
/*-----------------------------------------------------------------------*/
DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */
FATFS *fs, /* File system object */
DWORD clst /* Cluster# to get the link information */
)
{
UINT wc, bc;
BYTE *p;
if (clst < 2 || clst >= fs->n_fatent) /* Chack range */
return 1;
switch (fs->fs_type) {
case FS_FAT12 :
bc = (UINT)clst; bc += bc / 2;
if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
wc = fs->win[bc % SS(fs)]; bc++;
if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
wc |= fs->win[bc % SS(fs)] << 8;
return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
case FS_FAT16 :
if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break;
p = &fs->win[clst * 2 % SS(fs)];
return LD_WORD(p);
case FS_FAT32 :
if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break;
p = &fs->win[clst * 4 % SS(fs)];
return LD_DWORD(p) & 0x0FFFFFFF;
}
return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */
}
/*-----------------------------------------------------------------------*/
/* FAT access - Change value of a FAT entry */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
FRESULT put_fat (
FATFS *fs, /* File system object */
DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */
DWORD val /* New value to mark the cluster */
)
{
UINT bc;
BYTE *p;
FRESULT res;
if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
res = FR_INT_ERR;
} else {
switch (fs->fs_type) {
case FS_FAT12 :
bc = clst; bc += bc / 2;
res = move_window(fs, fs->fatbase + (bc / SS(fs)));
if (res != FR_OK) break;
p = &fs->win[bc % SS(fs)];
*p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
bc++;
fs->wflag = 1;
res = move_window(fs, fs->fatbase + (bc / SS(fs)));
if (res != FR_OK) break;
p = &fs->win[bc % SS(fs)];
*p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
break;
case FS_FAT16 :
res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
if (res != FR_OK) break;
p = &fs->win[clst * 2 % SS(fs)];
ST_WORD(p, (WORD)val);
break;
case FS_FAT32 :
res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
if (res != FR_OK) break;
p = &fs->win[clst * 4 % SS(fs)];
val |= LD_DWORD(p) & 0xF0000000;
ST_DWORD(p, val);
break;
default :
res = FR_INT_ERR;
}
fs->wflag = 1;
}
return res;
}
#endif /* !_FS_READONLY */
/*-----------------------------------------------------------------------*/
/* FAT handling - Remove a cluster chain */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
static
FRESULT remove_chain (
FATFS *fs, /* File system object */
DWORD clst /* Cluster# to remove a chain from */
)
{
FRESULT res;
DWORD nxt;
#if _USE_ERASE
DWORD scl = clst, ecl = clst, resion[2];
#endif
if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
res = FR_INT_ERR;
} else {
res = FR_OK;
while (clst < fs->n_fatent) { /* Not a last link? */
nxt = get_fat(fs, clst); /* Get cluster status */
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_fat(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;
}
#if _USE_ERASE
if (ecl + 1 == nxt) { /* Next cluster is contiguous */
ecl = nxt;
} else { /* End of contiguous clusters */
resion[0] = clust2sect(fs, scl); /* Start sector */
resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */
scl = ecl = nxt;
}
#endif
clst = nxt; /* Next cluster */
}
}
return res;
}
#endif
/*-----------------------------------------------------------------------*/
/* FAT handling - 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;
FRESULT res;
if (clst == 0) { /* Create a new chain */
scl = fs->last_clust; /* Get suggested start point */
if (!scl || scl >= fs->n_fatent) scl = 1;
}
else { /* Stretch the current chain */
cs = get_fat(fs, clst); /* Check the cluster status */
if (cs < 2) return 1; /* It is an invalid cluster */
if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */
scl = clst;
}
ncl = scl; /* Start cluster */
for (;;) {
ncl++; /* Next cluster */
if (ncl >= fs->n_fatent) { /* Wrap around */
ncl = 2;
if (ncl > scl) return 0; /* No free cluster */
}
cs = get_fat(fs, ncl); /* Get the cluster status */
if (cs == 0) break; /* Found a free cluster */
if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */
return cs;
if (ncl == scl) return 0; /* No free cluster */
}
res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */
if (res == FR_OK && clst != 0) {
res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */
}
if (res == FR_OK) {
fs->last_clust = ncl; /* Update FSINFO */
if (fs->free_clust != 0xFFFFFFFF) {
fs->free_clust--;
fs->fsi_flag = 1;
}
} else {
ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
}
return ncl; /* Return new cluster number or error code */
}
#endif /* !_FS_READONLY */
/*-----------------------------------------------------------------------*/
/* Directory handling - Set directory index */
/*-----------------------------------------------------------------------*/
static
FRESULT dir_sdi (
DIR *dj, /* Pointer to directory object */
WORD idx /* Directory index number */
)
{
DWORD clst;
WORD ic;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -