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

📄 fatlib.c

📁 The high portable FAT filesystem library for embedded system.
💻 C
📖 第 1 页 / 共 3 页
字号:
/**
 *	FATLib.c:		implementation of the FATLib class.
 *	class FATLib:	a portable FAT decoder class which is hardware independent.
 *			All hardware specific operations are abstracted with the
 *			class HALayer.  The FATLib class operates with only the buffer
 *			which it passes to the class HALayer
 *
 *	Author:	Ivan Sham
 *	Date: July 1, 2004
 *	Version: 2.0
 *	Note: Developed for William Hue and Pete Rizun
 *
 *****************************************************************
 *  Change Log
 *----------------------------------------------------------------
 *  Date    |   Author          | Reason for change
 *----------------------------------------------------------------
 * Aug31/04     William Hue       Changed char types to
 *                                unsigned char.
 *
 * Jul18/04     Alex Jiang        Made local variables and functions
 *                                static and moved to fatlib.c.
 *                                Prefixed public functions with
 *                                "fat_".
 *
 * Jan02/05     William Hue       Various bugfixes and clean-up for
 *                                Circuit Cellar article.
 **/

#include "FATLib.h"


//------------------
// private member variables:
//------------------

/**
 *	defines the structure of a opened file
 **/
typedef struct
{
	unsigned long currentCluster;
	unsigned int byteCount;	
	unsigned long firstCluster;    
    unsigned long fileSize;
    unsigned long dirLocation;    
    unsigned char sectorCount;    
	signed char fileHandle;
    unsigned char updateDir;
} file;


/**
 *	array of size BUFFER_SIZE of pointers to nodes of
 *	struct file opened for reading
 **/
static file openedRead[BUFFER_SIZE];

/**
 *	array of size BUFFER_SIZE of pointers to nodes of
 *	struct file opened for writing
 **/
static file openedWrite[BUFFER_SIZE];

/**
 *	sectors offset from absolute sector 0 in the MMC/SD.
 *  All operations with the MMC/SD card are offseted with
 *	this variable in a microcontroller application
 *	****this equals zero in Windows application
 **/
unsigned long sectorZero;

/**
 *	the sector in the MMC/SD card where data starts.
 *	This is right after the root directory sectors in FAT16
 **/
static unsigned long dataStarts;

/**
 *	the first sector where entries in the root directory is
 *	stored in FAT16.
 **/
static unsigned long rootDirectory;

/**
 *	the number of sectors per File Allocation Table (FAT)
 **/
static unsigned long sectorsPerFAT;

/**
 *	the number of sectors per cluster for the MMC/SD card
 **/
static unsigned int sectorsPerCluster;

/**
 *	the number of reserved sectors in the MMC/SD card
 **/
static unsigned int reservedSectors;

/**
 *	the number of File Allocation Table (FAT) on the MMC/SD.
 *	this is usually 2
 **/
static unsigned int numOfFATs;

/**
 *	the number of sectors in the section for root directory
 *	entries.
 **/
static unsigned int rootSectors;

/**
 *	the file system of which the MMC/SD card is formatted in
 *
 *	fileSys == 0  -> Unknown file system
 *	fileSys == 1  -> FAT16
 **/
static unsigned char fileSys;

/**
 *	number of files opened for reading
 **/
static unsigned char filesOpenedRead;

/**
 *	number of files opened for writing
 **/
static unsigned char filesOpenedWrite;

/**
 *	FAT sector number last searched for an empty cluster
 **/
static unsigned long int last_FAT_sector_searched_for_empty;


/* Local Prototypes */
static void FATLibInit();
static unsigned char identifyFileSystem(unsigned char *buf);
static signed char readFileSystemInfo(unsigned char *buf);
static unsigned long findEmptyCluster(unsigned char *buf);
static unsigned long getNextFAT(unsigned long cluster, unsigned char *buf);
static void updateFAT(unsigned long oldCluster, unsigned long newCluster, unsigned char *buf);
static signed char getFileHandle();
static unsigned long getFirstCluster(const char * pathname, unsigned long cluster, unsigned char *buf, boolean control, unsigned long * fileSize);
static unsigned long createNewEntry( const char * entryName, unsigned long cluster, unsigned char *buf, boolean control);
static signed char findFileIndex(signed char handle);
static signed char openedCheck(unsigned long cluster);
static void updateDirectory(unsigned long dirCluster, unsigned long firstCluster, unsigned long filesize, unsigned char *buf);
static void updateAccessDate(unsigned long dirCluster, unsigned long firstCluster, unsigned char *buf);


