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