📄 tff.i
字号:
if (fmt == 3) {
fs->fsi_sector = bootsect + (WORD)(((WORD)*(volatile BYTE*)((&fs->win[48])+1)<<8)|(WORD)*(volatile BYTE*)(&fs->win[48]));
if (disk_read(0, fs->win, fs->fsi_sector, 1) == RES_OK &&
(WORD)(((WORD)*(volatile BYTE*)((&fs->win[510])+1)<<8)|(WORD)*(volatile BYTE*)(&fs->win[510])) == 0xAA55 &&
(DWORD)(((DWORD)*(volatile BYTE*)((&fs->win[0])+3)<<24)|((DWORD)*(volatile BYTE*)((&fs->win[0])+2)<<16)|((WORD)*(volatile BYTE*)((&fs->win[0])+1)<<8)|*(volatile BYTE*)(&fs->win[0])) == 0x41615252 &&
(DWORD)(((DWORD)*(volatile BYTE*)((&fs->win[484])+3)<<24)|((DWORD)*(volatile BYTE*)((&fs->win[484])+2)<<16)|((WORD)*(volatile BYTE*)((&fs->win[484])+1)<<8)|*(volatile BYTE*)(&fs->win[484])) == 0x61417272) {
fs->last_clust = (DWORD)(((DWORD)*(volatile BYTE*)((&fs->win[492])+3)<<24)|((DWORD)*(volatile BYTE*)((&fs->win[492])+2)<<16)|((WORD)*(volatile BYTE*)((&fs->win[492])+1)<<8)|*(volatile BYTE*)(&fs->win[492]));
fs->free_clust = (DWORD)(((DWORD)*(volatile BYTE*)((&fs->win[488])+3)<<24)|((DWORD)*(volatile BYTE*)((&fs->win[488])+2)<<16)|((WORD)*(volatile BYTE*)((&fs->win[488])+1)<<8)|*(volatile BYTE*)(&fs->win[488]));
}
}
fs->fs_type = fmt; /* FAT syb-type */
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: Invalid */
const 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;
if (disk_status(0) & 0x01 )
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)*/
)
{
if (drv) return FR_INVALID_DRIVE;
if (FatFs) FatFs->fs_type = 0; /* Clear old object */
FatFs = fs; /* Register and clear new object */
if (fs) fs->fs_type = 0;
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;
BYTE *dir;
char fn[8+3+1];
fp->fs = 0; /* Clear file object */
mode &= (0x01|0x02|0x08|0x10|0x04);
res = auto_mount(&path, (BYTE)(mode & (0x02|0x08|0x10|0x04)));
if (res != FR_OK) return res;
res = trace_path(&dj, fn, path, &dir); /* Trace the file path */
/* Create or Open a File */
if (mode & (0x08|0x10|0x04)) {
CLUST rs;
DWORD dw;
if (res != FR_OK) { /* No file, create new */
if (res != FR_NO_FILE) return res;
res = reserve_direntry(&dj, &dir);
if (res != FR_OK) return res;
memset(dir, 0, 32); /* Initialize the new entry with open name */
memcpy(&dir[0], fn, 8+3);
dir[12] = fn[11];
mode |= 0x08;
}
else { /* Any object is already existing */
if (mode & 0x04) /* Cannot create new */
return FR_EXIST;
if (!dir || (dir[11] & (0x01 |0x10 ))) /* Cannot overwrite (R/O or DIR) */
return FR_DENIED;
if (mode & 0x08) { /* Resize it to zero */
rs = ((DWORD)((WORD)(((WORD)*(volatile BYTE*)((&dir[20])+1)<<8)|(WORD)*(volatile BYTE*)(&dir[20]))) << 16) | (WORD)(((WORD)*(volatile BYTE*)((&dir[26])+1)<<8)|(WORD)*(volatile BYTE*)(&dir[26]));
*(volatile BYTE*)(&dir[20])=(BYTE)(0); *(volatile BYTE*)((&dir[20])+1)=(BYTE)((WORD)(0)>>8);
*(volatile BYTE*)(&dir[26])=(BYTE)(0); *(volatile BYTE*)((&dir[26])+1)=(BYTE)((WORD)(0)>>8); /* cluster = 0 */
*(volatile BYTE*)(&dir[28])=(BYTE)(0); *(volatile BYTE*)((&dir[28])+1)=(BYTE)((WORD)(0)>>8); *(volatile BYTE*)((&dir[28])+2)=(BYTE)((DWORD)(0)>>16); *(volatile BYTE*)((&dir[28])+3)=(BYTE)((DWORD)(0)>>24); /* size = 0 */
dj.fs->winflag = 1;
dw = dj.fs->winsect; /* Remove the cluster chain */
if (!remove_chain(rs) || !move_window(dw))
return FR_RW_ERROR;
dj.fs->last_clust = rs - 1; /* Reuse the cluster hole */
}
}
if (mode & 0x08) {
dir[11] = 0; /* Reset attribute */
dw = get_fattime();
*(volatile BYTE*)(&dir[14])=(BYTE)(dw); *(volatile BYTE*)((&dir[14])+1)=(BYTE)((WORD)(dw)>>8); *(volatile BYTE*)((&dir[14])+2)=(BYTE)((DWORD)(dw)>>16); *(volatile BYTE*)((&dir[14])+3)=(BYTE)((DWORD)(dw)>>24); /* Created time */
dj.fs->winflag = 1;
mode |= 0x20; /* Set file changed flag */
}
}
/* Open an existing file */
else {
if (res != FR_OK) return res; /* Trace failed */
if (!dir || (dir[11] & 0x10 )) /* It is a directory */
return FR_NO_FILE;
if ((mode & 0x02) && (dir[11] & 0x01 )) /* R/O violation */
return FR_DENIED;
}
fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
fp->dir_ptr = dir;
fp->flag = mode; /* File access mode */
fp->org_clust = /* File start cluster */
((DWORD)((WORD)(((WORD)*(volatile BYTE*)((&dir[20])+1)<<8)|(WORD)*(volatile BYTE*)(&dir[20]))) << 16) |
(WORD)(((WORD)*(volatile BYTE*)((&dir[26])+1)<<8)|(WORD)*(volatile BYTE*)(&dir[26]));
fp->fsize = (DWORD)(((DWORD)*(volatile BYTE*)((&dir[28])+3)<<24)|((DWORD)*(volatile BYTE*)((&dir[28])+2)<<16)|((WORD)*(volatile BYTE*)((&dir[28])+1)<<8)|*(volatile BYTE*)(&dir[28])); /* File size */
fp->fptr = 0; fp->csect = 255; /* File pointer */
fp->fs = dj.fs; fp->id = dj.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 */
)
{
FRESULT res;
DWORD sect, remain;
UINT rcnt, cc;
CLUST clust;
BYTE *rbuff = buff;
*br = 0;
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res != FR_OK) return res;
if (fp->flag & 0x80) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & 0x01)) return FR_DENIED; /* Check access mode */
remain = fp->fsize - fp->fptr;
if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
for ( ; btr; /* Repeat until all data transferred */
rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
if ((fp->fptr % 512U) == 0) { /* On the sector boundary? */
if (fp->csect >= fp->fs->csize) { /* On the cluster boundary? */
clust = (fp->fptr == 0) ? /* On the top of the file? */
fp->org_clust : get_cluster(fp->curr_clust);
if (clust < 2 || clust >= fp->fs->max_clust) goto fr_error;
fp->curr_clust = clust; /* Update current cluster */
fp->csect = 0; /* Reset sector address in the cluster */
}
sect = clust2sect(fp->curr_clust) + fp->csect; /* Get current sector */
cc = btr / 512U; /* When remaining bytes >= sector size, */
if (cc) { /* Read maximum contiguous sectors directly */
if (fp->csect + cc > fp->fs->csize) /* Clip at cluster boundary */
cc = fp->fs->csize - fp->csect;
if (disk_read(0, rbuff, sect, (BYTE)cc) != RES_OK)
goto fr_error;
fp->csect += (BYTE)cc; /* Next sector address in the cluster */
rcnt = 512U * cc; /* Number of bytes transferred */
continue;
}
fp->csect++; /* Next sector address in the cluster */
}
sect = clust2sect(fp->curr_clust) + fp->csect - 1; /* Get current sector */
if (!move_window(sect)) goto fr_error; /* Move sector window */
rcnt = 512U - (fp->fptr % 512U); /* Get partial sector from sector window */
if (rcnt > btr) rcnt = btr;
memcpy(rbuff, &fp->fs->win[fp->fptr % 512U], rcnt);
}
return FR_OK;
fr_error: /* Abort this file due to an unrecoverable error */
fp->flag |= 0x80;
return FR_RW_ERROR;
}
/*-----------------------------------------------------------------------*/
/* 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 */
)
{
FRESULT res;
DWORD sect;
UINT wcnt, cc;
CLUST clust;
/*const*/ BYTE *wbuff = buff;
*bw = 0;
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res != FR_OK) return res;
if (fp->flag & 0x80) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & 0x02)) 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 % 512U) == 0) { /* On the sector boundary? */
if (fp->csect >= fp->fs->csize) { /* On the cluster boundary? */
if (fp->fptr == 0) { /* On the top of the file? */
clust = fp->org_clust; /* Follow from the origin */
if (clust == 0) /* When there is no cluster chain, */
fp->org_clust = clust = create_chain(0); /* Create a new cluster chain */
} else { /* Middle or end of the file */
clust = create_chain(fp->curr_clust); /* Trace or streach cluster chain */
}
if (clust == 0) break; /* Could not allocate a new cluster (disk full) */
if (clust == 1 || clust >= fp->fs->max_clust) goto fw_error;
fp->curr_clust = clust; /* Update current cluster */
fp->csect = 0; /* Reset sector address in the cluster */
}
sect = clust2sect(fp->curr_clust) + fp->csect; /* Get current sector */
cc = btw / 512U; /* When remaining bytes >= sector size, */
if (cc) { /* Write maximum contiguous sectors directly */
if (fp->csect + cc > fp->fs->csize) /* Clip at cluster boundary */
cc = fp->fs->csize - fp->csect;
if (disk_write(0, wbuff, sect, (BYTE)cc) != RES_OK)
goto fw_error;
fp->csect += (BYTE)cc; /* Next sector address in the cluster */
wcnt = 512U * cc; /* Number of bytes transferred */
continue;
}
if (fp->fptr >= fp->fsize) { /* Flush R/W window without reading if needed */
if (!move_window(0)) goto fw_error;
fp->fs->winsect = sect;
}
fp->csect++; /* Next sector address in the cluster */
}
sect = clust2sect(fp->curr_clust) + fp->csect - 1; /* Get current sector */
if (!move_window(sect)) goto fw_error; /* Move sector window */
wcnt = 512U - (fp->fptr % 512U); /* Put partial sector into sector window */
if (wcnt > btw) wcnt = btw;
memcpy(&fp->fs->win[fp->fptr % 512U], wbuff, wcnt);
fp->fs->winflag = 1;
}
if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */
fp->flag |= 0x20; /* Set file changed flag */
return res;
fw_error: /* Abort this file due to an unrecoverable error */
fp->flag |= 0x80;
return FR_RW_ERROR;
}
/*-----------------------------------------------------------------------*/
/* Synchronize the file object */
/*-----------------------------------------------------------------------*/
FRESULT f_sync (
FIL *fp /* Pointer to the file object */
)
{
FRESULT res;
DWORD tim;
BYTE *dir;
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & 0x20) { /* Has the file been written? */
/* Update the directory entry */
if (!move_window(fp->dir_sect))
return FR_RW_ERROR;
dir = fp->dir_ptr;
dir[11] |= 0x20 ; /* Set archive bit */
*(volatile BYTE*)(&dir[28])=(BYTE)(fp->fsize); *(volatile BYTE*)((&dir[28])+1)=(BYTE)((WORD)(fp->fsize)>>8); *(volatile BYTE*)((&dir[28])+2)=(BYTE)((DWORD)(fp->fsize)>>16); *(volatile BYTE*)((&dir[28])+3)=(BYTE)((DWORD)(fp->fsize)>>24); /* Update file size */
*(volatile BYTE*)(&dir[26])=(BYTE)(fp->org_clust); *(volatile BYTE*)((&dir[26])+1)=(BYTE)((WORD)(fp->org_clust)>>8); /* Update start cluster */
*(volatile BYTE*)(&dir[20])=(BYTE)(fp->org_clust >> 16); *(volatile BYTE*)((&dir[20])+1)=(BYTE)((WORD)(fp->org_clust >> 16)>>8);
tim = get_fattime(); /* Updated time */
*(volatile BYTE*)(&dir[22])=(BYTE)(tim); *(volatile BYTE*)((&dir[22])+1)=(BYTE)((WORD)(tim)>>8); *(volatile BYTE*)((&dir[22])+2)=(BYTE)((DWORD)(tim)>>16); *(volatile BYTE*)((&dir[22])+3)=(BYTE)((DWORD)(tim)>>24);
fp->flag &= (BYTE)~0x20;
res = sync();
}
}
return res;
}
/*-----------------------------------------------------------------------*/
/* Close File */
/*-----------------------------------------------------------------------*/
FRESULT f_close (
FIL *fp /* Pointer to the file object to be closed */
)
{
FRESULT res;
res = f_sync(fp);
if (res == FR_OK) fp->fs = 0;
return res;
}
/*-----------------------------------------------------------------------*/
/* Seek File R/W Pointer */
/*-----------------------------------------------------------------------*/
FRESULT f_lseek (
FIL *fp, /* Pointer to the file object */
DWORD ofs /* File pointer from top of file */
)
{
FRESULT res;
CLUST clust;
DWORD csize, ifptr;
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res != FR_OK) return res;
if (fp->flag & 0x80) return FR_RW_ERROR;
if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */
&& !(fp->flag & 0x02)
) ofs = fp->fsize;
ifptr = fp->fptr;
fp->fptr = 0; fp->csect = 255;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -