vuanoixao thân mến.
bạn muốn lập trình với bảng FAT(16/32) trong ngôn ngữ C thấp.
mình có mã nguồn tham khảo dành cho bạn.
đây là file fat.c
fat.c File Reference
--------------------------------------------------------------------------------
Detailed Description
Definition in file fat.c.
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <string.h>
#include "ata.h"
#include "rprintf.h"
#include "fat.h"
#include "fatconf.h"
Functions
unsigned long fatClustToSect (unsigned long clust)
unsigned int fatClusterSize (void)
unsigned char fatInit (unsigned char device)
unsigned long fatGetDirEntry (unsigned int entry, unsigned int count)
unsigned long fatGetFilesize (void)
char * fatGetFilename (void)
char * fatGetDirname (void)
void fatLoadCluster (unsigned long cluster, unsigned char *buffer)
unsigned long fatNextCluster (unsigned long cluster)
Variables
unsigned char * SectorBuffer = (unsigned char *) SECTOR_BUFFER1_ADDR
unsigned char * LongNameBuffer = (unsigned char *) LONGNAME_BUFFER_ADDR
unsigned char * DirNameBuffer = (unsigned char *) DIRNAME_BUFFER_ADDR
partrecord PartInfo
unsigned char Fat32Enabled
unsigned long FirstDataSector
unsigned int BytesPerSector
unsigned int SectorsPerCluster
unsigned long FirstFATSector
unsigned long FirstDirSector
unsigned long FileSize
unsigned long FatInCache = 0
unsigned int baseentry = 0
unsigned int entrycount = 0
00001 /*! \file fat.c \brief FAT16/32 file system driver. */
00002 //*****************************************************************************
00003 //
00004 // File Name : 'fat.c'
00005 // Title : FAT16/32 file system driver
00006 // Author : Pascal Stang
00007 // Date : 11/07/2000
00008 // Revised : 12/12/2000
00009 // Version : 0.3
00010 // Target MCU : ATmega103 (should work for Atmel AVR Series)
00011 // Editor Tabs : 4
00012 //
00013 // This code is based in part on work done by Jesper Hansen for his
00014 // YAMPP MP3 player project.
00015 //
00016 // NOTE: This code is currently below version 1.0, and therefore is considered
00017 // to be lacking in some functionality or documentation, or may not be fully
00018 // tested. Nonetheless, you can expect most functions to work.
00019 //
00020 // This code is distributed under the GNU Public License
00021 // which can be found at http://www.gnu.org/licenses/gpl.txt
00022 //
00023 //*****************************************************************************
00024
00025
00026 #include <avr/io.h>
00027 #include <avr/pgmspace.h>
00028 #include <string.h>
00029
00030 #include "ata.h"
00031 #include "rprintf.h"
00032
00033 #include "fat.h"
00034 #include "fatconf.h"
00035
00036 // globals
00037 unsigned char *SectorBuffer = (unsigned char *) SECTOR_BUFFER1_ADDR;
00038 unsigned char *LongNameBuffer = (unsigned char *) LONGNAME_BUFFER_ADDR;
00039 unsigned char *DirNameBuffer = (unsigned char *) DIRNAME_BUFFER_ADDR;
00040
00041 struct partrecord PartInfo;
00042 unsigned char Fat32Enabled;
00043 unsigned long FirstDataSector;
00044 unsigned int BytesPerSector;
00045 unsigned int SectorsPerCluster;
00046 unsigned long FirstFATSector;
00047 unsigned long FirstDirSector;
00048 unsigned long FileSize;
00049 unsigned long FatInCache = 0;
00050
00051 /*************************************************************************/
00052 /*************************************************************************/
00053
00054
00055 unsigned long fatClustToSect(unsigned long clust)
00056 {
00057 return ((clust-2) * SectorsPerCluster) + FirstDataSector;
00058 }
00059
00060 unsigned int fatClusterSize(void)
00061 {
00062 // return the number of sectors in a disk cluster
00063 return SectorsPerCluster;
00064 }
00065
00066 unsigned char fatInit( unsigned char device)
00067 {
00068 //struct partrecord *pr;
00069 struct bpb710 *bpb;
00070
00071 // read partition table
00072 // TODO.... error checking
00073 ataReadSectors(DRIVE0, 0, 1, SectorBuffer);
00074 // map first partition record
00075 // save partition information to global PartInfo
00076 PartInfo = *((struct partrecord *) ((struct partsector *) SectorBuffer)->psPart);
00077 // PartInfo = *pr;
00078
00079 // Read the Partition BootSector
00080 // **first sector of partition in PartInfo.prStartLBA
00081 ataReadSectors( DRIVE0, PartInfo.prStartLBA, 1, SectorBuffer );
00082 bpb = (struct bpb710 *) ((struct bootsector710 *) SectorBuffer)->bsBPB;
00083
00084 // setup global disk constants
00085 FirstDataSector = PartInfo.prStartLBA;
00086 if(bpb->bpbFATsecs)
00087 {
00088 // bpbFATsecs is non-zero and is therefore valid
00089 FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbFATsecs;
00090 }
00091 else
00092 {
00093 // bpbFATsecs is zero, real value is in bpbBigFATsecs
00094 FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbBigFATsecs;
00095 }
00096 SectorsPerCluster = bpb->bpbSecPerClust;
00097 BytesPerSector = bpb->bpbBytesPerSec;
00098 FirstFATSector = bpb->bpbResSectors + PartInfo.prStartLBA;
00099
00100 switch (PartInfo.prPartType)
00101 {
00102 case PART_TYPE_DOSFAT16:
00103 case PART_TYPE_FAT16:
00104 case PART_TYPE_FAT16LBA:
00105 // first directory cluster is 2 by default (clusters range 2->big)
00106 FirstDirSector = CLUST_FIRST;
00107 // push data sector pointer to end of root directory area
00108 //FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
00109 Fat32Enabled = FALSE;
00110 break;
00111 case PART_TYPE_FAT32LBA:
00112 case PART_TYPE_FAT32:
00113 // bpbRootClust field exists in FAT32 bpb710, but not in lesser bpb's
00114 FirstDirSector = bpb->bpbRootClust;
00115 // push data sector pointer to end of root directory area
00116 // need this? FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
00117 Fat32Enabled = TRUE;
00118 break;
00119 default:
00120 rprintfProgStrM("Found: No Partition!\r\n");
00121 //return 1;
00122 break;
00123 }
00124
00125
00126 #ifdef DEBUG_FAT
00127 switch (PartInfo.prPartType)
00128 {
00129 case PART_TYPE_DOSFAT16:
00130 rprintfProgStrM("Found: DOSFAT 16\r\n");
00131 break;
00132 case PART_TYPE_FAT16:
00133 rprintfProgStrM("Found: FAT16\r\n");
00134 break;
00135 case PART_TYPE_FAT16LBA:
00136 rprintfProgStrM("Found: FAT16 LBA\r\n");
00137 break;
00138 case PART_TYPE_FAT32LBA:
00139 rprintfProgStrM("Found: FAT32 LBA\r\n");
00140 break;
00141 case PART_TYPE_FAT32:
00142 rprintfProgStrM("Found: FAT32\r\n");
00143 //return 1;
00144 break;
00145 default:
00146 rprintfProgStrM("Found: No Partition!\r\n");
00147 //return 1;
00148 break;
00149 }
00150
00151 rprintfProgStrM("First sector : "); rprintfu32(PartInfo.prStartLBA); rprintfCRLF();
00152 rprintfProgStrM("Size : "); rprintfu32(PartInfo.prSize); rprintfCRLF();
00153 rprintfProgStrM("bytes/sector : "); rprintfu16(bpb->bpbBytesPerSec); rprintfCRLF();
00154 rprintfProgStrM("sectors/cluster : "); rprintfu08(bpb->bpbSecPerClust); rprintfCRLF();
00155 rprintfProgStrM("reserved sectors: "); rprintfu16(bpb->bpbResSectors); rprintfCRLF();
00156 rprintfProgStrM("FatSectors : "); rprintfu16(bpb->bpbFATsecs); rprintfCRLF();
00157 rprintfProgStrM("BigFatSectors : "); rprintfu32(bpb->bpbBigFATsecs); rprintfCRLF();
00158 rprintfProgStrM("Number of Fats : "); rprintfu08(bpb->bpbFATs); rprintfCRLF();
00159 rprintfProgStrM("First Fat Sector: "); rprintfu32(FirstFATSector); rprintfCRLF();
00160 rprintfProgStrM("First Data Sect : "); rprintfu32(FirstDataSector); rprintfCRLF();
00161 rprintfProgStrM("First Dir Clust : "); rprintfu32(FirstDirSector); rprintfCRLF();
00162 #endif
00163
00164 return 0;
00165 }
00166
00167 //////////////////////////////////////////////////////////////
00168
00169
00170 unsigned int baseentry = 0;
00171 unsigned int entrycount = 0;
00172
00173
00174 unsigned long fatGetDirEntry(unsigned int entry, unsigned int count)
00175 {
00176 unsigned long sector;
00177 struct direntry *de = 0; // avoid compiler warning by initializing
00178 struct winentry *we;
00179 unsigned int hasBuffer;
00180 unsigned int b;
00181 int i,index;
00182 char *p;
00183
00184 if(count == 0)
00185 {
00186 entrycount = 0;
00187 DirNameBuffer = 0;
00188 }
00189
00190 // read dir data
00191 sector = fatClustToSect(FirstDirSector);
00192
00193 hasBuffer = 0;
00194
00195 index = 16; // crank it up
00196 do
00197 {
00198 if(index == 16) // time for next sector ?
00199 {
00200 ataReadSectors( DRIVE0, sector++, 1, SectorBuffer);
00201 de = (struct direntry *) SectorBuffer;
00202 index = 0;
00203 }
00204
00205 if(*de->deName != 0xE5)
00206 {
00207 // if not a deleted entry
00208 if(de->deAttributes == ATTR_LONG_FILENAME)
00209 {
00210 // we have a long name entry
00211 we = (struct winentry *) de;
00212 b = 13 *( (we->weCnt-1) & 0x0f); // index into string
00213 p = &LongNameBuffer
;
00214 for (i=0;i<5;i++) *p++ = we->wePart1[i*2]; // copy first part
00215 for (i=0;i<6;i++) *p++ = we->wePart2[i*2]; // second part
00216 for (i=0;i<2;i++) *p++ = we->wePart3[i*2]; // and third part
00217 if (we->weCnt & 0x40) *p = 0; // in case dirnamelength is multiple of 13
00218 if ((we->weCnt & 0x0f) == 1) hasBuffer = 1; // mark that we have a long entry
00219 }
00220 else
00221 {
00222 // we have a short name entry
00223 // check if this is the end of a multi-part long name entry
00224 if(hasBuffer)
00225 {
00226 // a long entry name has been collected
00227 // is it a directory ?
00228 if(de->deAttributes == ATTR_DIRECTORY)
00229 {
00230 unsigned long save = FirstDirSector;
00231 unsigned int save2 = baseentry;
00232 unsigned long rval;
00233
00234 strcpy(DirNameBuffer,LongNameBuffer);
00235 strcat(DirNameBuffer,"/");
00236
00237 // rprintfStr(LongNameBuffer); rprintfProgStrM("/"); //EOL();
00238
00239 // call recursively
00240 FirstDirSector = ((unsigned long)de->deHighClust << 16) + de->deStartCluster;
00241 rval = fatGetDirEntry(entry,1);
00242 FirstDirSector = save;
00243 baseentry = save2;
00244 if (rval)
00245 return rval;
00246 else
00247 {
00248 // reload original sector
00249 ataReadSectors( DRIVE0, sector-1, 1, SectorBuffer);
00250 entrycount--; // decrement entry counter
00251 *DirNameBuffer = 0;
00252 }
00253 }
00254 else // normal file entry
00255 if(entrycount == entry)
00256 break;
00257 hasBuffer = 0; // clear buffer
00258 entrycount++; // increment entry counter
00259 }
00260 // else ignore short_name_only entries
00261 }
00262 }
00263 de++;
00264 index++;
00265 } while (*de->deName || index == 16); // 0 in de->deName[0] if no more entries
00266
00267 if (hasBuffer == 0) // end of entries
00268 return 0;
00269
00270 FileSize = de->deFileSize;
00271 return (unsigned long) ((unsigned long)de->deHighClust << 16) + de->deStartCluster;
00272 }
00273
00274
00275 // return the size of the last directory entry
00276 unsigned long fatGetFilesize(void)
00277 {
00278 return FileSize;
00279 }
00280
00281
00282 // return the long name of the last directory entry
00283 char* fatGetFilename(void)
00284 {
00285 return LongNameBuffer;
00286 }
00287
00288
00289 // return the directory of the last directory entry
00290 char* fatGetDirname(void)
00291 {
00292 return DirNameBuffer;
00293 }
00294
00295
00296 // load a clusterfull of data
00297 void fatLoadCluster(unsigned long cluster, unsigned char *buffer)
00298 {
00299 register unsigned char i;
00300 // read cluster
00301 //while ( ataReadSectors( DRIVE0, clust2sect(cluster), SectorsPerCluster, buffer) != 0);
00302 for(i=0; i<SectorsPerCluster; i++)
00303 {
00304 // ataReadSectors( DRIVE0, clust2sect(cluster)+i, 1, buffer+(i<<9) );
00305 // temporary fix for wierd misaligned cluster problem
00306 // (only when using FAT16?)
00307 ataReadSectors( DRIVE0, fatClustToSect(cluster+8)+i, 1, buffer+(i<<9) );
00308 }
00309 }
00310
00311
00312 // find next cluster in the FAT chain
00313 unsigned long fatNextCluster(unsigned long cluster)
00314 {
00315 unsigned long nextCluster;
00316 unsigned long fatMask;
00317 unsigned long fatOffset;
00318 unsigned long sector;
00319 unsigned int offset;
00320
00321 // get fat offset in bytes
00322 if(Fat32Enabled)
00323 {
00324 // four FAT bytes (32 bits) for every cluster
00325 fatOffset = cluster << 2;
00326 // set the FAT bit mask
00327 fatMask = FAT32_MASK;
00328 }
00329 else
00330 {
00331 // two FAT bytes (16 bits) for every cluster
00332 fatOffset = cluster << 1;
00333 // set the FAT bit mask
00334 fatMask = FAT16_MASK;
00335 }
00336
00337 // calculate the FAT sector that we're interested in
00338 sector = FirstFATSector + (fatOffset / BytesPerSector);
00339 // calculate offset of the our entry within that FAT sector
00340 offset = fatOffset % BytesPerSector;
00341
00342 // if we don't already have this FAT chunk loaded, go get it
00343 if (sector != FatInCache)
00344 {
00345 // read sector of FAT table
00346 while (ataReadSectors( DRIVE0, sector, 1, (unsigned char*)FAT_CACHE_ADDR) != 0);
00347 FatInCache = sector;
00348 }
00349
00350 // read the nextCluster value
00351 nextCluster = (*((unsigned long*) &((char*)FAT_CACHE_ADDR)[offset])) & fatMask;
00352
00353 // check to see if we're at the end of the chain
00354 if (nextCluster == (CLUST_EOFE & fatMask))
00355 nextCluster = 0;
00356
00357 #ifdef DEBUG_FAT
00358 rprintfProgStrM(">");
00359 rprintfu32(nextCluster);
00360 rprintfCRLF();
00361 #endif
00362
00363 return nextCluster;
00364 }
bạn có thể tìm thấy các hàm thư viện dùng trong fat.c và toàn bộ mã nguồn liên quan
tại đây
chúc bạn thành công
UDI-E1.
trở nên nhân vật cần thiết không thể thiếu, bất cứ nơi nào ta sống.