📄 fatlib.c
字号:
/**
* 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 + -