61,12 → 61,11 |
#include "sdc.h" |
#include "uart1.h" |
|
|
//________________________________________________________________________________________________________________________________________ |
// Module name: fat16.c |
// Compiler used: avr-gcc 3.4.5 |
// Last Modifikation: 16.06.2008 |
// Version: 2.00 |
// Last Modifikation: 20.03.2010 |
// Version: 2.10 |
// Authors: Stephan Busker & Gregor Stobrawa |
// Description: Source files for FAT16 implementation with read and write-access |
// Copyright (C) 2008 Stephan Busker & Gregor Stobrawa |
73,8 → 72,10 |
//........................................................................................................................................ |
// Functions: extern s16 Fat16_Init(void); |
// extern s16 Fat16_Deinit(void); |
// extern s8* FAT16_GetVolumeLabel(void); |
// extern File_t * fopen_(const u8 *filename, const s8 mode); |
// extern s16 fclose_(File_t *File); |
// extern u8 fexist_(s8 * const filename); |
// extern s16 fflush_(File_t *File); |
// extern s16 fseek_(File_t *File, s32 offset, s16 origin); |
// extern s16 fgetc_(File_t *File); |
83,6 → 84,7 |
// extern u32 fwrite_(void *buffer, u32 size, u32 count, File_t *File); |
// extern s16 fputs_(const u8 *string, File_t *File); |
// extern u8 * fgets_(u8 *string, s16 length, File_t *File); |
// extern u8 feof_(File_t * const file); |
//........................................................................................................................................ |
// ext. functions: extern SD_Result_t SDC_Init(void;) |
// extern SD_Result_t SDC_Deinit(void); |
230,8 → 232,14 |
s8 Name[8]; // 8 bytes name, padded with spaces. |
u8 Extension[3]; // 3 bytes extension, padded with spaces. |
u8 Attribute; // attribute of the directory entry (unused,archive,read-only,system,directory,volume) |
u8 Reserved[10]; // reserved bytes within the directory entry. |
u32 DateTime; // date and time of last write access to the file or directory. |
u8 Res1; // should be zero |
u8 CreationTime10ms; // subsecond resolution of creation time |
u16 CreationTime; // Time of creation h:m:s |
u16 CreationDate; // Date of creation Y.M.D |
u16 LastAccessDate; // The date where the file was last accessed |
u8 Res2[2]; // should be zero |
u16 ModTime; // date of last write access |
u16 ModDate; // date of last write access to the file or directory. |
u16 StartCluster; // first cluster of the file or directory. |
u32 Size; // size of the file or directory in bytes. |
} __attribute__((packed)) DirEntry_t; |
284,6 → 292,9 |
#define FAT16_BYTES 2 |
#define FAT16_ENTRIES_PER_SECTOR BYTES_PER_SECTOR/FAT16_BYTES |
|
#define SECTOR_UNDEFINED 0x00000000L |
#define CLUSTER_UNDEFINED 0x0000 |
|
#define FSTATE_UNUSED 0 |
#define FSTATE_USED 1 |
|
307,28 → 318,44 |
|
|
/****************************************************************************************************************************************/ |
/* Function: FileDateTime(DateTime_t *); */ |
/* Function: FileDate(DateTime_t *); */ |
/* */ |
/* Description: This function calculates the DOS date time from a pointer to a time structure. */ |
/* Description: This function calculates the DOS date from a pointer to a time structure. */ |
/* */ |
/* Returnvalue: Returns the DOS date time. */ |
/* Returnvalue: Returns the DOS date. */ |
/****************************************************************************************************************************************/ |
u16 FileDate(DateTime_t * pTimeStruct) |
{ |
u16 date = 0; |
if(pTimeStruct == NULL) return date; |
if(!(pTimeStruct->Valid)) return date; |
|
u32 FileDateTime(DateTime_t * pTimeStruct) |
date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year |
date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month |
date |= (0x001F & (u16)(pTimeStruct->Day)); |
return date; |
} |
|
/****************************************************************************************************************************************/ |
/* Function: FileTime(DateTime_t *); */ |
/* */ |
/* Description: This function calculates the DOS time from a pointer to a time structure. */ |
/* */ |
/* Returnvalue: Returns the DOS time. */ |
/****************************************************************************************************************************************/ |
|
u16 FileTime(DateTime_t * pTimeStruct) |
{ |
u32 datetime = 0; |
if((pTimeStruct == 0) || !(pTimeStruct->Valid)) return datetime; |
u16 time = 0; |
if(pTimeStruct == NULL) return time; |
if(!(pTimeStruct->Valid)) return time; |
|
datetime |= (0x0000007FL & (u32)(pTimeStruct->Year - 1980))<<25; // set year |
datetime |= (0x0000000FL & (u32)(pTimeStruct->Month))<<21; // set month |
datetime |= (0x0000001FL & (u32)(pTimeStruct->Day))<<16; |
datetime |= (0x0000001FL & (u32)(pTimeStruct->Hour))<<11; |
datetime |= (0x0000003FL & (u32)(pTimeStruct->Min))<<5; |
datetime |= (0x0000001FL & (u32)(pTimeStruct->Sec/2)); |
return datetime; |
time |= (0x001F & (u16)(pTimeStruct->Hour))<<11; |
time |= (0x003F & (u16)(pTimeStruct->Min))<<5; |
time |= (0x001F & (u16)(pTimeStruct->Sec/2)); |
return time; |
} |
|
|
/****************************************************************************************************************************************/ |
/* Function: LockFilePointer(); */ |
/* */ |
368,16 → 395,15 |
if(&FilePointer[cnt] == file) // filepointer to be freed found? |
{ |
file->State = FSTATE_UNUSED; |
file->FirstSectorOfFirstCluster = 0; // Sectorpointer to the first sector of the first datacluster of the file. |
file->FirstSectorOfCurrCluster = 0; |
file->SectorOfCurrCluster = 0; // Pointer to the cluster which is edited at the moment. |
file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; // Sectorpointer to the first sector of the first datacluster of the file. |
file->FirstSectorOfCurrCluster = SECTOR_UNDEFINED; // Pointer to the cluster which is edited at the moment. |
file->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
file->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
file->Mode = 0; // mode of fileoperation (read,write) |
file->Size = 0; // the size of the opend file in bytes. |
file->Position = 0; // pointer to a character within the file 0 < fileposition < filesize |
file->SectorInCache = 0; // the last sector read, wich is still in the sectorbuffer. |
file->DirectorySector = 0; // the sectorposition where the directoryentry has been made. |
file->SectorInCache = SECTOR_UNDEFINED; // the last sector read, wich is still in the sectorbuffer. |
file->DirectorySector = SECTOR_UNDEFINED; // the sectorposition where the directoryentry has been made. |
file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
file->Attribute = 0; // the attribute of the file opened. |
file = NULL; |
462,9 → 488,15 |
/****************************************************************************************************************************************/ |
u32 Fat16ClusterToSector(u16 cluster) |
{ |
if(!Partition.IsValid) return 0; |
if (cluster < 2) cluster = 2; // the 0. and 1. cluster in the fat are used for the media descriptor |
return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector is represented by the 2nd cluster |
if(!Partition.IsValid) return SECTOR_UNDEFINED; |
if (cluster < 2) |
{ |
return SECTOR_UNDEFINED; |
} |
else |
{ |
return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector is represented by the 2nd cluster |
} |
} |
|
/****************************************************************************************************************************************/ |
477,8 → 509,9 |
/****************************************************************************************************************************************/ |
u16 SectorToFat16Cluster(u32 sector) |
{ |
if(!Partition.IsValid) return 0; |
return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2); |
if(!Partition.IsValid) return CLUSTER_UNDEFINED; |
if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED; |
else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2); |
} |
|
|
514,6 → 547,7 |
{ |
returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers |
} |
else UnlockFilePointer(&FilePointer[cnt]); |
|
} |
SDC_Deinit(); // uninitialize interface to sd-card |
546,12 → 580,12 |
// declare the filepointers as unused. |
for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
{ |
FilePointer[cnt].State = FSTATE_UNUSED; |
UnlockFilePointer(&FilePointer[cnt]); |
} |
// set current file pinter to first position in list |
file = &FilePointer[0]; |
|
// try to initialise the sd-card. |
// try to initialize the sd-card. |
if(SD_SUCCESS != SDC_Init()) |
{ |
UART1_PutString("SD-Card could not be initialized."); |
649,6 → 683,7 |
if((!Partition.IsValid) || (file == NULL)) return(0); |
|
for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache |
if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do |
for(i = 0; i < Partition.SectorsPerCluster; i++) |
{ |
file->SectorInCache = file->FirstSectorOfCurrCluster + i; |
670,11 → 705,12 |
/*****************************************************************************************************************************************/ |
u16 GetNextCluster(File_t * file) |
{ |
u16 cluster = 0; |
u16 cluster = CLUSTER_UNDEFINED; |
u32 fat_byte_offset, sector, byte; |
Fat16Entry_t * fat; |
|
if((!Partition.IsValid) || (file == NULL)) return(cluster); |
if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster); |
// if sector is within the data area |
if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector)) |
{ |
699,10 → 735,10 |
// read the next cluster from cache |
fat = (Fat16Entry_t *)(&(file->Cache[byte])); |
cluster = fat->NextCluster; |
// if last cluster fat entry |
// if no next cluster exist |
if(FAT16_CLUSTER_LAST_MIN <= cluster) |
{ |
cluster = 0; |
cluster = CLUSTER_UNDEFINED; // next cluster is undefined |
} |
else |
{ |
727,7 → 763,7 |
u32 fat_sector; // current sector within the fat relative to the first sector of the fat. |
u32 curr_sector; // current sector |
u16 fat_entry; // index to an fatentry within the actual sector (256 fatentries are possible within one sector). |
u16 free_cluster = 0; // next free cluster number. |
u16 free_cluster = CLUSTER_UNDEFINED; // next free cluster number. |
Fat16Entry_t * fat; |
|
if((!Partition.IsValid) || (file == NULL)) return(0); |
772,7 → 808,7 |
/* */ |
/* Description: This function sets the pointer of the stream relative to the position */ |
/* specified by origin (SEEK_SET, SEEK_CUR, SEEK_END) */ |
/* Returnvalue: Is 1 if seek was successful */ |
/* Returnvalue: Is 0 if seek was successful */ |
/****************************************************************************************************************************************************/ |
s16 fseek_(File_t *file, s32 offset, s16 origin) |
{ |
779,7 → 815,7 |
s32 fposition = 0; |
s16 retvalue = 1; |
|
if((!Partition.IsValid) || (file == NULL)) return(0); |
if((!Partition.IsValid) || (file == NULL)) return(retvalue); |
switch(origin) |
{ |
case SEEK_SET: // Fileposition relative to the beginning of the file. |
803,7 → 839,7 |
file->SectorOfCurrCluster = 0; |
file->ByteOfCurrSector = 0; |
file->Position = 0; |
|
if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue); |
while(file->Position < fposition) // repeat until the current position is less than target |
{ |
file->Position++; // increment file position |
820,7 → 856,7 |
} |
else // the last cluster was allready reached |
{ |
file->SectorOfCurrCluster--; // jump back to the ast sector in the last cluster |
file->SectorOfCurrCluster--; // jump back to the last sector in the last cluster |
file->ByteOfCurrSector = BYTES_PER_SECTOR; // set ByteOfCurrSector one byte over sector end |
} |
} |
847,10 → 883,11 |
u32 sector_in_buffer = 0; |
u8 repeat = 0; |
|
if(!Partition.IsValid) return 0; |
if(!Partition.IsValid) return(0); |
if(StartCluster == CLUSTER_UNDEFINED) return(0); |
cluster = StartCluster; // init chain trace |
// if start cluster is equal to the last cluster we are done |
if(FAT16_CLUSTER_LAST_MIN <= cluster) return 1; |
// if start cluster is no real cluster |
if(FAT16_CLUSTER_LAST_MIN <= cluster) return 1; |
|
// calculate byte offset in the fat for corresponding entry |
fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster |
869,16 → 906,20 |
// read the next cluster from cache |
fat = (Fat16Entry_t *)(&(buffer[byte])); |
cluster = fat->NextCluster; |
if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1; |
fat->NextCluster = FAT16_CLUSTER_FREE; // mark current cluster as free |
|
if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) |
{ |
repeat = 1; |
// calculate sector byte and byte offset in the fat for the next cluster |
fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster |
// calculate the sector that contains the current cluster within the fat |
sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR); |
// calculate byte offset of the current cluster within that fat sector |
byte = fat_byte_offset % BYTES_PER_SECTOR; |
} |
else repeat = 0; |
|
fat->NextCluster = FAT16_CLUSTER_FREE; // mark current cluster as free |
// calculate byte offset in the fat for corresponding entry |
fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster |
// calculate the sector that contains the current cluster within the fat |
sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR); |
// calculate byte offset of the current cluster within that fat sector |
byte = fat_byte_offset % BYTES_PER_SECTOR; |
// if new sector is not the sector in buffer or the last cluster in the chain was traced |
if((sector != sector_in_buffer) || !repeat) |
{ // write sector in buffer |
885,7 → 926,7 |
if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) |
{ |
Fat16_Deinit(); |
return 0; |
return(0); |
} |
} |
} |
900,11 → 941,11 |
/* */ |
/* Description: This function looks in the fat to find the next free cluster and appends it to the file. */ |
/* */ |
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended. */ |
/* Returnvalue: The function returns the appened cluster number or CLUSTER_UNDEFINED of no cluster was appended. */ |
/****************************************************************************************************************************************/ |
u16 AppendCluster(File_t *file) |
{ |
u16 last_cluster, new_cluster = 0; |
u16 last_cluster, new_cluster = CLUSTER_UNDEFINED; |
u32 fat_byte_offset, sector, byte; |
Fat16Entry_t * fat; |
|
911,30 → 952,65 |
if((!Partition.IsValid) || (file == NULL)) return(new_cluster); |
|
new_cluster = FindNextFreeCluster(file); // the next free cluster found on the disk. |
if(new_cluster) |
if(new_cluster != CLUSTER_UNDEFINED) |
{ // A free cluster was found and can be added to the end of the file. |
fseek_(file, 0, SEEK_END); // jump to the end of the file |
last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster); // determine current file cluster |
fat_byte_offset = ((u32)last_cluster)<<1; |
sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR); |
byte = fat_byte_offset % BYTES_PER_SECTOR; |
|
if(file->SectorInCache != sector) |
if(last_cluster != CLUSTER_UNDEFINED) |
{ |
file->SectorInCache = sector; // update sector stored in buffer |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card |
// update FAT entry of last cluster |
fat_byte_offset = ((u32)last_cluster)<<1; |
sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR); |
byte = fat_byte_offset % BYTES_PER_SECTOR; |
// read the sector containing the last cluster of the file |
if(file->SectorInCache != sector) |
{ |
file->SectorInCache = sector; // update sector stored in buffer |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card |
{ |
Fat16_Deinit(); |
return(0); |
} |
} |
fat = (Fat16Entry_t *)(&(file->Cache[byte])); |
fat->NextCluster = new_cluster; // append the free cluster to the end of the file in the FAT. |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // save the modified sector to the FAT. |
{ |
Fat16_Deinit(); |
return(0); |
return(0); |
} |
} |
fat = (Fat16Entry_t *)(&(file->Cache[byte])); |
fat->NextCluster = new_cluster; // append the free cluster to the end of the file in the FAT. |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // save the modified sector to the FAT. |
{ |
Fat16_Deinit(); |
return(0); |
else // last cluster of the file is undefined |
{ // then the new cluster must be the first one of the file |
// and its cluster number must be set in the direntry |
DirEntry_t * dir; |
file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(CLUSTER_UNDEFINED); |
} |
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
dir[file->DirectoryIndex].Res1 = 0; |
dir[file->DirectoryIndex].Res2[0] = 0; |
dir[file->DirectoryIndex].Res2[1] = 0; |
dir[file->DirectoryIndex].StartCluster = new_cluster; // update startcluster |
dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);// set time |
dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);// and date of modification |
dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
dir[file->DirectoryIndex].Size = 0; |
// write sector containing the direntry |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
{ |
Fat16_Deinit(); |
return(CLUSTER_UNDEFINED); |
} |
// update file info |
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster); |
file->Size = 0; |
file->Position = 0; |
} |
// update file pointes |
file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster); |
file->SectorOfCurrCluster = 0; |
file->ByteOfCurrSector = 0; |
966,9 → 1042,9 |
// a corresponding dir entry with adir-flag set in its attribute |
// or direct within the root directory area |
|
file->FirstSectorOfFirstCluster = 0; |
file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
// no current directory exist therefore assume searching in the root |
if(file->DirectorySector == 0) |
if(file->DirectorySector == SECTOR_UNDEFINED) |
{ |
max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector; |
985,7 → 1061,7 |
} |
else return (direntry_exist); // bad sector range for directory sector of the file |
// if search area is not defined yet |
if(file->FirstSectorOfFirstCluster == 0) |
if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED) |
{ |
// check if the directory entry of current file is existent and has the dir-flag set |
file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
995,7 → 1071,7 |
return(direntry_exist); |
} |
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
{ |
case SLOT_EMPTY: |
case SLOT_DELETED: |
1098,9 → 1174,9 |
// Dir entries can be created only in file-clusters that have |
// the dir-flag set in its attribute or within the root directory |
|
file->FirstSectorOfFirstCluster = 0; |
file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
// no current directory exist therefore assume creating in the root |
if(file->DirectorySector == 0) |
if(file->DirectorySector == SECTOR_UNDEFINED) |
{ |
max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
dircluster = 0; |
1118,7 → 1194,7 |
} |
else return (retvalue); // bad sector range for directory sector of the file |
// if search area is not defined yet |
if(file->FirstSectorOfFirstCluster == 0) |
if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED) |
{ |
// check if the directory entry of current file is existent and has the dir-flag set |
file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1145,97 → 1221,113 |
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster); |
} |
|
subdircluster = FindNextFreeCluster(file); // get the next free cluster on the disk and mark it as used. |
if(subdircluster) |
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
file->SectorOfCurrCluster = 0; |
do // loop over all clusters of current directory |
{ |
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
file->SectorOfCurrCluster = 0; |
do // loop over all clusters of current directory |
dir_sector = 0; // reset sector counter within a new cluster |
do // loop over all sectors of a cluster or all sectors of the root directory |
{ |
dir_sector = 0; // reset sector counter within a new cluster |
do // loop over all sectors of a cluster or all sectors of the root directory |
curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
file->SectorInCache = curr_sector; // upate the sector number of file cache. |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
file->SectorInCache = curr_sector; // upate the sector number of file cache. |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(retvalue); |
} |
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
// search all directory entries of a sector |
for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++) |
{ // check if current direntry is available |
if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED)) |
{ // a free direntry was found |
for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i]; // Set dir name |
dir[dir_entry].Attribute = attrib; // Set the attribute of the new directoryentry. |
dir[dir_entry].StartCluster = subdircluster; // copy the location of the first datacluster to the directoryentry. |
dir[dir_entry].DateTime = FileDateTime(&SystemTime); // set date/time |
dir[dir_entry].Size = 0; // the new createted file has no content yet. |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to card |
Fat16_Deinit(); |
return(retvalue); |
} |
|
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
// search all directory entries of a sector |
for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++) |
{ // check if current direntry is available |
if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED)) |
{ // a free direntry was found |
for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i]; // Set dir name |
dir[dir_entry].Attribute = attrib; |
dir[dir_entry].Res1 = 0; |
dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10); |
dir[dir_entry].CreationTime = FileTime(&SystemTime); |
dir[dir_entry].CreationDate = FileDate(&SystemTime); |
dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate; |
dir[dir_entry].Res2[0] = 0; |
dir[dir_entry].Res2[1] = 0; |
dir[dir_entry].ModTime = dir[dir_entry].CreationTime; |
dir[dir_entry].ModDate = dir[dir_entry].CreationDate; |
// if the new direntry is a subdirectory |
if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY) |
{ // get a free clutser for its content |
subdircluster = FindNextFreeCluster(file); // get the next free cluster on the disk and mark it as used. |
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster); // Calculate absolute sectorposition of first datacluster. |
} |
else // normal file |
{ // has no data cluster after creation |
subdircluster = CLUSTER_UNDEFINED; |
file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
} |
// Set the attribute of the new directoryentry. |
dir[dir_entry].StartCluster = subdircluster; // copy the location of the first datacluster to the directoryentry. |
dir[dir_entry].Size = 0; // the new createted file has no content yet. |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to card |
{ |
Fat16_Deinit(); |
return(retvalue); |
} |
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; // Start reading the file with the first sector of the first datacluster. |
file->SectorOfCurrCluster = 0; // reset sector of cureen cluster |
file->ByteOfCurrSector = 0; // reset the byte location within the current sector |
file->Attribute = attrib; // set file attribute to dir attribute |
file->Size = 0; // new file has no size |
file->DirectorySector = curr_sector; |
file->DirectoryIndex = dir_entry; |
// prepare subdirectory data cluster |
if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY) // if a new directory was created then initilize the data area |
{ |
ClearCurrCluster(file); // fill cluster with zeros |
file->SectorInCache = file->FirstSectorOfFirstCluster; |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
Fat16_Deinit(); |
return(retvalue); |
} |
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster); // Calculate absolute sectorposition of first datacluster. |
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; // Start reading the file with the first sector of the first datacluster. |
file->SectorOfCurrCluster = 0; // reset sector of cureen cluster |
file->ByteOfCurrSector = 0; // reset the byte location within the current sector |
file->Attribute = attrib; // set file attribute to dir attribute |
file->Size = 0; // new file has no size |
file->DirectorySector = curr_sector; |
file->DirectoryIndex = dir_entry; |
if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY) // if a new directory was created then initilize the data area |
dir = (DirEntry_t *)file->Cache; |
// create direntry "." to current dir |
dir[0].Name[0] = 0x2E; |
for(i = 1; i < 11; i++) dir[0].Name[i] = ' '; |
dir[0].Attribute = ATTR_SUBDIRECTORY; |
dir[0].StartCluster = subdircluster; |
dir[0].Size = 0; |
// create direntry ".." to the upper dir |
dir[1].Name[0] = 0x2E; |
dir[1].Name[1] = 0x2E; |
for(i = 2; i < 11; i++) dir[1].Name[i] = ' '; |
dir[1].Attribute = ATTR_SUBDIRECTORY; |
dir[1].StartCluster = dircluster; |
dir[1].Size = 0; |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
ClearCurrCluster(file); // fill cluster with zeros |
file->SectorInCache = file->FirstSectorOfFirstCluster; |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(retvalue); |
} |
dir = (DirEntry_t *)file->Cache; |
// create direntry "." to current dir |
dir[0].Name[0] = 0x2E; |
for(i = 1; i < 11; i++) dir[0].Name[i] = ' '; |
dir[0].Attribute = ATTR_SUBDIRECTORY; |
dir[0].StartCluster = subdircluster; |
dir[0].DateTime = 0; |
dir[0].Size = 0; |
// create direntry ".." to the upper dir |
dir[1].Name[0] = 0x2E; |
dir[1].Name[1] = 0x2E; |
for(i = 2; i < 11; i++) dir[1].Name[i] = ' '; |
dir[1].Attribute = ATTR_SUBDIRECTORY; |
dir[1].StartCluster = dircluster; |
dir[1].DateTime = 0; |
dir[1].Size = 0; |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(retvalue); |
} |
} |
retvalue = 1; |
dir_entry = DIRENTRIES_PER_SECTOR; // stop for-loop |
} |
Fat16_Deinit(); |
return(retvalue); |
} |
} |
retvalue = 1; |
dir_entry = DIRENTRIES_PER_SECTOR; // stop for-loop |
} |
dir_sector++; // search next sector |
// stop if we reached the end of the cluster or the end of the root dir |
}while((dir_sector < max_dir_sector) && (!retvalue)); |
} |
dir_sector++; // search next sector |
// stop if we reached the end of the cluster or the end of the root dir |
}while((dir_sector < max_dir_sector) && (!retvalue)); |
|
// if we are seaching in the data area and the file not found in this cluster so take next cluster. |
if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)) |
{ |
end_of_directory_not_reached = GetNextCluster(file); // updates File->FirstSectorOfCurrCluster |
} |
}while((end_of_directory_not_reached) && (!retvalue)); |
// Perhaps we are at the end of the last cluster of a directory file an have no free direntry found. |
// Then we would need to add a cluster to that file and create the new direntry there. |
// This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are |
// within a subdirectory of root. |
} |
// if we are seaching in the data area and the file not found in this cluster so take next cluster. |
if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)) |
{ |
end_of_directory_not_reached = GetNextCluster(file); // updates File->FirstSectorOfCurrCluster |
} |
}while((end_of_directory_not_reached) && (!retvalue)); |
// Perhaps we are at the end of the last cluster of a directory file and have no free direntry found. |
// Then we would need to add a cluster to that file and create the new direntry there. |
// This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are |
// within a subdirectory of root. |
|
return(retvalue); // return 1 if file has been created otherwise return 0. |
} |
|
1382,15 → 1474,15 |
|
// now we have found a free filepointer and claimed it |
// so let initiate its property values |
file->FirstSectorOfFirstCluster = 0; // Sectorpointer to the first sector of the first datacluster of the file. |
file->FirstSectorOfCurrCluster = 0; // Pointer to the cluster which is edited at the moment. |
file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; // Sectorpointer to the first sector of the first datacluster of the file. |
file->FirstSectorOfCurrCluster = SECTOR_UNDEFINED; // Pointer to the cluster which is edited at the moment. |
file->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
file->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
file->Mode = mode; // mode of fileoperation (read,write) |
file->Size = 0; // the size of the opened file in bytes. |
file->Position = 0; // pointer to a byte within the file 0 < fileposition < filesize |
file->SectorInCache = 0; // the last sector read, wich is still in the sectorbuffer. |
file->DirectorySector = 0; // the sectorposition where the directoryentry has been made. |
file->SectorInCache = SECTOR_UNDEFINED; // the last sector read, wich is still in the sectorbuffer. |
file->DirectorySector = SECTOR_UNDEFINED; // the sectorposition where the directoryentry has been made. |
file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
file->Attribute = 0; // the attribute of the file opened. |
|
1417,11 → 1509,30 |
file = NULL; |
} |
else |
{ // file is not marked as read only --> goto start of file |
{ // file is not marked as read only |
DirEntry_t * dir; |
// free all clusters of that file |
DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster)); |
// mark an empy cluster as the last one and store the corresponding sector |
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(FindNextFreeCluster(file)); |
// update directory entry of that file |
file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(NULL); |
} |
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime); // set modification time |
dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime); // set modification date |
dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED; // update startcluster |
dir[file->DirectoryIndex].Size = 0; |
// write sector containing the direntry |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
{ |
Fat16_Deinit(); |
return(NULL); |
} |
file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
file->SectorOfCurrCluster = 0; |
file->ByteOfCurrSector = 0; |
1501,8 → 1612,11 |
} |
|
dir = (DirEntry_t *)file->Cache; |
// update dile size and modification time & date |
dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime); |
dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime); |
dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
dir[file->DirectoryIndex].Size = file->Size; // update file size |
dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime); // update date time |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to sd-card |
{ |
Fat16_Deinit(); |
1511,6 → 1625,7 |
break; |
case 'r': |
default: |
// do nothing! |
return(EOF); |
break; |
|
1603,57 → 1718,68 |
u32 curr_sector = 0; |
|
if((!Partition.IsValid) || (file == NULL)) return(EOF); |
|
// If file position equals to file size, then the end of file has reached. |
// In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR |
// and a new cluster should be appended. |
if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) |
switch(file->Mode) |
{ |
if(!AppendCluster(file)) return(EOF); |
} |
|
curr_sector = file->FirstSectorOfCurrCluster; |
curr_sector += file->SectorOfCurrCluster; |
if(file->SectorInCache != curr_sector) |
{ |
file->SectorInCache = curr_sector; |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) |
{ |
Fat16_Deinit(); |
return(EOF); |
} |
} |
|
file->Cache[file->ByteOfCurrSector] = (u8)c; // write databyte into the buffer. The byte will be written to the device at once |
if(file->Size == file->Position) file->Size++; // a character has been written to the file so the size is incremented only when the character has been added at the end of the file. |
file->Position++; // the actual positon within the file. |
file->ByteOfCurrSector++; // goto next byte in sector |
if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet |
{ // save the sector to the sd-card |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
{ |
Fat16_Deinit(); |
return(EOF); |
} |
file->ByteOfCurrSector = 0; // reset byte location |
file->SectorOfCurrCluster++; // next sector |
if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT. |
{ |
if(!GetNextCluster(file)) // Sets the clusterpointer of the file to the next datacluster. |
{ // if current cluster was the last cluster of the file |
if(!AppendCluster(file)) // append a new and free cluster at the end of the file. |
case 'w': |
case 'a': |
// If file position equals to file size, then the end of file has been reached. |
// In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR |
// and a new cluster should be appended. |
// If the first sector of first cluster is unvalid, then the file claims no data clusters |
// and size should be zero, therefore append a new Cluster too. |
if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)) |
{ |
if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF); |
} |
|
curr_sector = file->FirstSectorOfCurrCluster; |
curr_sector += file->SectorOfCurrCluster; |
if(file->SectorInCache != curr_sector) |
{ |
file->SectorInCache = curr_sector; |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) |
{ |
file->SectorOfCurrCluster--; // jump back to last sector of last cluster |
file->ByteOfCurrSector = BYTES_PER_SECTOR; // set byte location to 1 byte over sector len |
return(EOF); |
Fat16_Deinit(); |
return(EOF); |
} |
} |
else // next cluster |
{ |
file->SectorOfCurrCluster = 0; // start reading new cluster at first sector of the cluster. |
|
file->Cache[file->ByteOfCurrSector] = (u8)c; // write databyte into the buffer. The byte will be written to the device at once |
if(file->Size == file->Position) file->Size++; // a character has been written to the file so the size is incremented only when the character has been added at the end of the file. |
file->Position++; // the actual positon within the file. |
file->ByteOfCurrSector++; // goto next byte in sector |
if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet |
{ // save the sector to the sd-card |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
{ |
Fat16_Deinit(); |
return(EOF); |
} |
file->ByteOfCurrSector = 0; // reset byte location |
file->SectorOfCurrCluster++; // next sector |
if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT. |
{ |
if(!GetNextCluster(file)) // Sets the clusterpointer of the file to the next datacluster. |
{ // if current cluster was the last cluster of the file |
if(!AppendCluster(file)) // append a new and free cluster at the end of the file. |
{ |
file->SectorOfCurrCluster--; // jump back to last sector of last cluster |
file->ByteOfCurrSector = BYTES_PER_SECTOR; // set byte location to 1 byte over sector len |
return(EOF); |
} |
} |
else // next cluster |
{ |
file->SectorOfCurrCluster = 0; // start reading new cluster at first sector of the cluster. |
} |
} |
} |
} |
} |
break; |
case 'r': |
default: |
return(EOF); |
break; |
} // EOF switch(file->Mode) |
return(0); |
} |
|
1718,7 → 1844,7 |
s16 c; |
|
if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0); |
|
if(file->Mode == 'r') return (0); // opened read only |
pbuff = (u8 *) buffer; // cast the void pointer to an u8 * |
|
while((object_cnt < count) && success) |
1756,8 → 1882,8 |
u8 i=0; |
s16 c = 0; |
|
if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0); |
|
if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF); |
if(file->Mode == 'r') return(EOF); |
while((string[i] != 0)&& (c != EOF)) |
{ |
c = fputc_(string[i], file); |