📄 main.i
字号:
do {
if (!move_window(dirobj->sect)) return FR_RW_ERROR;
dptr = &fs->win[(dirobj->index & 15) * 32]; /* Pointer to the directory entry */
c = dptr[0];
if (c == 0 || c == 0xE5) { /* Found an empty entry! */
*dir = dptr; return FR_OK;
}
} while (next_dir_entry(dirobj)); /* Next directory pointer */
/* Reached to end of the directory table */
/* Abort when static table or could not stretch dynamic table */
if (!clust || !(clust = create_chain(dirobj->clust))) return FR_DENIED;
if (clust == 1 || !move_window(0)) return FR_RW_ERROR;
fs->winsect = sector = clust2sect(clust); /* Cleanup the expanded table */
memset(fs->win, 0, 512);
for (n = fs->sects_clust; n; n--) {
if (disk_write(0, fs->win, sector, 1) != RES_OK)
return FR_RW_ERROR;
sector++;
}
fs->winflag = 1;
*dir = fs->win;
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* Load boot record and check if it is a 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 or error */
DWORD sect /* Sector# to check if it is a FAT boot record or not */
)
{
FATFS *fs = FatFs;
if (disk_read(0, fs->win, sect, 1) != RES_OK) /* Load boot record */
return 2;
if (((WORD)(((WORD)*(volatile BYTE*)((&fs->win[510])+1)<<8)|(WORD)*(volatile BYTE*)(&fs->win[510]))) != 0xAA55) /* Check record signature */
return 2;
if (!memcmpf(&fs->win[54], "FAT", 3)) /* Check FAT signature */
return 0;
if (!memcmpf(&fs->win[82], "FAT32", 5) && !(fs->win[40] & 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) */
char **path, /* Pointer to pointer to the path name (drive number) */
BYTE chk_wp /* !=0: Check media write protection for write access */
)
{
BYTE fmt;
DSTATUS stat;
DWORD bootsect, fatsize, totalsect, maxclust;
// const char *p = *path;
char *p = *path;
FATFS *fs = FatFs;
while (*p == ' ') p++; /* Strip leading spaces */
if (*p == '/') p++; /* Strip heading slash */
*path = p; /* Return pointer to the path name */
/* Is the file system object registered? */
if (!fs) return FR_NOT_ENABLED;
/* Chekck if the logical drive has been mounted or not */
if (fs->fs_type) {
stat = disk_status(0);
if (!(stat & 0x01 )) { /* If the physical drive is kept initialized */
if (chk_wp && (stat & 0x04 )) /* Check write protection if needed */
return FR_WRITE_PROTECTED;
return FR_OK; /* The file system object is valid */
}
}
/* The logical drive has not been mounted, following code attempts to mount the logical drive */
memset(fs, 0, sizeof(FATFS)); /* Clean-up the file system object */
stat = disk_initialize(0); /* Initialize low level disk I/O layer */
if (stat & 0x01 ) /* Check if the drive is ready */
return FR_NOT_READY;
if (chk_wp && (stat & 0x04 )) /* Check write protection if needed */
return FR_WRITE_PROTECTED;
/* Search FAT partition on the drive */
fmt = check_fs(bootsect = 0); /* Check sector 0 as an SFD format */
if (fmt == 1) { /* Not a FAT boot record, it may be patitioned */
/* Check a partition listed in top of the partition table */
if (fs->win[446+4]) { /* Is the 1st partition existing? */
bootsect = ((DWORD)(((DWORD)*(volatile BYTE*)((&fs->win[446+8])+3)<<24)|((DWORD)*(volatile BYTE*)((&fs->win[446+8])+2)<<16)|((WORD)*(volatile BYTE*)((&fs->win[446+8])+1)<<8)|*(volatile BYTE*)(&fs->win[446+8]))); /* Partition offset in LBA */
fmt = check_fs(bootsect); /* Check the partition */
}
}
if (fmt || ((WORD)(((WORD)*(volatile BYTE*)((&fs->win[11])+1)<<8)|(WORD)*(volatile BYTE*)(&fs->win[11]))) != 512) /* No valid FAT patition is found */
return FR_NO_FILESYSTEM;
/* Initialize the file system object */
fatsize = ((WORD)(((WORD)*(volatile BYTE*)((&fs->win[22])+1)<<8)|(WORD)*(volatile BYTE*)(&fs->win[22]))); /* Number of sectors per FAT */
if (!fatsize) fatsize = ((DWORD)(((DWORD)*(volatile BYTE*)((&fs->win[36])+3)<<24)|((DWORD)*(volatile BYTE*)((&fs->win[36])+2)<<16)|((WORD)*(volatile BYTE*)((&fs->win[36])+1)<<8)|*(volatile BYTE*)(&fs->win[36])));
fs->sects_fat = (CLUST)fatsize;
fs->n_fats = fs->win[16]; /* Number of FAT copies */
fatsize *= fs->n_fats; /* (Number of sectors in FAT area) */
fs->fatbase = bootsect + ((WORD)(((WORD)*(volatile BYTE*)((&fs->win[14])+1)<<8)|(WORD)*(volatile BYTE*)(&fs->win[14]))); /* FAT start sector (lba) */
fs->sects_clust = fs->win[13]; /* Number of sectors per cluster */
fs->n_rootdir = ((WORD)(((WORD)*(volatile BYTE*)((&fs->win[17])+1)<<8)|(WORD)*(volatile BYTE*)(&fs->win[17]))); /* Nmuber of root directory entries */
totalsect = ((WORD)(((WORD)*(volatile BYTE*)((&fs->win[19])+1)<<8)|(WORD)*(volatile BYTE*)(&fs->win[19]))); /* Number of sectors on the file system */
if (!totalsect) totalsect = ((DWORD)(((DWORD)*(volatile BYTE*)((&fs->win[32])+3)<<24)|((DWORD)*(volatile BYTE*)((&fs->win[32])+2)<<16)|((WORD)*(volatile BYTE*)((&fs->win[32])+1)<<8)|*(volatile BYTE*)(&fs->win[32])));
fs->max_clust = maxclust = (totalsect /* Last cluster# + 1 */
- ((WORD)(((WORD)*(volatile BYTE*)((&fs->win[14])+1)<<8)|(WORD)*(volatile BYTE*)(&fs->win[14]))) - fatsize - fs->n_rootdir / 16
) / fs->sects_clust + 2;
fmt = 1; /* Determine the FAT sub type */
if (maxclust > 0xFF7) fmt = 2;
if (maxclust > 0xFFF7)
fmt = 3;
if (fmt == 3)
fs->dirbase = ((DWORD)(((DWORD)*(volatile BYTE*)((&fs->win[44])+3)<<24)|((DWORD)*(volatile BYTE*)((&fs->win[44])+2)<<16)|((WORD)*(volatile BYTE*)((&fs->win[44])+1)<<8)|*(volatile BYTE*)(&fs->win[44]))); /* Root directory start cluster */
else
fs->dirbase = fs->fatbase + fatsize; /* Root directory start sector (lba) */
fs->database = fs->fatbase + fatsize + fs->n_rootdir / 16; /* Data start sector (lba) */
fs->fs_type = fmt; /* FAT sub-type */
fs->free_clust = (CLUST)0xFFFFFFFF;
/* Load fsinfo sector if needed */
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->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 id 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(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)*/)
{
FATFS *fsobj;
if (drv) return FR_INVALID_DRIVE;
fsobj = FatFs;
FatFs = 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 = FatFs;
fp->fs = 0;
mode &= (0x01|0x02|0x08|0x10|0x04);
res = auto_mount(&path, (BYTE)(mode & (0x02|0x08|0x10|0x04)));
if (res != FR_OK) return res;
/* Trace the file path */
res = trace_path(&dirobj, 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(&dirobj, &dir);
if (res != FR_OK) return res;
memset(dir, 0, 32); /* Initialize the new entry */
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 == 0 || (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 */
fs->winflag = 1;
dw = fs->winsect; /* Remove the cluster chain */
if (!remove_chain(rs) || !move_window(dw))
return FR_RW_ERROR;
fs->last_clust = rs - 1; /* Reuse the cluster hole */
}
}
if (mode & 0x08) {
dir[11] = 0x20 ; /* New attribute */
dw = get_fattime();
*(volatile BYTE*)(&dir[22])=(BYTE)(dw); *(volatile BYTE*)((&dir[22])+1)=(BYTE)((WORD)(dw)>>8); *(volatile BYTE*)((&dir[22])+2)=(BYTE)((DWORD)(dw)>>16); *(volatile BYTE*)((&dir[22])+3)=(BYTE)((DWORD)(dw)>>24); /* Updated time */
*(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 */
fs->winflag = 1;
}
}
/* Open a File */
else {
if (res != FR_OK) return res; /* Trace failed */
if (dir == 0 || (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 = 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; /* 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 sect, remain;
UINT rcnt, cc;
CLUST clust;
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 & 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 = (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 % 512) == 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(fp->curr_clust);
if (clust < 2 || clust >= fs->max_clust)
goto fr_error;
fp->curr_clust = clust; /* Current cluster */
sect = clust2sect(clust); /* Get current sector */
fp->sect_clust = fs->sects_clust; /* Re-initialize the left sector counter */
}
fp->curr_sect = sect; /* Update current sector */
cc = btr / 512; /* When left bytes >= 512, */
if (cc) { /* Read maximum contiguous sectors directly */
if (cc > fp->sect_clust) cc = fp->sect_clust;
if (disk_read(0, rbuff, sect, (BYTE)cc) != RES_OK)
goto fr_error;
fp->sect_clust -= (BYTE)(cc - 1);
fp->curr_sect += cc - 1;
rcnt = cc * 512;
continue;
}
}
if (!move_window(fp->curr_sect)) goto fr_error; /* Move sector window */
rcnt = 512 - (WORD)(fp->fptr % 512); /* Copy fractional bytes from sector window */
if (rcnt > btr) rcnt = btr;
memcpy(rbuff, &fs->win[(WORD)fp->fptr % 512], rcnt);
}
return FR_OK;
fr_error: /* Abort this function 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 byte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -