📄 ff.c
字号:
fs->fsi_sector = bootsect + LD_U16(&fs->win[BPB_FSInfo]); if (diskRead(0, fs->win, fs->fsi_sector, 1) == DRESULT_OK && LD_U16(&fs->win[BS_55AA]) == 0xAA55 && LD_U32(&fs->win[FSI_LeadSig]) == 0x41615252 && LD_U32(&fs->win[FSI_StrucSig]) == 0x61417272) { fs->last_clust = LD_U32(&fs->win[FSI_Nxt_Free]); fs->free_clust = LD_U32(&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 *//*-----------------------------------------------------------------------*/staticFRESULT validate ( /* FR_OK(0): The object is valid, !=0: Not valid */ const FATFS *fs, /* Pointer to the file system object */ U16 id /* id member of the target object to be checked */ ){ if (!fs || fs->id != id) return FR_INVALID_OBJECT; if (diskStatus(fs->drive) & DSTATUS_NOINIT) return FR_NOT_READY; return FR_OK;}/*-------------------------------------------------------------------------- Public Functions --------------------------------------------------------------------------*/const char *f_ferrorlookup (FRESULT f){ unsigned int i; typedef struct errorStrings_s { FRESULT fresult; const char *string; } errorStrings_t; static const errorStrings_t errorStrings [] = { { FR_OK, "OK" }, { FR_NOT_READY, "NOT_READY" }, { FR_NO_FILE, "NO_FILE" }, { FR_NO_PATH, "NO_PATH" }, { FR_INVALID_NAME, "INVALID_NAME" }, { FR_INVALID_DRIVE, "INVALID_DRIVE" }, { FR_DENIED, "DENIED" }, { FR_EXIST, "EXIST" }, { FR_RW_ERROR, "RW_ERROR" }, { FR_WRITE_PROTECTED, "WRITE_PROTECTED" }, { FR_NOT_ENABLED, "NOT_ENABLED" }, { FR_NO_FILESYSTEM, "NO_FILESYSTEM" }, { FR_INVALID_OBJECT, "INVALID_OBJECT" }, { FR_MKFS_ABORTED, "MKFS_ABORTED" }, }; for (i = 0; i < arrsizeof (errorStrings); i++) if (errorStrings [i].fresult == f) return errorStrings [f].string; return "(no err text)";}void f_printerror (FRESULT f){ printf ("rrc=%u %s\n", f, f_ferrorlookup (f));}/*-----------------------------------------------------------------------*//* Mount/Unmount a Locical Drive *//*-----------------------------------------------------------------------*/FRESULT f_mount (U8 drv, FATFS *fs){ 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 */ U8 mode /* Access mode and file open mode flags */ ){ FRESULT res; U8 *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, (U8)(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)) { U32 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 = ((U32)LD_U16(&dir[DIR_FstClusHI]) << 16) | LD_U16(&dir[DIR_FstClusLO]); /* Get start cluster */ ST_U16(&dir[DIR_FstClusHI], 0); /* cluster = 0 */ ST_U16(&dir[DIR_FstClusLO], 0); ST_U32(&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_U32(&dir[DIR_WrtTime], ps); /* Updated time */ ST_U32(&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 */ ((U32)LD_U16(&dir[DIR_FstClusHI]) << 16) | LD_U16(&dir[DIR_FstClusLO]); fp->fsize = LD_U32(&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 */ U16 btr, /* Number of bytes to read */ U16 *br /* Pointer to number of bytes read */ ){ U32 clust, sect, remain; U16 rcnt; U8 cc, *rbuff = buff; FRESULT res; FATFS *fs = fp->fs; *br = 0; res = validate(fs, fp->id); /* Check validity of the object */ if (res) 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 = (U16)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 (diskWrite(fs->drive, fp->buffer, fp->curr_sect, 1) != DRESULT_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 (diskRead(fs->drive, rbuff, sect, cc) != DRESULT_OK) goto fr_error; fp->sect_clust -= cc - 1; fp->curr_sect += cc - 1; rcnt = cc * S_SIZ; continue; } if (diskRead(fs->drive, fp->buffer, sect, 1) != DRESULT_OK) /* Load the sector into file I/O buffer */ goto fr_error; } rcnt = S_SIZ - ((U16)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 */ U16 btw, /* Number of bytes to write */ U16 *bw /* Pointer to number of bytes written */ ){ U32 clust, sect; U16 wcnt; U8 cc; FRESULT res; const U8 *wbuff = buff; FATFS *fs = fp->fs; *bw = 0; res = validate(fs, fp->id); /* Check validity of the object */ if (res) 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 (diskWrite(fs->drive, fp->buffer, fp->curr_sect, 1) != DRESULT_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 (diskWrite(fs->drive, wbuff, sect, cc) != DRESULT_OK) goto fw_error; fp->sect_clust -= 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 */ diskRead(fs->drive, fp->buffer, sect, 1) != DRESULT_OK) goto fw_error; } wcnt = S_SIZ - ((U16)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 between File and Disk *//*-----------------------------------------------------------------------*/FRESULT f_sync ( FIL *fp /* Pointer to the file object */ ){ U32 tim; U8 *dir; FRESULT res;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -