⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 avr MP3 的源程序,包含文件系统,适合初学者
💻 C
字号:
//---------------------------------------------------------------------
//FileName     : fat.c
//Created by   : nasif
//Modified by  : ZhengYanbo
//Last Modified: 2006.4.8
//function     : implementation to interface CF with FAT filesystem

//---------------------------------------------------------------------

#include "fat.h"
#include "global_def.h"

//*******************************************************************
// Convert cluster address to LBA address
unsigned long clust2LBA(unsigned long clust) 
//*******************************************************************
{   
	return ((clust-2) * Sectors_Per_Cluster) + FirstDataSector;
}

/*
//*******************************************************************
// Convert LBA address to cluster address
unsigned long LBA2Cluster(unsigned long LBA)
//*******************************************************************
{
	return ((LBA-FirstDataSector)/Sectors_Per_Cluster)+2;
}
*/

//*******************************************************************
//  FAT filesystem Init
//  Return: FAT type
byte ATA_getFileSystemInfo(void)
//*******************************************************************
{
 	struct partRec *pr;
	struct bootSec710 *boot;
	//struct driveID *driveInfo;
	dword  CountofClusters;
	//struct FAT32fsInfo *fsInfo; 	
	dword  startSector;
	dword  FATSz, dataSec, totalSector;
	
	LCDclrscr();
	writestring("读文件系统...");
	gotoxy(1,0);
	writestring("文件系统:");
	
	//---------------------------------------------	
	//Start to Read MBR sector
	//---------------------------------------------
	ATA_Read_Sector(0, sectorBuffer.data);
	if(sectorBuffer.data[0] == 0xeb) 
	{ //If first byte is a instruction of JMP,no DPT.
	  //---------------------------------------------
	  //  debug info here
	  //---------------------------------------------
	}	 
	else 
	{ 
	  //skipping boot code in first 445 bytes. 
	  //Read 64 bytes partition table record
	  pr = (struct partRec *)&sectorBuffer.data[0x1BE];
	  startSector = pr->startLBA;
	  ATA_Read_Sector(startSector, sectorBuffer.data); //read boot record
	}
	boot = (struct bootSec710 *) sectorBuffer.data; //Load BPB struct pointer

	//All of the following calculations are from Microsoft FAT32 White Paper	
	Sectors_Per_Cluster = boot->BPB.secPerClust;
	Bytes_Per_Sector = boot->BPB.bytesPerSec;
	FirstFATSector = boot->BPB.resSectors + startSector;

	FATtype=OTHER;
	if (boot->BPB.rootDirEnts==0) 
	{
	  FATtype=FAT32; //FAT32
	  FirstRootCluster = boot->BPB.rootClust; 
	  writestring("FAT32");
	}
	rootDirSectors=(((boot->BPB.rootDirEnts * 32)+ (Bytes_Per_Sector - 1)) / Bytes_Per_Sector);
	
	//-------------- Get FAT Size and total sectors ----------------
	//For FAT32,BPB.FATSz16 must equal to 0.
	//For FAT12 or FAT16,BPB.FATSz16 is a word wide.
	//--------------------------------------------------------------
	FATSz = boot->BPB.FATSz16;   //For FAT16 or FAT12 Filesystem
	if (FATSz==0) FATSz = boot->BPB.FATSz32;
	//For FAT16 or FAT12,if(totSec>65536) BPB.totSec16==0.You must get tatal 
	//sectors from totSec32. !!!For FAT32, BPB.totSec16 Must Equal to 0 !
	if (boot->BPB.totSec16 != 0) totalSector=boot->BPB.totSec16;
	else totalSector=boot->BPB.totSec32;

	dataSec = totalSector - (boot->BPB.resSectors + (boot->BPB.FATs * FATSz) + rootDirSectors);
	FirstRootSector = FirstFATSector + (boot->BPB.FATs * FATSz); //for fat16 or fat12
	FirstDataSector = boot->BPB.resSectors + (boot->BPB.FATs * FATSz) + rootDirSectors + startSector;
	
	//Number of valid clusters
	CountofClusters = dataSec / Sectors_Per_Cluster;
	//maxcluster=CountofClusters+2;
	//writeNumber(CountofClusters);
	//Note also that the CountofClusters value is exactly that: the count of data clusters
	//starting at cluster 2. The maximum valid cluster number for the volume is
	//CountofClusters + 1, and the "count of clusters including the two reserved clusters"
	//is CountofClusters + 2.
	
	//get cluster size(how many bytes?)
	Bytes_Per_Cluster = Bytes_Per_Sector * Sectors_Per_Cluster;

	//---------------  Determine Filesystem Type --------------------
	if(FATtype!=FAT32) 
	{
	FirstRootCluster=0; // for FAT12 and FAT16
	if(CountofClusters < 4085) 
	{
	    FATtype=FAT12; writestring("FAT12");
	} //FAT12
	else 
	{
	    FATtype=FAT16; writestring("FAT16");
	} //FAT16
	}
	
	//delay_ms(1000); //delay for showing fat type
	
	//-----------------------------------------
	//    debug info
	//-----------------------------------------
	/*
	LCDclrscr();
	writestring("BPS:");
	writeNumber(Bytes_Per_Sector);
	writechar(' ');
	writestring("SPC:");
	writeNumber(Sectors_Per_Cluster);
	gotoxy(1,0);
	writestring("Start Sector:");
	writeNumber(startSector);
	//delay_ms(3000); //pause 1000ms
	
	//-------------------------------------------
	// rootDirSectors and boot->BPB.rootDirEnts
	// This is debugging for fat12 or fat16.
	//-------------------------------------------
	gotoxy(2,0);
	writestring("RootDirEnt:");
	writeNumber(boot->BPB.rootDirEnts);
	gotoxy(3,0);
	writestring("RootDirSect:");
	writeNumber(rootDirSectors);
	delay_ms(1000);
	
	//-------------------------------------------
	// FirstRootSector and FirstDataSector
	//-------------------------------------------
	LCDclrscr();
	writestring("Root Start:");
	writeNumber(FirstRootSector);
	gotoxy(1,0);
	writestring("Data Start:");
	writeNumber(FirstDataSector);
	delay_ms(1000); */	
	
	return(FATtype);
}

