429,6 → 429,7 |
/****************************************************************************************************************************************/ |
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 |
} |
443,10 → 444,37 |
/****************************************************************************************************************************************/ |
u16 SectorToFat16Cluster(u32 sector) |
{ |
if(!Partition.IsValid) return 0; |
return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2); |
} |
|
|
/****************************************************************************************************************************************/ |
/* Function: Fat16_Deinit(void); */ |
/* */ |
/* Description: This function uninitializes the fat 16 api */ |
/* */ |
/* Returnvalue: The function returns "0" on success */ |
/****************************************************************************************************************************************/ |
u8 Fat16_Deinit(void) |
{ |
s16 returnvalue = 0; |
u8 cnt; |
// declare the filepointers as unused. |
for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
{ |
if(FilePointer[cnt].State == FSTATE_USED) |
{ |
returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers |
} |
|
} |
SDC_Deinit(); // uninitialize interface to sd-card |
Partition.IsValid = 0; // mark data in partition structure as invalid |
return(returnvalue); |
} |
|
/****************************************************************************************************************************************/ |
/* Function: Fat16_Init(void); */ |
/* */ |
/* Description: This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir */ |
454,7 → 482,7 |
/* */ |
/* Returnvalue: The function returns "0" if the filesystem is initialized. */ |
/****************************************************************************************************************************************/ |
s16 Fat16_Init(void) |
u8 Fat16_Init(void) |
{ |
u8 cnt = 0; |
u32 PartitionFirstSector; |
461,6 → 489,7 |
VBR_Entry_t *VBR; |
MBR_Entry_t *MBR; |
File_t *File; |
u8 result; |
|
Partition.IsValid = 0; |
|
476,10 → 505,11 |
cnt = 0; |
while(SD_SUCCESS != SDC_Init()) |
{ |
if(cnt > 5) |
if(cnt > 3) |
{ |
SerialPutString("SD-Card could not be initialized.\r\n"); |
return(1); |
result = 1; |
goto end; |
} |
cnt++; |
} |
488,27 → 518,33 |
if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,File->Cache)) // Read the MasterBootRecord |
{ |
SerialPutString("Error reading the MBR.\r\n"); |
return(2); |
result = 2; |
goto end; |
} |
MBR = (MBR_Entry_t *)File->Cache; // Enter the MBR using the structure MBR_Entry_t. |
if(MBR->PartitionEntry1.Type != PART_TYPE_FAT16) |
if(MBR->PartitionEntry1.Type == PART_TYPE_FAT16) |
{ |
SerialPutString("MBR: 1st Partition ist not FAT16 type.\r\n"); |
return(1); |
// get sector offset 1st partition |
PartitionFirstSector = MBR->PartitionEntry1.NoSectorsBeforePartition; |
// Start of Partition is the Volume Boot Sector |
if(SD_SUCCESS != SDC_GetSector(PartitionFirstSector,File->Cache)) // Read the volume boot record |
{ |
SerialPutString("Error reading the VBR.\r\n"); |
result = 3; |
goto end; |
} |
} |
// get sector offset 1st partition |
PartitionFirstSector = MBR->PartitionEntry1.NoSectorsBeforePartition; |
// Start of Partition is the Volume Boot Sector |
if(SD_SUCCESS != SDC_GetSector(PartitionFirstSector,File->Cache)) // Read the volume boot record |
else // maybe the medium has no partition assuming sector 0 is the vbr |
{ |
SerialPutString("Error reading the VBR of 1st partition.\r\n"); |
return(2); |
} |
PartitionFirstSector = 0; |
} |
|
VBR = (VBR_Entry_t *) File->Cache; // Enter the VBR using the structure VBR_Entry_t. |
if(VBR->BytesPerSector != BYTES_PER_SECTOR) |
{ |
SerialPutString("Sector size of 1st partition not supported.\r\n"); |
return(3); |
SerialPutString("VBR: Sector size not supported.\r\n"); |
result = 4; |
goto end; |
} |
Partition.SectorsPerCluster = VBR->SectorsPerCluster; // Number of sectors per cluster. Depends on the memorysize of the sd-card. |
Partition.FatCopies = VBR->NoFATCopies; // Number of fatcopies. |
528,8 → 564,9 |
// Calculate the last data sector |
if(VBR->NoSectors == 0) |
{ |
SerialPutString("Bad nuber of sectors in this partition.\r\n"); |
return(4); |
SerialPutString("VBR: Bad number of sectors.\r\n"); |
result = 5; |
goto end; |
} |
Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1; |
// check for FAT16 in VBR of first partition |
536,37 → 573,18 |
if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6'))) |
{ |
SerialPutString("VBR: Partition ist not FAT16 type.\r\n"); |
return (2); |
result = 6; |
goto end; |
} |
Partition.IsValid = 1; // mark data in partition structure as valid |
return(0); |
result = 0; |
end: |
if(result != 0) Fat16_Deinit(); |
return(result); |
} |
|
/****************************************************************************************************************************************/ |
/* Function: Fat16_Deinit(void); */ |
/* */ |
/* Description: This function uninitializes the fat 16 api */ |
/* */ |
/* Returnvalue: The function returns "0" on success */ |
/****************************************************************************************************************************************/ |
s16 Fat16_Deinit(void) |
{ |
s16 returnvalue = 0; |
u8 cnt; |
// declare the filepointers as unused. |
for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
{ |
if(FilePointer[cnt].State == FSTATE_USED) |
{ |
returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers |
} |
|
} |
SDC_Deinit(); // uninitialize interface to sd-card |
Partition.IsValid = 0; // mark data in partition structure as invalid |
return(returnvalue); |
} |
|
|
/****************************************************************************************************************************************/ |
/* Function: ClearCurrCluster(File_t file); */ |
/* */ |
578,11 → 596,18 |
{ |
u8 retvalue = 1; |
u32 i; |
|
if((!Partition.IsValid) || (File == 0)) return(0); |
|
for(i = 0; i < BYTES_PER_SECTOR; i++) File->Cache[i] = 0; // clear file cache |
for(i = 0; i < Partition.SectorsPerCluster; i++) |
{ |
File->SectorInCache = File->FirstSectorOfCurrCluster + i; |
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) retvalue = 0; |
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) |
{ |
Fat16_Deinit(); |
retvalue = 0; |
} |
} |
return(retvalue); |
} |
600,7 → 625,7 |
u32 fat_byte_offset, sector, byte; |
Fat16Entry_t * Fat; |
|
if(File == 0) return(cluster); |
if((!Partition.IsValid) || (File == 0)) return(cluster); |
// if sector is within the data area |
if((Partition.FirstDataSector <= File->FirstSectorOfCurrCluster)&& (File->FirstSectorOfCurrCluster <= Partition.LastDataSector)) |
{ |
616,7 → 641,11 |
if(File->SectorInCache != sector) |
{ |
File->SectorInCache = sector; // update sector stored in buffer |
SDC_GetSector(File->SectorInCache, File->Cache); // read sector from sd-card |
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) // read sector from sd-card |
{ |
Fat16_Deinit(); |
return (cluster); |
} |
} |
// read the next cluster from cache |
Fat = (Fat16Entry_t *)(&(File->Cache[byte])); |
632,7 → 661,7 |
File->SectorOfCurrCluster = 0; |
File->ByteOfCurrSector = 0; |
} |
} |
} |
return(cluster); |
} |
|
652,7 → 681,7 |
u16 free_cluster = 0; // next free cluster number. |
Fat16Entry_t * Fat; |
|
if(File == 0) return(0); |
if((!Partition.IsValid) || (File == 0)) return(0); |
|
// start searching for an empty cluster at the beginning of the fat. |
fat_sector = 0; |
662,6 → 691,7 |
File->SectorInCache = curr_sector; // upate the sector number of file cache. |
if( SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) // read sector of fat from sd-card. |
{ |
Fat16_Deinit(); |
return(free_cluster); |
} |
|
674,6 → 704,7 |
Fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX; // mark this fat-entry as used |
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) // and save the sector at the sd-card. |
{ |
Fat16_Deinit(); |
return(free_cluster); |
} |
free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry); |
682,7 → 713,7 |
} |
fat_sector++; // continue the search in next fat sector |
// repeat until the end of the fat is reached and no free cluster has been found so far |
}while((fat_sector < Partition.SectorsPerFat) && (!free_cluster)); |
}while((fat_sector < Partition.SectorsPerFat) && (!free_cluster)); |
return(free_cluster); |
} |
|
699,7 → 730,7 |
s32 fposition = 0; |
s16 retvalue = 1; |
|
if(!Partition.IsValid) return(0); |
if((!Partition.IsValid) || (File == 0)) return(0); |
switch(origin) |
{ |
case SEEK_SET: // Fileposition relative to the beginning of the file. |
765,6 → 796,8 |
u32 fat_byte_offset, sector, byte; |
Fat16Entry_t * Fat; |
|
if((!Partition.IsValid) || (File == 0)) return(new_cluster); |
|
new_cluster = FindNextFreeCluster(File); // the next free cluster found on the disk. |
if(new_cluster) |
{ // A free cluster was found and can be added to the end of the file. |
779,6 → 812,7 |
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); |
} |
} |
786,12 → 820,12 |
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); |
} |
File->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster); |
File->SectorOfCurrCluster = 0; |
File->ByteOfCurrSector = 0; |
ClearCurrCluster(File); |
} |
return(new_cluster); |
} |
814,7 → 848,7 |
DirEntry_t * Dir; |
|
// if incomming pointers are useless return immediatly |
if((File == 0) || (dirname == 0)) return(direntry_exist); |
if((!Partition.IsValid) || (File == 0) || (dirname == 0)) return(direntry_exist); |
|
// dir entries can be searched only in filesclusters that have |
// a corresponding dir entry with adir-flag set in its attribute |
843,7 → 877,11 |
{ |
// 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. |
SDC_GetSector(File->SectorInCache, File->Cache); // read in the sector. |
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(direntry_exist); |
} |
Dir = (DirEntry_t *)File->Cache; // set pointer to directory |
switch(Dir[File->DirectoryIndex].Name[0]) // check if current directory exist |
{ |
875,7 → 913,11 |
{ |
curr_sector = File->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
File->SectorInCache = curr_sector; // upate the sector number of file cache. |
SDC_GetSector(File->SectorInCache, File->Cache); // read the sector |
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache))// read the sector |
{ |
Fat16_Deinit(); |
return(direntry_exist); |
} |
Dir = (DirEntry_t *)File->Cache; // set pointer to directory |
// search all directory entries within that sector |
for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++) |
938,7 → 980,7 |
u8 retvalue = 0; |
DirEntry_t *Dir; |
|
if((File == 0) || (dirname == 0)) return (retvalue); |
if((!Partition.IsValid) || (File == 0) || (dirname == 0)) return (retvalue); |
// It is not checked here that the dir entry that should be created is already existent! |
|
// Dir entries can be created only in file-clusters that have |
968,7 → 1010,11 |
{ |
// 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. |
SDC_GetSector(File->SectorInCache, File->Cache); // read in the sector. |
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 |
switch(Dir[File->DirectoryIndex].Name[0]) // check if current directory exist |
{ |
999,7 → 1045,11 |
{ |
curr_sector = File->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
File->SectorInCache = curr_sector; // upate the sector number of file cache. |
SDC_GetSector(File->SectorInCache, 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++) |
1010,7 → 1060,11 |
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].Size = 0; // the new createted file has no content yet. |
SDC_PutSector(File->SectorInCache, File->Cache); // write back to card |
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) // write back to card |
{ |
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 |
1023,7 → 1077,11 |
{ |
ClearCurrCluster(File); // fill cluster with zeros |
File->SectorInCache = File->FirstSectorOfFirstCluster; |
SDC_GetSector(File->SectorInCache, File->Cache); |
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; |
1038,7 → 1096,11 |
Dir[1].Attribute = ATTR_SUBDIRECTORY; |
Dir[1].StartCluster = DirCluster; |
Dir[1].Size = 0; |
SDC_PutSector(File->SectorInCache, File->Cache); |
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 |
1299,29 → 1361,40 |
|
if((File == 0) || (!Partition.IsValid)) return (EOF); |
|
if(File->Mode == 'a') |
switch(File->Mode) |
{ |
if(File->ByteOfCurrSector > 0) // has data been added to the file? |
{ |
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache))// save the data still in the buffer |
case 'a': |
case 'w': |
if(File->ByteOfCurrSector > 0) // has data been added to the file? |
{ |
return(EOF); |
} |
} |
File->SectorInCache = File->DirectorySector; |
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) // read the directory entry for this file. |
{ |
return(EOF); |
} |
|
Dir = (DirEntry_t *)File->Cache; |
Dir[File->DirectoryIndex].Size = File->Size; // update file size |
Dir[File->DirectoryIndex].Time = time; // update time |
Dir[File->DirectoryIndex].Date = date; // update date |
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) // write back to sd-card |
{ |
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache))// save the data still in the buffer |
{ |
Fat16_Deinit(); |
return(EOF); |
} |
} |
File->SectorInCache = File->DirectorySector; |
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) // read the directory entry for this file. |
{ |
Fat16_Deinit(); |
return(EOF); |
} |
|
Dir = (DirEntry_t *)File->Cache; |
Dir[File->DirectoryIndex].Size = File->Size; // update file size |
Dir[File->DirectoryIndex].Time = time; // update time |
Dir[File->DirectoryIndex].Date = date; // update date |
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) // write back to sd-card |
{ |
Fat16_Deinit(); |
return(EOF); |
} |
break; |
case 'r': |
default: |
return(EOF); |
} |
break; |
|
} |
return(0); |
} |
1367,7 → 1440,11 |
if(File->SectorInCache != curr_sector) |
{ |
File->SectorInCache = curr_sector; |
SDC_GetSector(File->SectorInCache, File->Cache); |
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) |
{ |
Fat16_Deinit(); |
return(c); |
} |
} |
c = (s16) File->Cache[File->ByteOfCurrSector]; |
File->Position++; // increment file position |
1411,7 → 1488,7 |
// 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)) |
if((File->Position >= File->Size) && (File->ByteOfCurrSector >= BYTES_PER_SECTOR)) |
{ |
if(!AppendCluster(File)) return(EOF); |
} |
1423,6 → 1500,7 |
File->SectorInCache = curr_sector; |
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) |
{ |
Fat16_Deinit(); |
return(EOF); |
} |
} |
1435,6 → 1513,7 |
{ // 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 |