/**
 *	default constructor
 **/
static void FATLibInit()
{
	unsigned char i;

	sectorZero = 0;
	filesOpenedRead = 0;
	filesOpenedWrite = 0;
	fileSys = UNKNOWN;
	for(i = 0; i < BUFFER_SIZE;i++)
	{
		openedRead[i].fileHandle = -1;
		openedWrite[i].fileHandle = -1;
	}
    last_FAT_sector_searched_for_empty = 0;
}

/**
 *	initialize the system
 *
 *	@return	0			UNKNOWN file system
 *	@return	1			FAT16 file system
 *	@return 3			could not set block length
 *	@return	4			could not initialize memory card
 **/
unsigned char fat_initialize(void)
{
    unsigned char buf[SECTOR_SIZE];

	FATLibInit();
	HALayerInit();
	if(memCardInit())
	{
		if(setBLockLength())
		{
			sectorZero = getPartitionOffset();
		}
		else
		{
			return 3;
		}
	}
	else
	{
		return 4;
	}
	identifyFileSystem(buf);
	readFileSystemInfo(buf);
	return fileSys;
}

/**
 *	identifies the file system used by the MMC/SD card
 *
 *	@param	buf			the buffer to be used to access the MMC/SD card
 *
 *	@return	0			for unknow file system
 *	@return	1			for FAT16
 **/
static unsigned char identifyFileSystem(unsigned char *buf)
{
	readSector(0, buf);
	fileSys = UNKNOWN;	
	if( (buf[54] == 'F') &&
		(buf[55] == 'A') &&
		(buf[56] == 'T') &&
		(buf[57] == '1') &&
		(buf[58] == '6'))
	{
		fileSys = FAT16;		
	}
	return fileSys;
}

/**
 *	initialize variables for file system
 *
 *	@param	buf		the buffer to be used to access the MMC/SD card
 *
 *	@return	0			variables sucessfully initialized
 *	@return	-1			unknown file system
 *	@return -2			error reading from MMC/SD card 
 **/
static signed char readFileSystemInfo(unsigned char *buf)
{	
	unsigned int maxRootEntry = 0;

	if(fileSys == UNKNOWN)
	{
		return -1;
	}
	if(readSector(0, buf) < SECTOR_SIZE)
	{
		return -2;
	}

	sectorsPerCluster = buf[13];
	reservedSectors = buf[14];
	reservedSectors |= (unsigned long int)buf[15] << 8;
	numOfFATs = buf[16];

	if(fileSys == FAT16)
	{
		maxRootEntry = buf[17];
		maxRootEntry |= (unsigned long int)buf[18] << 8;
		sectorsPerFAT = buf[22];
		sectorsPerFAT |= (unsigned long int)buf[23] << 8;
	} else
	{			
		sectorsPerFAT = buf[36];
		sectorsPerFAT |= (unsigned long int)buf[37] << 8;
		sectorsPerFAT |= (unsigned long int)buf[38] << 16;
		sectorsPerFAT |= (unsigned long int)buf[39] << 24;		
	}
	rootDirectory = reservedSectors + sectorsPerFAT * numOfFATs;
	rootSectors = ( maxRootEntry / SECTOR_SIZE ) * 32;
	dataStarts = rootDirectory + rootSectors;
	return 0;
}

/**
 *	finds an unoccupied cluster in the FAT and returns the location.
 *	The previously empty location in the FAT will be changed to a
 *	end of file marker
 *
 *	@pre	file system is properly initialized and fileSys != UNKNOWN
 *
 *	@param	buf			the buffer to be used to access the MMC/SD card
 *
 *	@return	0			no more clusters available (disk full)
 *	@return	...			location of empty cluster
 **/
static unsigned long findEmptyCluster(unsigned char *buf)
{
	unsigned long sector, end_sector;
	unsigned long returnCluster;
	unsigned int i;
	unsigned char j;

    if (last_FAT_sector_searched_for_empty == 0)
    {
        sector = reservedSectors;
    }
    else
    {
        sector = last_FAT_sector_searched_for_empty;
    }
    end_sector = reservedSectors + sectorsPerFAT;

    if(fileSys == FAT16)
    {
        // 256 entries in a 512-byte FAT sector
        returnCluster = (sector - reservedSectors) * 256;
    }
    else
    {
        return 0;
    }

    while (TRUE)
    {
        while(sector < end_sector)
        {
            readSector(sector, buf);
            for(i = 0; i < SECTOR_SIZE; i += 2*fileSys)
            {
                if(buf[i] == 0x00 && buf[i+1] == 0)                   
                {
                    // This cluster is unused.
                    buf[i] = 0xFF;
                    buf[i + 1] = 0xFF;
                  	
                    for(j = 0; j < numOfFATs; j++)
                    {
                        writeSector(sector + (j * sectorsPerFAT), buf);
                    }

                    // Remember where we found it:
                    last_FAT_sector_searched_for_empty = sector;

                    return returnCluster;
                }
                returnCluster++;
            }
            sector++;
        }

        // We reached the end of the FAT.  Should we wrap around and search from
        // the beginning?
        if (last_FAT_sector_searched_for_empty > reservedSectors)
        {
            // Yes.
            sector = reservedSectors;
            end_sector = last_FAT_sector_searched_for_empty;
            last_FAT_sector_searched_for_empty = 0;
            returnCluster = 0;
            // We will take the else block next time if we don't find anything.
        }
        else
        {
            return 0; 
        }
    }
}

/**
 *	gets the next cluster in the FAT chain given the current cluster
 *
 *	@param	cluster		the current cluster
 *	@param	buf			the buffer to be used to access the MMC/SD card
 *
 *	@return	...			the location of the next cluster or end of file marker 
 **/
static unsigned long getNextFAT(unsigned long cluster, unsigned char *buf)
{
	unsigned long sectorOffset;
	unsigned int byteOffset;
	
	cluster = 2 * cluster * fileSys;
	sectorOffset = (cluster >> 9);
	sectorOffset = sectorOffset + reservedSectors;
	byteOffset = cluster & 0x01FF;
	readSector(sectorOffset, buf);
	cluster = buf[byteOffset];
	cluster |= (unsigned long int)buf[byteOffset + 1] << 8;
	
	return cluster;
}

/**
 *	updates the FAT from in location of oldCluster and place the newCluster in 
 *	that location
 *
 *	@param	buf			the buffer to be used to access the MMC/SD card
 *	@param	oldCluster	the location of the cluster to be replaced 
 *	@param	newCluster	the new location
 **/
static void updateFAT(unsigned long oldCluster, unsigned long newCluster, unsigned char *buf)
{
	unsigned long sectorOffset;
	unsigned int byteOffset;
	unsigned char j;

	oldCluster = 2 * oldCluster * fileSys;
	sectorOffset = (oldCluster >> 9);
	sectorOffset = sectorOffset + reservedSectors;
	byteOffset = oldCluster & 0x01FF;
	readSector(sectorOffset, buf);
	buf[byteOffset] = newCluster & 0x000000FF;
	buf[byteOffset+1] = (newCluster & 0x0000FF00) >> 8;	
	
	for(j = 0; j < numOfFATs; j++)
	{
		writeSector(sectorOffset + (j * sectorsPerFAT), buf);
	}
}

/**
 *	gets the next available file handle 
 *	Note:  all files have unique handle (no overlap between read and write)
 *
 *	@return	-10			no more file handles available
 *	@return ...			file handle
 **/
static signed char getFileHandle()
{
	signed char i = 0;
	signed char newHandle = 0;
	while(newHandle < 2 * BUFFER_SIZE)
	{
		i = 0;
		while((i < BUFFER_SIZE) && (i >= 0))
		{
			if(openedRead[i].fileHandle != -1)
			{				
				if(openedRead[i].fileHandle==newHandle)
				{
					i = -128;
				}
			}
			if((openedWrite[i].fileHandle != -1)&&(i>=0))
			{
				if(openedWrite[i].fileHandle==newHandle)
				{
					i = -128;
				}
			}
			i++;
		}
		if(i == BUFFER_SIZE)
		{
			return newHandle;
		}
		newHandle++;
	}
	return -10;
}

/**
 *	closes the file indicated by the input
 *	
 *	@param	fileHandle	handle of file to be closed
 *	
 *	@return	0			file sucessfully closed
 *	@return	-1			invalid file handle
 *	@return	-2			invalid file system
 **/
signed char fat_close(signed char fileHandle)
{
	unsigned char i;

	if(detectCard() == FALSE)
	{
		return -10;
	}
	if(fileSys == UNKNOWN)
	{
		return -2;
	}

    fat_flush();

	for(i = 0; i < filesOpenedRead; i++)
	{
		if(openedRead[i].fileHandle == fileHandle)
		{

⌨️ 快捷键说明

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