📄 ff.c
字号:
//// $Id: ff.c 42 2008-10-04 18:40:36Z jcw $// $Revision: 42 $// $Author: jcw $// $Date: 2008-10-04 14:40:36 -0400 (Sat, 04 Oct 2008) $// $HeadURL: http://tinymicros.com/svn_public/arm/lpc2148_demo/trunk/fatfs/ff.c $///*--------------------------------------------------------------------------/ / FatFs - FAT file system module R0.04b (C)ChaN, 2007 /---------------------------------------------------------------------------/ / The FatFs module is an experimenal project to implement FAT file system to / cheap microcontrollers. This is a free software and is opened for education, / research and development under license policy of following trems. / / Copyright (C) 2007, ChaN, all right reserved. / / * The FatFs module is a free software and there is no warranty. / * You can use, modify and/or redistribute it for personal, non-profit or / profit use without any restriction under your responsibility. / * Redistributions of source code must retain the above copyright notice. / /---------------------------------------------------------------------------/ / Feb 26, 2006 R0.00 Prototype. / Apr 29, 2006 R0.01 First stable version. / Jun 01, 2006 R0.02 Added FAT12 support. / Removed unbuffered mode. / Fixed a problem on small (<32M) patition. / Jun 10, 2006 R0.02a Added a configuration option (_FS_MINIMUM). / Sep 22, 2006 R0.03 Added f_rename(). / Changed option _FS_MINIMUM to _FS_MINIMIZE. / Dec 11, 2006 R0.03a Improved cluster scan algolithm to write files fast. / Fixed f_mkdir() creates incorrect directory on FAT32. / Feb 04, 2007 R0.04 Supported multiple drive system. / Changed some interfaces for multiple drive system. / Changed f_mountdrv() to f_mount(). / Added f_mkfs(). / Apr 01, 2007 R0.04a Supported multiple partitions on a plysical drive. / Added a capability of extending file size to f_lseek(). / Added minimization level 3. / Fixed an endian sensitive code in f_mkfs(). / May 05, 2007 R0.04b Added a configuration option _USE_NTFLAG. / Added FSInfo support. / Fixed DBCS name can result FR_INVALID_NAME. / Fixed short seek (<= csize) collapses the file object. /---------------------------------------------------------------------------*/#include <stdio.h> // ####include <string.h>#include "ff.h" /* FatFs declarations */#include "disk.h" /* Include file for user provided disk functions *//*-------------------------------------------------------------------------- Module Private Functions ---------------------------------------------------------------------------*/static FATFS *FatFs [_DRIVES]; /* Pointer to the file system objects (logical drives) */static U16 fsid; /* File system mount ID *//*-----------------------------------------------------------------------*//* Change window offset *//*-----------------------------------------------------------------------*/staticBOOL move_window ( /* TRUE: successful, FALSE: failed */ FATFS *fs, /* File system object */ U32 sector /* Sector number to make apperance in the fs->win[] */ ) /* Move to zero only writes back dirty window */{ U32 wsect; wsect = fs->winsect; if (wsect != sector) { /* Changed current window */#if _FS_READONLY == 0 U8 n; if (fs->winflag) { /* Write back dirty window if needed */ if (diskWrite(fs->drive, fs->win, wsect, 1) != DRESULT_OK) return FALSE; fs->winflag = 0; if (wsect < (fs->fatbase + fs->sects_fat)) { /* In FAT area */ for (n = fs->n_fats; n >= 2; n--) { /* Refrect the change to FAT copy */ wsect += fs->sects_fat; diskWrite(fs->drive, fs->win, wsect, 1); } } }#endif if (sector) { if (diskRead(fs->drive, fs->win, sector, 1) != DRESULT_OK) return FALSE; fs->winsect = sector; } } return TRUE;}/*-----------------------------------------------------------------------*//* Clean-up cached data *//*-----------------------------------------------------------------------*/#if _FS_READONLY == 0staticFRESULT sync ( /* FR_OK: successful, FR_RW_ERROR: failed */ FATFS *fs /* File system object */ ){ fs->winflag = 1; if (!move_window(fs, 0)) return FR_RW_ERROR;#if _USE_FSINFO if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { /* Update FSInfo sector if needed */ fs->winsect = 0; memset(fs->win, 0, 512); ST_U16(&fs->win[BS_55AA], 0xAA55); ST_U32(&fs->win[FSI_LeadSig], 0x41615252); ST_U32(&fs->win[FSI_StrucSig], 0x61417272); ST_U32(&fs->win[FSI_Free_Count], fs->free_clust); ST_U32(&fs->win[FSI_Nxt_Free], fs->last_clust); diskWrite(0, fs->win, fs->fsi_sector, 1); fs->fsi_flag = 0; }#endif if (diskIoctl(fs->drive, IOCTL_CTRL_SYNC, NULL) != DRESULT_OK) return FR_RW_ERROR; return FR_OK;}#endif/*-----------------------------------------------------------------------*//* Get a cluster status *//*-----------------------------------------------------------------------*/staticU32 get_cluster ( /* 0,>=2: successful, 1: failed */ FATFS *fs, /* File system object */ U32 clust /* Cluster# to get the link information */ ){ U16 wc, bc; U32 fatsect; if (clust >= 2 && clust < fs->max_clust) { /* Valid cluster# */ fatsect = fs->fatbase; switch (fs->fs_type) { case FS_FAT12 : bc = (U16)clust * 3 / 2; if (!move_window(fs, fatsect + (bc / S_SIZ))) break; wc = fs->win[bc & (S_SIZ - 1)]; bc++; if (!move_window(fs, fatsect + (bc / S_SIZ))) break; wc |= (U16)fs->win[bc & (S_SIZ - 1)] << 8; return (clust & 1) ? (wc >> 4) : (wc & 0xFFF); case FS_FAT16 : if (!move_window(fs, fatsect + (clust / (S_SIZ / 2)))) break; return LD_U16(&fs->win[((U16)clust * 2) & (S_SIZ - 1)]); case FS_FAT32 : if (!move_window(fs, fatsect + (clust / (S_SIZ / 4)))) break; return LD_U32(&fs->win[((U16)clust * 4) & (S_SIZ - 1)]) & 0x0FFFFFFF; } } return 1; /* There is no cluster information, or an error occured */}/*-----------------------------------------------------------------------*//* Change a cluster status *//*-----------------------------------------------------------------------*/#if _FS_READONLY == 0staticBOOL put_cluster ( /* TRUE: successful, FALSE: failed */ FATFS *fs, /* File system object */ U32 clust, /* Cluster# to change */ U32 val /* New value to mark the cluster */ ){ U16 bc; U8 *p; U32 fatsect; fatsect = fs->fatbase; switch (fs->fs_type) { case FS_FAT12 : bc = (U16)clust * 3 / 2; if (!move_window(fs, fatsect + (bc / S_SIZ))) return FALSE; p = &fs->win[bc & (S_SIZ - 1)]; *p = (clust & 1) ? ((*p & 0x0F) | ((U8)val << 4)) : (U8)val; bc++; fs->winflag = 1; if (!move_window(fs, fatsect + (bc / S_SIZ))) return FALSE; p = &fs->win[bc & (S_SIZ - 1)]; *p = (clust & 1) ? (U8)(val >> 4) : ((*p & 0xF0) | ((U8)(val >> 8) & 0x0F)); break; case FS_FAT16 : if (!move_window(fs, fatsect + (clust / (S_SIZ / 2)))) return FALSE; ST_U16(&fs->win[((U16)clust * 2) & (S_SIZ - 1)], (U16)val); break; case FS_FAT32 : if (!move_window(fs, fatsect + (clust / (S_SIZ / 4)))) return FALSE; ST_U32(&fs->win[((U16)clust * 4) & (S_SIZ - 1)], val); break; default : return FALSE; } fs->winflag = 1; return TRUE;}#endif /* !_FS_READONLY *//*-----------------------------------------------------------------------*//* Remove a cluster chain *//*-----------------------------------------------------------------------*/#if _FS_READONLY == 0staticBOOL remove_chain ( /* TRUE: successful, FALSE: failed */ FATFS *fs, /* File system object */ U32 clust /* Cluster# to remove chain from */ ){ U32 nxt; while (clust >= 2 && clust < fs->max_clust) { nxt = get_cluster(fs, clust); if (nxt == 1) return FALSE; if (!put_cluster(fs, clust, 0)) return FALSE; if (fs->free_clust != 0xFFFFFFFF) { fs->free_clust++;#if _USE_FSINFO fs->fsi_flag = 1;#endif } clust = nxt; } return TRUE;}#endif/*-----------------------------------------------------------------------*//* Stretch or create a cluster chain *//*-----------------------------------------------------------------------*/#if _FS_READONLY == 0staticU32 create_chain ( /* 0: no free cluster, 1: error, >=2: new cluster number */ FATFS *fs, /* File system object */ U32 clust /* Cluster# to stretch, 0 means create new */ ){ U32 cstat, ncl, scl, mcl = fs->max_clust; if (clust == 0) { /* Create new chain */ scl = fs->last_clust; /* Get suggested start point */ if (scl == 0 || scl >= mcl) scl = 1; } else { /* Stretch existing chain */ cstat = get_cluster(fs, clust); /* Check the cluster status */ if (cstat < 2) return 1; /* It is an invalid cluster */ if (cstat < mcl) return cstat; /* It is already followed by next cluster */ scl = clust; } ncl = scl; /* Start cluster */ for (;;) { ncl++; /* Next cluster */ if (ncl >= mcl) { /* Wrap around */ ncl = 2; if (ncl > scl) return 0; /* No free custer */ } cstat = get_cluster(fs, ncl); /* Get the cluster status */ if (cstat == 0) break; /* Found a free cluster */ if (cstat == 1) return 1; /* Any error occured */ if (ncl == scl) return 0; /* No free custer */ } if (!put_cluster(fs, ncl, 0x0FFFFFFF)) return 1; /* Mark the new cluster "in use" */ if (clust && !put_cluster(fs, clust, ncl)) return 1; /* Link it to previous one if needed */ fs->last_clust = ncl; /* Update fsinfo */ if (fs->free_clust != 0xFFFFFFFF) { fs->free_clust--;#if _USE_FSINFO fs->fsi_flag = 1;#endif } return ncl; /* Return new cluster number */}#endif /* !_FS_READONLY *//*-----------------------------------------------------------------------*//* Get sector# from cluster# *//*-----------------------------------------------------------------------*/staticU32 clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */ FATFS *fs, /* File system object */ U32 clust /* Cluster# to be converted */ ){ clust -= 2; if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */ return clust * fs->sects_clust + fs->database;}/*-----------------------------------------------------------------------*//* Move directory pointer to next *//*-----------------------------------------------------------------------*/staticBOOL next_dir_entry ( /* TRUE: successful, FALSE: could not move next */ DIR *dirobj /* Pointer to directory object */ ){ U32 clust; U16 idx; FATFS *fs = dirobj->fs; idx = dirobj->index + 1; if ((idx & ((S_SIZ - 1) / 32)) == 0) { /* Table sector changed? */ dirobj->sect++; /* Next sector */ if (!dirobj->clust) { /* In static table */ if (idx >= fs->n_rootdir) return FALSE; /* Reached to end of table */ } else { /* In dynamic table */ if (((idx / (S_SIZ / 32)) & (fs->sects_clust - 1)) == 0) { /* Cluster changed? */ clust = get_cluster(fs, dirobj->clust); /* Get next cluster */ if (clust < 2 || clust >= fs->max_clust) /* Reached to end of table */ return FALSE; dirobj->clust = clust; /* Initialize for new cluster */ dirobj->sect = clust2sect(fs, clust); } } } dirobj->index = idx; /* Lower 4 bit of dirobj->index indicates offset in dirobj->sect */ return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -