3//********************************************************
// **** ROUTINES FOR FAT32
IMPLEMATATION OF SD CARD *****
//********************************************************
//Controller: ATmega8 (Clock: 8
Mhz-internal)
//Compiler:
AVR-GCC
//Version : 2.1
//Author: CC Dharmani,
Chennai (India)
// http://www.dharmanitech.com/
//Date: 26 Feb 2009 - updated
13 Sep 2009
//********************************************************
//Link to the Post: http://www.dharmanitech.com/2009/01/sd-card-interfacing-with-atmega8-fat32.html
//**************************************************
// ***** HEADER FILE : FAT32.h
******
//**************************************************
#ifndef
_FAT32_H_
#define _FAT32_H_
//Structure to access Master
Boot Record for getting info about partioions
struct
MBRinfo_Structure{
unsigned char
nothing[446]; //ignore, placed here to fill
the gap in the structure
unsigned
char partitionData[64]; //partition records
(16x4)
unsigned
int
signature; //0xaa55
};
//Structure to access info of
the first partioion of the disk
struct
partitionInfo_Structure{
unsigned
char
status;
//0x80 - active
partition
unsigned char
headStart;
//starting
head
unsigned
int
cylSectStart;
//starting
cylinder and sector
unsigned
char
type;
//partition type
unsigned
char
headEnd;
//ending head of
the partition
unsigned
int
cylSectEnd;
//ending cylinder
and sector
unsigned
long
firstSector;
//total sectors
between MBR & the first sector of the partition
unsigned
long
sectorsTotal;
//size of this
partition in sectors
};
//Structure to access boot
sector data
struct
BS_Structure{
unsigned char jumpBoot[3];
//default:
0x009000EB
unsigned char
OEMName[8];
unsigned int bytesPerSector; //deafault:
512
unsigned char
sectorPerCluster;
unsigned int
reservedSectorCount;
unsigned char
numberofFATs;
unsigned int
rootEntryCount;
unsigned int totalSectors_F16;
//must be 0 for
FAT32
unsigned char
mediaType;
unsigned int FATsize_F16; //must be 0
for FAT32
unsigned
int sectorsPerTrack;
unsigned int
numberofHeads;
unsigned long hiddenSectors;
unsigned
long totalSectors_F32;
unsigned long FATsize_F32;
//count of sectors occupied by one FAT
unsigned
int extFlags;
unsigned int FSversion;
//0x0000 (defines version
0.0)
unsigned long
rootCluster; //first cluster of root
directory (=2)
unsigned
int FSinfo;
//sector number of FSinfo structure (=1)
unsigned
int BackupBootSector;
unsigned char
reserved[12];
unsigned char driveNumber;
unsigned
char reserved1;
unsigned char
bootSignature;
unsigned long volumeID;
unsigned
char volumeLabel[11]; //"NO NAME "
unsigned char
fileSystemType[8]; //"FAT32"
unsigned char
bootData[420];
unsigned int bootEndSignature;
//0xaa55
};
//Structure to access FSinfo
sector data
struct
FSInfo_Structure
{
unsigned long leadSignature;
//0x41615252
unsigned char
reserved1[480];
unsigned long structureSignature; //0x61417272
unsigned long
freeClusterCount; //initial:
0xffffffff
unsigned long
nextFreeCluster; //initial:
0xffffffff
unsigned char
reserved2[12];
unsigned long trailSignature;
//0xaa550000
};
//Structure to access Directory
Entry in the FAT
struct
dir_Structure{
unsigned char name[11];
unsigned
char attrib;
//file attributes
unsigned char
NTreserved; //always
0
unsigned char
timeTenth; //tenths of
seconds, set to 0 here
unsigned
int createTime; //time file
was created
unsigned
int createDate; //date file
was created
unsigned
int lastAccessDate;
unsigned int
firstClusterHI; //higher word of the first
cluster number
unsigned
int writeTime; //time of
last write
unsigned
int writeDate; //date of last
write
unsigned
int firstClusterLO; //lower word of the first
cluster number
unsigned long
fileSize;
//size of file in bytes
};
//Attribute definitions for
file/directory
#define
ATTR_READ_ONLY 0x01
#define
ATTR_HIDDEN 0x02
#define
ATTR_SYSTEM 0x04
#define
ATTR_VOLUME_ID 0x08
#define
ATTR_DIRECTORY 0x10
#define
ATTR_ARCHIVE 0x20
#define
ATTR_LONG_NAME 0x0f
#define
DIR_ENTRY_SIZE 0x32
#define
EMPTY
0x00
#define
DELETED
0xe5
#define GET 0
#define
SET 1
#define
READ 0
#define VERIFY
1
#define
ADD 0
#define
REMOVE 1
#define TOTAL_FREE 1
#define
NEXT_FREE 2
#define GET_LIST 0
#define
GET_FILE 1
#define
DELETE 2
#define
EOF
0x0fffffff
//************* external
variables *************
extern
volatile unsigned char buffer[512];
extern
volatile unsigned long startBlock;
extern
volatile unsigned long firstDataSector, rootCluster,
totalClusters;
extern volatile unsigned int
bytesPerSector, sectorPerCluster, reservedSectorCount;
//global flag to keep track of
free cluster count updating in FSinfo sector
unsigned char
freeClusterCountUpdated;
unsigned long
unusedSectors;
//************* functions
*************
unsigned char
getBootSectorData (void);
unsigned long
getFirstSector(unsigned long clusterNumber);
unsigned
long getSetFreeCluster(unsigned char totOrNext,
unsigned char get_set, unsigned long
FSEntry);
struct dir_Structure* findFiles (unsigned char
flag, unsigned char *fileName);
unsigned long
getSetNextCluster (unsigned long clusterNumber,unsigned
char get_set,unsigned long
clusterEntry);
unsigned char readFile (unsigned
char flag, unsigned char *fileName);
unsigned
char convertFileName (unsigned char
*fileName);
void createFile (unsigned char
*fileName);
unsigned long searchNextFreeCluster
(unsigned long startCluster);
void memoryStatistics
(void);
void displayMemory (unsigned long
memory);
void deleteFile (unsigned char
*fileName);
void freeMemoryUpdate (unsigned char flag,
unsigned long size);
#endif
//*******************************************************
// **** ROUTINES FOR FAT32
IMPLEMATATION OF SD CARD ****
//*******************************************************
//Controller: ATmega8 (Clock: 8
Mhz-internal)
//Compiler:
AVR-GCC
//Version : 2.0
//Author: CC Dharmani,
Chennai (India)
// http://www.dharmanitech.com/
//Date: 26 Feb
2009
//*******************************************************
//Link to the Post: http://www.dharmanitech.com/2009/01/sd-card-interfacing-with-atmega8-fat32.html
//**************************************************
// ***** SOURCE FILE : FAT32.c
******
//**************************************************
#include
<avr/io.h>
#include <avr/pgmspace.h>
#include
"FAT32.h"
#include "UART_routines.h"
#include
"SD_routines.h"
//***************************************************************************
//Function: to read data from
boot sector of SD card, to determine important
//parameters like
bytesPerSector, sectorsPerCluster etc.
//Arguments:
none
//return:
none
//***************************************************************************
unsigned char
getBootSectorData (void)
{
struct BS_Structure *bpb;
//mapping the
buffer onto the structure
struct
MBRinfo_Structure *mbr;
struct partitionInfo_Structure
*partition;
unsigned long dataSectors;
unusedSectors =
0;
SD_readSingleBlock(0);
bpb = (struct BS_Structure
*)buffer;
if(bpb->jumpBoot[0]!=0xE9 &&
bpb->jumpBoot[0]!=0xEB) //check if it is boot
sector
{
mbr =
(struct MBRinfo_Structure *)
buffer; //if it is not boot sector, it
must be MBR
if(mbr->signature != 0xaa55) return
1;
//if it is not
even MBR then it's not FAT32
partition = (struct partitionInfo_Structure
*)(mbr->partitionData);//first partition
unusedSectors =
partition->firstSector; //the unused sectors, hidden to
the FAT
SD_readSingleBlock(partition->firstSector);//read the bpb
sector
bpb = (struct BS_Structure *)buffer;
if(bpb->jumpBoot[0]!=0xE9 && bpb->jumpBoot[0]!=0xEB)
return 1;
}
bytesPerSector =
bpb->bytesPerSector;
sectorPerCluster =
bpb->sectorPerCluster;
reservedSectorCount =
bpb->reservedSectorCount;
rootCluster
= bpb->rootCluster;// + (sector /
sectorPerCluster) +1;
firstDataSector
= bpb->hiddenSectors + reservedSectorCount +
(bpb->numberofFATs * bpb->FATsize_F32);
dataSectors =
bpb->totalSectors_F32 - bpb->reservedSectorCount - ( bpb->numberofFATs
* bpb->FATsize_F32);
totalClusters = dataSectors /
sectorPerCluster;
if((getSetFreeCluster (TOTAL_FREE, GET, 0)) >
totalClusters) //check if FSinfo free clusters
count is valid
freeClusterCountUpdated = 0;
else
freeClusterCountUpdated =
1;
return 0;
}
//***************************************************************************
//Function: to calculate first
sector address of any given cluster
//Arguments: cluster number for
which first sector is to be found
//return: first sector
address
//***************************************************************************
unsigned long
getFirstSector(unsigned long clusterNumber)
{
return (((clusterNumber - 2) * sectorPerCluster) +
firstDataSector);
}
//***************************************************************************
//Function: get cluster entry
value from FAT to find out the next cluster in the chain
//or set new cluster entry in
FAT
//Arguments: 1. current cluster
number, 2. get_set (=GET, if next cluster is to be found or =
SET,
//if next
cluster is to be set 3. next cluster number, if argument#2 = SET, else
0
//return:
next cluster number, if if argument#2 = GET, else 0
//****************************************************************************
unsigned long
getSetNextCluster (unsigned long
clusterNumber,
unsigned char
get_set,
unsigned long clusterEntry)
{
unsigned
int FATEntryOffset;
unsigned long
*FATEntryValue;
unsigned long
FATEntrySector;
unsigned char retry = 0;
//get sector number of the
cluster entry in the FAT
FATEntrySector =
unusedSectors + reservedSectorCount + ((clusterNumber * 4) / bytesPerSector)
;
//get the
offset address in that sector number
FATEntryOffset =
(unsigned int) ((clusterNumber * 4) %
bytesPerSector);
//read the sector into a
buffer
while(retry
<10)
{ if(!SD_readSingleBlock(FATEntrySector)) break;
retry++;}
//get the cluster address from
the buffer
FATEntryValue =
(unsigned long *)
&buffer[FATEntryOffset];
if(get_set == GET)
return ((*FATEntryValue) & 0x0fffffff);
*FATEntryValue =
clusterEntry; //for setting new value in
cluster entry in FAT
SD_writeSingleBlock(FATEntrySector);
return
(0);
}
//********************************************************************************************
//Function: to get or set next
free cluster or total free clusters in FSinfo sector of SD card
//Arguments: 1.flag:TOTAL_FREE
or NEXT_FREE,
//
2.flag: GET or SET
//
3.new FS entry, when argument2 is SET; or 0, when argument2 is
GET
//return:
-next free cluster, if arg1 is NEXT_FREE & arg2 is GET
//
-total number of free clusters, if arg1 is TOTAL_FREE & arg2 is
GET
//
-0xffffffff, if any error or if arg2 is SET
//********************************************************************************************
unsigned long
getSetFreeCluster(unsigned char totOrNext, unsigned
char get_set, unsigned long FSEntry)
{
struct
FSInfo_Structure *FS = (struct FSInfo_Structure *)
&buffer;
unsigned char
error;
SD_readSingleBlock(unusedSectors +
1);
if((FS->leadSignature != 0x41615252) ||
(FS->structureSignature != 0x61417272) || (FS->trailSignature
!=0xaa550000))
return
0xffffffff;
if(get_set == GET)
{
if(totOrNext == TOTAL_FREE)
return(FS->freeClusterCount);
else // when totOrNext =
NEXT_FREE
return(FS->nextFreeCluster);
}
else
{
if(totOrNext == TOTAL_FREE)
FS->freeClusterCount = FSEntry;
else // when totOrNext =
NEXT_FREE
FS->nextFreeCluster = FSEntry;
error =
SD_writeSingleBlock(unusedSectors + 1); //update FSinfo
}
return
0xffffffff;
}
//***************************************************************************
//Function: to get DIR/FILE
list or a single file address (cluster number) or to delete a specified
file
//Arguments: #1 - flag:
GET_LIST, GET_FILE or DELETE #2 - pointer to file name (0 if arg#1 is
GET_LIST)
//return: first cluster of the
file, if flag = GET_FILE
//
print file/dir list of the root directory, if flag = GET_LIST
//
Delete the file mentioned in arg#2, if flag = DELETE
//****************************************************************************
struct
dir_Structure* findFiles (unsigned char flag, unsigned
char *fileName)
{
unsigned long cluster, sector,
firstSector, firstCluster, nextCluster;
struct dir_Structure
*dir;
unsigned int i;
unsigned char
j;
cluster = rootCluster; //root cluster
while(1)
{
firstSector = getFirstSector (cluster);
for(sector =
0; sector < sectorPerCluster; sector++)
{
SD_readSingleBlock (firstSector +
sector);
for(i=0; i<bytesPerSector; i+=32)
{
dir = (struct dir_Structure *)
&buffer[i];
if(dir->name[0] == EMPTY) //indicates end of the file
list of the directory
{
if((flag ==
GET_FILE) || (flag ==
DELETE))
transmitString_F(PSTR("File does not
exist!"));
return 0;
}
if((dir->name[0] != DELETED) &&
(dir->attrib !=
ATTR_LONG_NAME))
{
if((flag ==
GET_FILE) || (flag ==
DELETE))
{
for(j=0; j<11;
j++)
if(dir->name[j] != fileName[j])
break;
if(j ==
11)
{
if(flag ==
GET_FILE)
return
(dir);
else //when flag =
DELETE
{
TX_NEWLINE;
transmitString_F(PSTR("Deleting.."));
TX_NEWLINE;
TX_NEWLINE;
firstCluster = (((unsigned long) dir->firstClusterHI) <<
16) |
dir->firstClusterLO;
//mark file as
'deleted' in FAT table
dir->name[0] =
DELETED;
SD_writeSingleBlock
(firstSector+sector);
freeMemoryUpdate (ADD,
dir->fileSize);
//update next free
cluster entry in FSinfo sector
cluster = getSetFreeCluster (NEXT_FREE, GET,
0);
if(firstCluster <
cluster)
getSetFreeCluster (NEXT_FREE, SET,
firstCluster);
//mark all the
clusters allocated to the file as 'free'
while(1)
{
nextCluster = getSetNextCluster (firstCluster, GET,
0);
getSetNextCluster (firstCluster, SET,
0);
if(nextCluster >
0x0ffffff6)
{transmitString_F(PSTR("File deleted!"));return
0;}
firstCluster =
nextCluster;
}
}
}
}
else
//when flag =
GET_LIST
{
TX_NEWLINE;
for(j=0; j<11;
j++)
{
if(j == 8) transmitByte('
');
transmitByte
(dir->name[j]);
}
transmitString_F (PSTR("
"));
if((dir->attrib != 0x10) && (dir->attrib !=
0x08))
{
transmitString_F (PSTR("FILE"
));
transmitString_F (PSTR("
"));
displayMemory
(dir->fileSize);
}
else
transmitString_F ((dir->attrib == 0x10)? PSTR("DIR") :
PSTR("ROOT"));
}
}
}
}
cluster = (getSetNextCluster (cluster,
GET, 0));
if(cluster > 0x0ffffff6)
return 0;
if(cluster ==
0)
{transmitString_F(PSTR("Error in getting
cluster")); return 0;}
}
return
0;
}
//***************************************************************************
//Function: if flag=READ then
to read file from SD card and send contents to UART
//if flag=VERIFY then functions
will verify whether a specified file is already existing
//Arguments: flag (READ or
VERIFY) and pointer to the file name
//return: 0, if normal
operation or flag is READ
//
1, if file is already existing and flag =
VERIFY
//
2, if file name is incompatible
//***************************************************************************
unsigned char
readFile (unsigned char flag, unsigned char
*fileName)
{
struct dir_Structure *dir;
unsigned
long cluster, byteCounter = 0, fileSize, firstSector;
unsigned
int k;
unsigned char j, error;
error =
convertFileName (fileName); //convert fileName into FAT
format
if(error)
return 2;
dir = findFiles (GET_FILE, fileName); //get the file
location
if(dir ==
0)
return (0);
if(flag == VERIFY)
return (1); //specified file name is
already existing
cluster =
(((unsigned long) dir->firstClusterHI) << 16) |
dir->firstClusterLO;
fileSize =
dir->fileSize;
TX_NEWLINE;
TX_NEWLINE;
while(1)
{
firstSector = getFirstSector (cluster);
for(j=0; j<8;
j++)
{
SD_readSingleBlock(firstSector +
j);
for(k=0; k<512;
k++)
{
transmitByte(buffer[k]);
if
((byteCounter++) >= fileSize ) return 0;
}
}
cluster = getSetNextCluster (cluster, GET, 0);
if(cluster == 0) {transmitString_F(PSTR("Error in getting
cluster")); return 0;}
}
return
0;
}
//***************************************************************************
//Function: to convert normal
short file name into FAT format
//Arguments: pointer to the
file name
//return: 0-if no error, 1-if
error
//****************************************************************************
unsigned char
convertFileName (unsigned char *fileName)
{
unsigned
char fileNameFAT[11];
unsigned char j,
k;
for(j=0; j<12; j++)
if(fileName[j] == '.')
break;
if(j>8) {transmitString_F(PSTR("Invalid
fileName..")); return 1;}
for(k=0; k<j; k++)
//setting file
name
fileNameFAT[k] = fileName[k];
for(k=j; k<=7; k++) //filling file name trail with
blanks
fileNameFAT[k] = ' ';
j++;
for(k=8; k<11; k++)
//setting file
extention
{
if(fileName[j] != 0)
fileNameFAT[k] =
fileName[j++];
else //filling extension trail with blanks
while(k<11)
fileNameFAT[k++] = '
';
}
for(j=0; j<11; j++) //converting small letters to
caps
if((fileNameFAT[j] >= 0x61) && (fileNameFAT[j] <=
0x7a))
fileNameFAT[j] -= 0x20;
for(j=0;
j<11; j++)
fileName[j] = fileNameFAT[j];
return
0;
}
//***************************************************************************
//Function: to create a
file in FAT32 format in the root directory
//Arguments: pointer to
the file name
//return: none
//***************************************************************************
void createFile (unsigned char
*fileName)
{
unsigned char j, data, error,
fileCreatedFlag = 0;
unsigned int i, firstClusterHigh,
firstClusterLow;
struct dir_Structure *dir;
unsigned long cluster, prevCluster,
firstSector, sector;
unsigned long size;
j = readFile (VERIFY, fileName);
if(j == 1)
{transmitString_F(PSTR(" File already existing")); return;}
if(j == 2) return; //invalid file name
TX_NEWLINE;
transmitString_F(PSTR(" Creating
File.."));
cluster
= getSetFreeCluster (NEXT_FREE, GET, 0);
if(cluster > totalClusters)
cluster = rootCluster;
cluster
= searchNextFreeCluster(cluster);
if(cluster == 0)
{
TX_NEWLINE;
transmitString_F(PSTR(" No free cluster!"));
return;
}
//transmitHex(LONG, cluster);
firstClusterHigh = (unsigned int) ((cluster
& 0xffff0000) >> 16 );
firstClusterLow = (unsigned int) ( cluster
& 0x0000ffff);
size =
0;
while(1)
{
getSetNextCluster (cluster, SET,
EOF); //last cluster of the
file, marked EOF
startBlock = getFirstSector
(cluster);
TX_NEWLINE;
transmitString_F(PSTR(" Enter text
(end with ~):"));
i=0;
j=0;
do
{
data =
receiveByte();
if(data ==
0x08) //'Back Space' key
pressed
{
if(i !=
0)
{
transmitByte(data);
transmitByte(' ');
transmitByte(data);
i--;
size--;
}
continue;
}
transmitByte(data);
buffer[i++] =
data;
size++;
if(data ==
'\r') //'Carriege Return (CR)'
character
{
transmitByte('\n');
buffer[i++] = '\n'; //appending 'Line Feed
(LF)' character
size++;
}
if(i == 512)
{
i=0;
error =
SD_writeSingleBlock (startBlock);
j++;
if(j ==
sectorPerCluster) {j = 0; break;}
startBlock++;
}
}while (data !=
'~');
if(data == '~')
{
size--; //to remove the last entered '~' character
i--;
for(;i<512;i++) //fill the rest of the buffer with 0x00
buffer[i]= 0x00;
error =
SD_writeSingleBlock (startBlock);
break;
}
prevCluster = cluster;
cluster =
searchNextFreeCluster(prevCluster); //look for a free cluster starting from the
current cluster
if(cluster == 0)
{
TX_NEWLINE;
transmitString_F(PSTR(" No free cluster!"));
return;
}
getSetNextCluster(prevCluster,
SET, cluster);
}
getSetFreeCluster (NEXT_FREE, SET, cluster);
//update FSinfo next free cluster entry
prevCluster = rootCluster; //root
cluster
while(1)
{
firstSector = getFirstSector
(prevCluster);
for(sector = 0; sector <
sectorPerCluster; sector++)
{
SD_readSingleBlock
(firstSector + sector);
for(i=0;
i<bytesPerSector; i+=32)
{
dir =
(struct dir_Structure *) &buffer[i];
if(fileCreatedFlag) //to mark last directory entry with
0x00 (empty) mark
{
//indicating end of the directory file
list
dir->name[0] = 0x00;
return;
}
if((dir->name[0] == EMPTY) || (dir->name[0] == DELETED))
//looking for an empty slot to enter file info
{
for(j=0; j<11; j++)
dir->name[j] = fileName[j];
dir->attrib = ATTR_ARCHIVE; //settting file attribute as
'archive'
dir->NTreserved = 0;
//always set to 0
dir->timeTenth = 0;
//always set to 0
dir->createTime = 0x9684; //fixed time
of creation
dir->createDate = 0x3a37; //fixed date
of creation
dir->lastAccessDate = 0x3a37; //fixed date of last
access
dir->writeTime = 0x9684; //fixed time of
last write
dir->writeDate = 0x3a37; //fixed date of
last write
dir->firstClusterHI = firstClusterHigh;
dir->firstClusterLO = firstClusterLow;
dir->fileSize = size;
SD_writeSingleBlock (firstSector + sector);
fileCreatedFlag = 1;
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR(" File Created!"));
freeMemoryUpdate (REMOVE, size); //updating free memory count in FSinfo
sector
}
}
}
cluster = getSetNextCluster
(prevCluster, GET, 0);
if(cluster >
0x0ffffff6)
{
if(cluster == EOF) //this situation will come when total
files in root is multiple of (32*sectorPerCluster)
{
cluster =
searchNextFreeCluster(prevCluster); //find next cluster for root directory
entries
getSetNextCluster(prevCluster, SET, cluster); //link the new cluster of
root to the previous cluster
getSetNextCluster(cluster, SET, EOF); //set the new cluster as end
of the root directory
}
else
{
transmitString_F(PSTR("End of Cluster Chain"));
return;
}
}
if(cluster == 0)
{transmitString_F(PSTR("Error in getting cluster")); return;}
prevCluster = cluster;
}
return;
}
//***************************************************************************
//Function: to search for the
next free cluster in the root directory
//
starting from a specified cluster
//Arguments: Starting
cluster
//return: the next free
cluster
//****************************************************************
unsigned long
searchNextFreeCluster (unsigned long startCluster)
{
unsigned long cluster, *value, sector;
unsigned
char i;
startCluster -= (startCluster % 128); //to start with the first file
in a FAT sector
for(cluster =startCluster; cluster <totalClusters;
cluster+=128)
{
sector =
unusedSectors + reservedSectorCount + ((cluster * 4) /
bytesPerSector);
SD_readSingleBlock(sector);
for(i=0;
i<128; i++)
{
value = (unsigned
long *)
&buffer[i*4];
if(((*value) & 0x0fffffff) ==
0)
return(cluster+i);
}
}
return
0;
}
//***************************************************************************
//Function: to display total
memory and free memory of SD card, using UART
//Arguments:
none
//return:
none
//Note:
this routine may take upto 15sec for 1GB card (@8MHz clock)
//it tries to read from SD
whether a free cluster count is stored, if it is stored
//then it will return
immediately. Otherwise it will count the total number of
//free clusters, which takes
time
//****************************************************************************
void
memoryStatistics (void)
{
unsigned long totalMemory,
freeMemory, freeClusters, totalClusterCount, cluster;
unsigned
long sector, *value;
unsigned int i;
totalMemory
= totalClusters * sectorPerCluster *
bytesPerSector;
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("Total
Memory: "));
displayMemory (totalMemory);
freeClusters =
getSetFreeCluster (TOTAL_FREE, GET, 0);
//freeClusters =
0xffffffff;
if(freeClusters
> totalClusters)
{
freeClusterCountUpdated =
0;
freeClusters = 0;
totalClusterCount =
0;
cluster =
rootCluster;
while(1)
{
sector
= unusedSectors + reservedSectorCount + ((cluster * 4) / bytesPerSector)
;
SD_readSingleBlock(sector);
for(i=0;
i<128; i++)
{
value = (unsigned
long *)
&buffer[i*4];
if(((*value)& 0x0fffffff) ==
0)
freeClusters++;;
totalClusterCount++;
if(totalClusterCount == (totalClusters+2))
break;
}
if(i < 128)
break;
cluster+=128;
}
}
if(!freeClusterCountUpdated)
getSetFreeCluster
(TOTAL_FREE, SET, freeClusters); //update FSinfo total free
cluster entry
freeClusterCountUpdated =
1; //set
flag
freeMemory
= freeClusters * sectorPerCluster *
bytesPerSector;
TX_NEWLINE;
transmitString_F(PSTR(" Free Memory:
"));
displayMemory (freeMemory);
TX_NEWLINE;
}
//************************************************************
//Function: To convert the
unsigned long value of memory into
//
text string and send to UART
//Arguments: unsigned long
memory value
//return: none
//************************************************************
void displayMemory
(unsigned long memory)
{
unsigned char
memoryString[] =
"
Bytes"; //18
character long string for memory display
unsigned
char i;
for(i=12; i>0; i--) //converting freeMemory into
ASCII string
{
if(i == 5 || i == 9)
{
memoryString[i-1] =
',';
i--;
}
memoryString[i-1] = (memory %
10) | 0x30;
memory /= 10;
if(memory == 0) break;
}
transmitString(memoryString);
}
//********************************************************************
//Function: to delete a
specified file from the root directory
//Arguments: pointer to the
file name
//return: none
//********************************************************************
void deleteFile
(unsigned char *fileName)
{
unsigned
char error;
error = convertFileName (fileName);
if(error) return;
findFiles (DELETE,
fileName);
}
//********************************************************************
//Function: update the free
memory count in the FSinfo sector.
//
Whenever a file is deleted or created, this function will be
called
//
to ADD or REMOVE clusters occupied by the file
//Arguments: #1.flag ADD or
REMOVE #2.file size in Bytes
//return:
none
//********************************************************************
void freeMemoryUpdate
(unsigned char flag,
unsigned long
size)
{
unsigned long freeClusters;
//convert file size into number
of clusters occupied
if((size %
512) == 0) size = size / 512;
else size = (size / 512)
+1;
if((size % 8) == 0) size = size / 8;
else
size = (size / 8) +1;
if(freeClusterCountUpdated)
{
freeClusters = getSetFreeCluster
(TOTAL_FREE, GET, 0);
if(flag ==
ADD)
freeClusters = freeClusters
+ size;
else //when flag =
REMOVE
freeClusters = freeClusters -
size;
getSetFreeCluster (TOTAL_FREE, SET,
freeClusters);
}
}
//******** END ****** http://www.dharmanitech.com/
*****