除了支持长文件名外,其实FAT32基本上只是在族(cluster)的定义上加长为32bit而已。反过来,FAT32实际上简化了整个结构:它的根目录区被简化为一个族。所以 对FAT32文件系统的根目录操作不必另眼看待,可与普通子目录的操作相同。
以下是一个对FAT32读操作的实例 (在PIC18F2520上实现):
#include <string.h> #include "define.h" #include "mmcspi.h" #include "mmcfile.h" #include "fat32.h" #include "lcd3310.h"
#define fileStartCluster(dir) ((dir->startClusterHi << 16) | dir->startClusterLo)
static FileDesc_t *FAT32_FindFileInSubDir (unsigned long cluster, unsigned int *cntptr, unsigned char depth); static void FAT32_searchFileInSubDir (unsigned long cluster, unsigned int *cnt, unsigned char depth);
/////////////////////////////////////////////////////////////////////// char FAT32_InitEntry (BootSector_t_FAT32 *pp) { if ( pp->numOfFAT == 2 && pp->rootEntries == 0 && pp->sectorPerCluster && pp->sectorSize == MMC_SECTOR_SIZE ) { FILE_entry.sectorPerCluster = pp->sectorPerCluster; FILE_entry.sectorPerFAT32 = pp->numOfSectorPerFAT; // FILE_entry.totalSectors = pp->totalSectors; // size of volume // FILE_entry.startOfFileSys = FILE_entry.startSector + pp->sectorOfFileSysInfo; FILE_entry.fatStart = FILE_entry.startSector + pp->reserveSectors; // fat area start sector # // FILE_entry.rootStart = FILE_entry.fatStart + FILE_entry.sectorPerFAT32 * FILE_entry.numOfFAT; FILE_entry.dataStart = FILE_entry.fatStart + FILE_entry.sectorPerFAT32 * 2; // data area start sector # FILE_entry.startClusterOfRoot= pp->clusterOfRootDir; // root directory start cluster # /* char buf[20]; ltoa (FILE_entry.fatStart, buf, 10); LCD_write_string (0, 3, buf); ltoa (FILE_entry.dataStart, buf, 10); LCD_write_string (0, 4, buf); ltoa (pp->clusterOfRootDir, buf, 10); LCD_write_string (0, 5, buf);
for(;;); */ return FILE_OK; }
return FILE_ERR_FMT; }
/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// FileDesc_t * FAT32_ReturnFileHandle (DirEntry_t_FAT32 *dir) { memcpy (fileDesc.fileName, dir->fileName, 11); // get filename+ext fileDesc.size = dir->fileSize; // get file size fileDesc.cluster = fileStartCluster(dir); // get file (start) cluster) fileDesc.sector = 0; return &fileDesc; }
/////////////////////////////////////////////////////////////////////////////// // // now it supports N-level directory structure ... (Ha-Ha!) May, 2004 // /////////////////////////////////////////////////////////////////////////////// FileDesc_t *FAT32_FindFile (unsigned int index) { return FAT32_FindFileInSubDir (FILE_entry.startClusterOfRoot, &index, 0); }
/////////////////////////////////////////////////////////////////////////////// #pragma recursive_function static FileDesc_t *FAT32_FindFileInSubDir (unsigned long cluster, unsigned int *cntptr, unsigned char depth) { subDirDesc.cluster = cluster; subDirDesc.sector = 0;
while ( FAT32_readFileSector (&subDirDesc) != NULL ) { unsigned int j; FileDesc_t *fdes;
for (j = 0; j < MMC_SECTOR_SIZE; j += DIR_ENTRY_SIZE) { DirEntry_t_FAT32 *dir = (DirEntry_t_FAT32 *)&FILE_tempBuf[j];
switch ( FILE_EntryType (dir) ) { case MP3_FILE: (*cntptr)--; // it's an MP3 file
if ( *cntptr == 0 ) return FAT32_ReturnFileHandle (dir); break;
case SUB_DIR: // it's a sub-directory! if ( depth < MAX_DIR_DEPTH ) { // save the cluster/sector unsigned long this_cluster= subDirDesc.cluster; unsigned char this_sector = subDirDesc.sector;
// recursive searching for sub-directory fdes = FAT32_FindFileInSubDir (fileStartCluster(dir), cntptr, depth+1);
if ( fdes != NULL ) return fdes;
// restore the cluster/sector subDirDesc.cluster= this_cluster; subDirDesc.sector = this_sector - 1;
FAT32_readFileSector (&subDirDesc); // read back the sector } break; } } } return NULL; }
/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static unsigned long FAT32_GetDataSector (unsigned long cluster) { return FILE_entry.dataStart + (cluster - FILE_entry.startClusterOfRoot) * FILE_entry.sectorPerCluster; }
#define FILE_ClusterFatOffset(cluster) ((cluster & 0x7f) << 2)
/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static unsigned long FAT32_NextCluster (unsigned long cluster) { unsigned long sector;
//#pragma short_branch if ( cluster < 2 || cluster >= 0x0ffffff0 ) return 0xffffffff;
// FAT32: 128 cluster items per sector sector = FILE_entry.fatStart + cluster / 128;
if ( MMC_ReadSector (FILE_tempBuf, sector) == MMC_OK ) { unsigned int offset = FILE_ClusterFatOffset (cluster); return *((unsigned long *)&FILE_tempBuf[offset]); }
return 0xffffffff; }
/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// unsigned char *FAT32_readFileSector (FileDesc_t *file) { if ( file->sector >= FILE_entry.sectorPerCluster ) { file->cluster = FAT32_NextCluster (file->cluster); file->sector = 0; }
if ( file->cluster >= 0x0ffffff0 ) return NULL;
if ( file->sector == 0 ) file->startSector = FAT32_GetDataSector (file->cluster);
unsigned long sector = file->startSector + file->sector++;
if ( MMC_ReadSector (FILE_tempBuf, sector) != MMC_OK ) return NULL;
return FILE_tempBuf; }
/////////////////////////////////////////////////////////////////////////////// /* only get data sector number, not read the sector data! */ char FAT32_nextFileSector (FileDesc_t *file) { if ( file->sector >= FILE_entry.sectorPerCluster ) { file->cluster = FAT32_NextCluster (file->cluster); file->sector = 0; }
if ( file->cluster >= 0xffffff0 ) return 0;
if ( file->sector == 0 ) file->startSector = FAT32_GetDataSector (file->cluster);
file->sector++; return -1; }
/////////////////////////////////////////////////////////////////////////////// unsigned int FAT32_searchMP3Files (void) { unsigned int cnt = 0;
FAT32_searchFileInSubDir (FILE_entry.startClusterOfRoot, &cnt, 0); return cnt; }
/////////////////////////////////////////////////////////////////////////////// #pragma recursive_function static void FAT32_searchFileInSubDir (unsigned long cluster, unsigned int *cnt, unsigned char depth) { subDirDesc.cluster = cluster; subDirDesc.sector = 0;
while ( FAT32_readFileSector (&subDirDesc) != NULL ) { unsigned int i;
for (i = 0; i < MMC_SECTOR_SIZE; i += DIR_ENTRY_SIZE) { DirEntry_t_FAT32 *dir = &FILE_tempBuf;
switch ( FILE_EntryType (dir) ) { case MP3_FILE: (*cnt)++; // it's an MP3 file break;
case SUB_DIR: // it's a sub-directory! if ( depth < MAX_DIR_DEPTH ) { // save the cluster/sector unsigned long this_cluster= subDirDesc.cluster; unsigned char this_sector = subDirDesc.sector;
// recursive searching for sub-directory FAT32_searchFileInSubDir (fileStartCluster (dir), cnt, depth+1);
// restore the cluster/sector subDirDesc.cluster = this_cluster; subDirDesc.sector = this_sector - 1; FAT32_readFileSector (&subDirDesc); } break; } } } }
|