//*******************************************************************
//get directory Entry info 
//gets a filename.ext, filesize, and start cluster of that file.
//Returns 1 if file is found, returns 0 if no file found and reaches
//end of directory.Each file record in dir is 32 byte long.
//Root Directory Access Only!
//NOTICE: I had copied Extension name for short name, too!!!
unsigned char getDirEntry(byte onlyMP3)
//*******************************************************************
{
    word    fileNum=0;
    dword   extension,cluster;
    byte    i,j,start,longNameFound;
    word    rootEntries; //root directory count	
    struct  direntry *file;	
    struct  winentry *longFile;
    dword   dirReadLBA; //directory entry LBA address(fat16 or fat12)
  
    readPos=0;
    if((currentFileNum & dirReadOffset.fileNum) ==0) 
    {   //if reading from start of root dir
        dirReadLBA=FirstRootSector;//for fat16 or fat12
        subDirLevel=0; //root directory now
        dirReadOffset.entryCount=0; //clear entry count
        rootEntries=0;
        //dirString[0]=2;
        //dirString[1]='/';
    }
    else 
    {   //Find the previous file record read offset in root directory.
        fileNum=dirReadOffset.fileNum;   //Last read file number
        dirReadLBA=dirReadOffset.dirLBA; //Last LBA address
        readPos=dirReadOffset.readPos;
        rootEntries=dirReadOffset.entryCount;
        GoToSectorOffset(dirReadLBA, readPos);
 	}          
 	
 	CLEAR: //Jump position if an entry was invalid entry, clear fileName
	
	for(i=0; i<FILE_NAME_LENGTH; i++) fileName[i]=0; //Clear file name
	extension=0;
	longNameFound=0; //long name flag
    
    do { //loop untill find a file or reach the end of a directory.
    //directory entry is in root directory, read 32 bytes of root directory  
    ATA_Read_Sector_Bytes(dirReadLBA,32,sectorBuffer.data);
    //We have read an entry(32 bytes long),increase rootEntries
    rootEntries++;
    //NOTICE: for fat12/fat16, root directories take up 32 sectors at most.
    //Means : total Root Directories < 512 
    if(rootEntries>512) goto ROOT_DIR_END;
    //must to be read a new root dir sector. 
    if(readPos==0) dirReadLBA++;
    
    //Init file entry pointer
    longFile=(struct winentry *) sectorBuffer.data; 
    file=(struct direntry *) sectorBuffer.data;
    
    if(sectorBuffer.data[0] == 0xE5) { goto CLEAR; } //Deleted entry
    
    //------------------------------------------------------------------           	  
    //  End of a Root directory  block
    //------------------------------------------------------------------ 
    if(sectorBuffer.data[0] == 0)
    {   //We reached end of a directory
        ROOT_DIR_END:
        currentFileNum=0;
        ATA_lba_close();
        return 0; //Done. Finished reading all root entries so return 0
    }  
    
    //------------------------------------------------------------------------	             
    //  Active long name sub-component block
    //------------------------------------------------------------------------ 	
    if((longFile->Attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME)
    {	/*
        start = 13 *( (longFile->Cnt-1) & 0x0F);
        i=0;
        while ((start<40)&&(i<13)) 
        { fileName[start++] = sectorBuffer.data[longNameOffset[i++]]; } */
        start = 26 *( (longFile->Cnt-1) & 0x0F); //Fine offset of text in long file name	   
        i=0;
        while ((start<(FILE_NAME_LENGTH-2))&&(i<5)) 
        { fileName[start++]=(byte)(longFile->Part1[i]>>8);
          fileName[start++]=(byte)(longFile->Part1[i]);
          i++; 
        }
        i=0;
        while ((start<(FILE_NAME_LENGTH-2))&&(i<6)) 
        { fileName[start++]=(byte)(longFile->Part2[i]>>8); 
          fileName[start++]=(byte)(longFile->Part2[i]);
          i++;
        }
        i=0;
        while ((start<(FILE_NAME_LENGTH-2))&&(i<2)) 
        { fileName[start++]=(byte)(longFile->Part3[i]>>8);
          fileName[start++]=(byte)(longFile->Part3[i]);
          i++; 
        }  	 
        longNameFound=1;
    }//long name process
    else 
    {   //Found Short file entry, now determine its type
        for (i=0; i<8; i++) 
        {  
        for (j=0; j<47; j++) if (invalidFileChars[j]== file->name[i]) goto CLEAR;
        if (longNameFound==0) fileName[i]=file->name[i]; // Reading short file name
        }
        
        //----------------------------------------------------------------------
        //          Copy Extension name, for short file name only
        //----------------------------------------------------------------------
        if (longNameFound==0)
        {
            for(i=0; i<3; i++) fileName[i+8] = file->name[i];
        }   
    
        //----------------------------------------------------------------------
        //          Found a file
        //----------------------------------------------------------------------
        if ((file->attributes & 0x18 /*(ATTR_DIRECTORY | ATTR_VOLUME_ID)*/ ) == 0x00) 
        {   for(i=0;i<3; i++) 
            { //Collect the file extension
             fileExtension[i]=file->extension[i];
            }      
            extension = (*(dword *)fileExtension) & 0x00FFFFFF;
	        // we want WMA files
            if ((onlyMP3==1)&&(extension!=0x00414D57)) 
            {goto CLEAR;}; //extension = 03PM (little endian struct)	   
            fileNum++;                            
	        if(fileNum>currentFileNum) 
	        { currentFileNum=fileNum;
	        FileSize = file->fileSize;
	        currentCluster = file->highClust;
	        currentCluster = (currentCluster<<16) + file->startCluster;
	        //Remember the first cluster of the file
	        firstCluster = currentCluster;  
	        dirReadOffset.dirLBA=dirReadLBA; //save lba address
	        dirReadOffset.readPos=readPos;   //address of current Entry
	        dirReadOffset.fileNum=fileNum;
	        dirReadOffset.entryCount=rootEntries;
	        ATA_lba_close();
	        return 1;
	        }//fileNum>currentFileNum
	        goto CLEAR;
        }//Found a file                                                                                     
    
        //-------------------------------------------------------------
        //      Found a directory
        //-------------------------------------------------------------	  	  
        if ((file->attributes & 0x18) == ATTR_DIRECTORY) 
        { 
            goto CLEAR;
        }//((file->attributes & 0x18) == ATTR_DIRECTORY)
    }//File Entry end  
    }while (1); //loop until arrived at the end of a directory.	 
}

//*******************************************************************
// Find next cluster in fat(only for FAT16)
dword findNextCluster()
//*******************************************************************
{
    unsigned long FatOffset, sector;
    unsigned int offset;
    
    FatOffset = (currentCluster << 1);   //Lshift by 1 in FAT16
    sector = FirstFATSector + (FatOffset / Bytes_Per_Sector);
    offset = FatOffset % Bytes_Per_Sector;
    ATA_Read_Sector(sector, sectorBuffer.data);
    //FAT16 address return 
    return (*(unsigned int *)&sectorBuffer.data[offset]); 
}

  
//======================== End of zfat.c ==========================//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -