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

📄 fat16avr.c

📁 移植到mega32上面的fat16代码实现了
💻 C
📖 第 1 页 / 共 3 页
字号:
//############################################################################
//
// File Name	: 'fat.c'
// Title		: FAT16 file system driver
// Author		: Zoltan Gradwohl
// Date			: 28/07/2005
// Revised		: 28/07/2005
// Version		: 1.0
// Target MCU	: ATmega128 (2K Byte Internal SRAM required)
// Editor Tabs	: 4
//
//
// NOTE: This code is currently below version 1.0, and therefore is considered
// to be lacking in some functionality or documentation, or may not be fully
// tested.  Nonetheless, you can expect most functions to work.
//
// This code is distributed under the GNU Public License
//		which can be found at http://www.gnu.org/licenses/gpl.txt
//
//############################################################################

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <string.h>

#include "mmc.h"
#include "rprintf.h"
#include "fat.h"
#include "fatconf.h"
#include "debug.h"

// globals
volatile uint16_t  RootDirectoryRegionStart;
volatile uint32_t  DataRegionStart;
volatile uint16_t  FATRegionSize;
volatile uint16_t  RootDirectoryRegionSize;
volatile uint32_t  DataRegionSize;
volatile uint8_t   SectorsPerCluster;
volatile uint16_t  BytePerSector;
volatile uint16_t  FATRegionStart;
volatile uint16_t  NumberOfFATs;
volatile uint8_t   SectorsPerFAT;
volatile uint16_t  VolumeStart = 0;
volatile uint16_t  ReservedSectors;

uint16_t glbl_FAT_Entry = 0;	// FAT entry
uint32_t glbl_FileSize = 0;	// filesize
uint32_t glbl_DataSector = 0;	// Sector where data starts
uint32_t glbl_Sector = 0;		// Sector which contains file size inforation
uint8_t  glbl_SubSector = 0;	// Which of the 16 32byte long SubSectors contains the file size
uint8_t  glbl_Attributes = 0; 	// Attribute Dir, archive, hidden, system, volume ...

uint16_t FATSectorAddress_old = 0;		// Zum überprüfen ob der FAT Sector schon geladen wurde

#define NAMEBUFFERSIZE 32
char NameBuffer[NAMEBUFFERSIZE];
char NameBufferShort[8];
char NameBufferExt[3];
char Name2FindBuffer[NAMEBUFFERSIZE];

union FAT16_Buffer F16;
#define F16_BUFFER_ONE (uint8_t*)(&F16.FATBuffer)
uint16_t FAT_Buf2[256];
#define F16_BUFFER_TWO (uint8_t*)(&FAT_Buf2)

#define RootEntiesCount 	 F16.BootSec.bsRootEntCnt
#define TotalNumberOfSectors F16.BootSec.bsTotSec32



//############################################################################
unsigned char fatInit(void)
//############################################################################
{
	// mmc read first sector
	mmcRead( 0 , F16_BUFFER_ONE );

	//If partitions are available
	if( F16.BootSec.bsjmpBoot == 0 )
	{
		// Number of Sectors Between the MBR and the First Sector in the Partition (32bit)
		VolumeStart = (uint16_t)F16.MBS.mbPartitionEntries[0].prStartLBA;
		// mmc read Fat16 boot sector
		mmcRead( VolumeStart , F16_BUFFER_ONE );
	}

	//
	ReservedSectors 		    = F16.BootSec.bsRsvdSecCnt; 		// 6
	BytePerSector 				= F16.BootSec.bsBytesPerSec;		// 512
	SectorsPerCluster  			= F16.BootSec.bsSecPerClus;		// 4
	NumberOfFATs 		 		= F16.BootSec.bsNumFATs;			// 2
	SectorsPerFAT 		 		= F16.BootSec.bsNrSeProFAT;		// 245

	// Calculation Algorithms
	FATRegionStart				= VolumeStart + ReservedSectors;						// 6
	RootDirectoryRegionStart 	= FATRegionStart + (NumberOfFATs * SectorsPerFAT);		// 496
	RootDirectoryRegionSize 	= (RootEntiesCount*32)/ BytePerSector;					// 32
	DataRegionStart 			= RootDirectoryRegionStart + RootDirectoryRegionSize;	// 528
    FATRegionSize 				= NumberOfFATs * SectorsPerFAT;							// 490
	DataRegionSize				= TotalNumberOfSectors - (ReservedSectors + FATRegionSize + RootDirectoryRegionSize);

	#ifdef DEBUG_FAT
		rprintfCRLF();
		rprintfProgStrM("OEM Name        : ");	rprintfStrLen(F16.BootSec.bsOEMName, 0, 8 );				rprintfCRLF();
		rprintfProgStrM("Bytes Per Sector: ");	rprintfNum(10,6, FALSE,' ',F16.BootSec.bsBytesPerSec);		rprintfCRLF();
		rprintfProgStrM("Sector Per Clust: ");	rprintfNum(10,6, FALSE,' ',F16.BootSec.bsSecPerClus);		rprintfCRLF();
		rprintfProgStrM("Reserved SecCnt : ");	rprintfNum(10,6, FALSE,' ',F16.BootSec.bsRsvdSecCnt);		rprintfCRLF();
		rprintfProgStrM("Number Of FAT   : ");	rprintfNum(10,6, FALSE,' ',F16.BootSec.bsNumFATs);			rprintfCRLF();
		rprintfProgStrM("Root Dir Entries: ");	rprintfNum(10,6, FALSE,' ',F16.BootSec.bsRootEntCnt);		rprintfCRLF();
		rprintfProgStrM("Total Sector 16 : ");	rprintfNum(10,6, FALSE,' ',F16.BootSec.bsTotSec16);		rprintfCRLF();
		rprintfProgStrM("Media           : ");
			switch (F16.BootSec.bsMedia)
			{
				// TODO expand further cases
				case 0xf8:
						rprintfProgStrM("Found: Hard disk. DOS version 2.0 \r\n");
						break;
				default:
						rprintfProgStrM("Found: No Partition!\r\n");
						break;
			}

		rprintfProgStrM("Total Sector 32 : ");	rprintfNum(10,6, FALSE,' ',F16.BootSec.bsTotSec32);		rprintfCRLF();
		rprintfProgStrM("Sector Per FAT  : ");	rprintfNum(10,6, FALSE,' ',F16.BootSec.bsNrSeProFAT);		rprintfCRLF();
		rprintfProgStrM("Volume Label    : ");	rprintfStrLen(F16.BootSec.bsVolLbl, 0, 11 );				rprintfCRLF();
		rprintfProgStrM("Filesystem Type : ");	rprintfStrLen(F16.BootSec.bsFileSysType, 0, 8);			rprintfCRLF();
		rprintfCRLF();

		rprintfProgStrM("RootDirectoryRegionStart: ");	rprintfNum(10,6, FALSE,' ',RootDirectoryRegionStart);	rprintfCRLF();
		rprintfProgStrM("DataRegionStart         : ");	rprintfNum(10,6, FALSE,' ',DataRegionStart);			rprintfCRLF();
		rprintfProgStrM("FATRegionSize           : ");	rprintfNum(10,6, FALSE,' ',FATRegionSize);				rprintfCRLF();
		rprintfProgStrM("RootDirectoryRegionSize : ");	rprintfNum(10,6, FALSE,' ',RootDirectoryRegionSize);	rprintfCRLF();
		rprintfProgStrM("DataRegionSize          : ");	rprintfNum(10,6, FALSE,' ',DataRegionSize);			rprintfCRLF();
		rprintfCRLF();
	#endif

	return 0;
}



//####################################################################################
void FAT16_Search (  	char   *FilePathName,		// In: 		File name to find
						int8_t SelectMode	)	  	// In: 		Select operation: overwrite or contiue data
//####################################################################################
{
	#ifdef DEBUG_FAT
		uint32_t notused = 0;
	#endif
	int8_t ret = TRUE;

	// Reset varaibles and buffers
	FATSectorAddress_old = 0;
	glbl_FAT_Entry = 0;		// FAT entry
	glbl_FileSize = 0;		// filesize
	glbl_DataSector = 0;	// Current data sector
	glbl_Sector = 0;		// Sector which contains file size inforation
	glbl_SubSector = 0;		// Which of the 16 32byte long SubSectors contains the file size
	glbl_Attributes = 0; 	// Attribute Dir, archive, hidden, system, volume ...
	memset( F16_BUFFER_ONE, 0x00 , 512 );				// Clear buffer
	memset( F16_BUFFER_TWO, 0x00 , 512 );				// Clear buffer
	memset( NameBuffer, 0x00 , NAMEBUFFERSIZE );		// Clear buffer
	memset( NameBufferShort, 0x00 , 8 );				// Clear buffer
	memset( NameBufferExt, 0x00 , 3 );					// Clear buffer
	memset( Name2FindBuffer, 0x00 , NAMEBUFFERSIZE );	// Clear buffer



	#ifdef DEBUG_FAT
		rprintfProgStrM("Searching for >"); rprintfStrLen(FilePathName, 0, 64 );
		if( SelectMode == OVERWRITE) rprintfProgStrM(" (OVERWRITE)");
		if( SelectMode == CONTINUE) rprintfProgStrM(" (CONTINUE)");
		rprintfCRLF();
	#endif

	ret = fatSearch_File( 	FilePathName,		// In: 		File name to find
							&glbl_FAT_Entry,  	// In/Ret:  FAT entry where data starts
							&glbl_FileSize, 	// Return: 	Return filesize
							&glbl_Sector, 		// Return: 	Sector which contains file size inforation
							&glbl_SubSector,	// Return: 	Return which of the 16 32byte long SubSectors contains the file size
							&glbl_DataSector,  	// Return:  Return sector where data starts
							&glbl_Attributes, 	// Return: 	Return Attribute Dir, archive, hidden, system, volume ...
							F16_BUFFER_ONE );	// In: 		Buffer to use

	// empty name buffer for next use
	memset( FilePathName, 0x00 , 64 );

	if( (ret == TRUE)  &&  (glbl_Attributes == ATTR_ARCHIVE) )
	{
		if( SelectMode == OVERWRITE )
		{
			// delete fat entries of current file from "glbl_FAT_Entry" on until end of file and init File
			fat_Delete( &glbl_FAT_Entry,		// In/Ret:  FAT entry where data starts
						&glbl_FileSize,   		// Return: 	Return filesize
						&glbl_Sector,			// In: 		Sector which contains file size inforation
						&glbl_SubSector, 		// In: 		Return which of the 16 32byte long SubSectors contains the file size
						&glbl_DataSector, 		// Return:	Sector where data starts
						F16_BUFFER_TWO );		// In:		Select buffer to use
		}

		// if filesize and fat entry is zero (means that file hasn't been used until now)
		// search fat address, where data can start
		fat_Init_File 	(	&glbl_FAT_Entry,	// In/Ret:  FAT entry where data starts
							&glbl_FileSize,    	// In: 		Filesize
							&glbl_Sector,		// In: 		Sector which contains file size inforation
							&glbl_SubSector,	// In: 		Return which of the 16 32byte long SubSectors contains the file size
							&glbl_DataSector,	// Return:	Sector where data starts
							F16_BUFFER_ONE);	// In:		Select buffer to use

		#ifdef DEBUG_FAT
			rprintfCRLF();
			rprintfProgStrM("Data starts at FAT address  : ");	rprintfNum( 10,6, FALSE,' ', glbl_FAT_Entry );	   	rprintfCRLF();
			rprintfProgStrM("Sector containing file info : ");	rprintfNum( 10,6, FALSE,' ', glbl_Sector ); 		rprintfCRLF();
			rprintfProgStrM("Data starts in sector       : ");	rprintfNum( 10,6, FALSE,' ', glbl_DataSector ); 	rprintfCRLF();
			rprintfProgStrM("FileSize [uint8_t]          : ");	rprintfNum( 10,6, FALSE,' ', glbl_FileSize );	   	rprintfCRLF();
			fatRead_File( 	&glbl_FAT_Entry, 	// In:  	Start clusters of file
							&notused, 			// In:
							&glbl_FileSize, 	// In:
							F16_BUFFER_ONE );	// In:		Select buffer to use
		#endif


		if( SelectMode == CONTINUE ){
			#ifdef DEBUG_FAT
				rprintfProgStrM("\r\n----- Searching end of file -----\r\n");
			#endif

			// load last sector in current file into F16_BUFFER_ONE
			fatWrite_Continue( 	&glbl_FAT_Entry, 	// In/Ret:  FAT entry where data starts
								&glbl_DataSector, 	// Return:  Current data sector address
								&glbl_FileSize,    	// Return: 	Return filesize
								F16_BUFFER_ONE );	// In:		Select buffer to use

			#ifdef DEBUG_FAT
				rprintfCRLF();
				rprintfProgStrM("Data ends in FAT address: ");	rprintfNum( 10,6, FALSE,' ', glbl_FAT_Entry );	   	rprintfCRLF();
				rprintfProgStrM("Data ends in sector     : ");	rprintfNum( 10,6, FALSE,' ', glbl_DataSector ); 	rprintfCRLF();
				rprintfProgStrM("FileSize                : ");	rprintfNum( 10,6, FALSE,' ', glbl_FileSize );	   	rprintfCRLF();
				rprintfProgStrM("Loading last sector of file ->"); rprintfCRLF();
				debugPrintHexTable(0x200, F16_BUFFER_ONE);
			#endif
		}
	}
	else{
		#ifdef DEBUG_FAT
			rprintfProgStrM("\r\n----- File not found -----\r\n");
		#endif
	}

}


//############################################################################
void fatWrite_Continue (	uint16_t *FATEntry,		// In/Ret:  FAT entry where data starts
							uint32_t *SectorAddress,	// Return:  Current data sector address
							uint32_t *FileSize,    	// Return: 	Return filesize
							uint8_t  *Buffer)			// In:		Select buffer to use
//############################################################################
{
	uint16_t FAT_Entry_Temp = 0;
	uint16_t offset = 0;

	// find at which sector in current cluster the data ends
	offset = *FileSize / BytePerSector;
	offset %= SectorsPerCluster;

	// search end of file to continue to save data there
	while(*FATEntry != 0xFFFF)
	{
		FAT_Entry_Temp = *FATEntry;
		fatLoad( FATEntry, SectorAddress, F16_BUFFER_TWO ); // F16_BUFFER_TWO
	}
	*FATEntry = FAT_Entry_Temp;
	*SectorAddress += offset;
	// Sector_Address_Temp contains only the address of the first sector in a cluster
	// 'offset' contains an offset. So the exact sector address in a cluster can be determined
	// read last sector of curent file, which contains data
	mmcRead( *SectorAddress , Buffer );
}


//############################################################################
void fat_Delete 		(	uint16_t *FATEntry,		// In/Ret:  FAT entry where data starts
							uint32_t *FileSize,    	// Return: 	Return filesize
							uint32_t *Sector,			// In: 		Sector which contains file size inforation
							uint8_t  *SubSector,		// In: 		Return which of the 16 32byte long SubSectors contains the file size
							uint32_t *DataSector,		// Return:	Sector where data starts
							uint8_t  *Buffer)			// In:		Select buffer to use
//############################################################################
{
	uint16_t FATSectorAddress;
	uint16_t Temp;

	if(*FileSize != 0)
	{
		#ifdef DEBUG_FAT
			// deleting file content by deleting FAT addresses
			rprintfProgStrM("\r\n----- Deleting file content -----\r\n");
		#endif

		// Calculate which FAT-sector has to be read depending on FAT-entry
		FATSectorAddress = 	((*FATEntry*2) / BytePerSector) + FATRegionStart;	// ((8*2)/512) + 6 = 6
		mmcRead( FATSectorAddress , Buffer );
		FATSectorAddress_old = FATSectorAddress;

		do{
			Temp = FAT_Buf2[*FATEntry]; 	// load next FAT-address from current FAT-address
			FAT_Buf2[*FATEntry] = 0;		// clear contents in current FAT-address
			*FATEntry = Temp; 				// prepare next FAT-address

			// Calculate which FAT-sector has to be read depending on FAT-entry
			FATSectorAddress =  ((*FATEntry*2) / BytePerSector) + FATRegionStart;	// ((8*2)/512) + 6 = 6

			// If new FAT-entry is in new FAT-sector then save old FAT-sector at first and then load new FAT-sector
			if (FATSectorAddress != FATSectorAddress_old)

⌨️ 快捷键说明

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