Subversion Repositories NaviCtrl

Compare Revisions

Ignore whitespace Rev 378 → Rev 379

/trunk/fat16.c
54,13 → 54,14
// + Note: For information on license extensions (e.g. commercial use), please contact us at info(@)hisystems.de.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <stdio.h>
#include <string.h>
#include "91x_lib.h"
#include "timer1.h"
#include "fat16.h"
#include "sdc.h"
#include "uart1.h"
#include "logging.h"
#include "led.h"
#include "main.h"
 
//________________________________________________________________________________________________________________________________________
// Module name: fat16.c
// Compiler used: avr-gcc 3.4.5
106,6 → 107,7
*/
 
 
 
/*
________________________________________________________________________________________________________________________________________
 
126,6 → 128,8
u32 NoSectorsPartition ; // Number of Sectors in the Partition
} __attribute__((packed)) PartitionEntry_t;
 
 
 
/*
Coding of Cylinder/Sector words
 
309,14 → 313,18
u32 FirstRootDirSector; // sector of the rootdirectory
u32 FirstDataSector; // sector of the first cluster containing data (cluster2).
u32 LastDataSector; // the last data sector of the partition
u8 VolumeLabel[12]; // the volume label
} Partition_t;
u8 VolumeLabel[12]; // the volume label
u32 CurrentWorkingDirectory;// A pointer to the directory we are actual using
s8 PathToCwd[256]; // a string containing the complete path to the current working directory
} __attribute__((packed)) Partition_t;
 
Partition_t Partition; // Structure holds partition information
Partition_t Partition; // Structure holds partition information
 
File_t FilePointer[FILE_MAX_OPEN]; // Allocate Memmoryspace for each filepointer used.
 
 
 
 
/****************************************************************************************************************************************/
/* Function: FileDate(DateTime_t *); */
/* */
444,6 → 452,28
// clear dirname with spaces
dirname[11] = 0; // terminate dirname
for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
 
// handle the special dirnames "." and ".." seperately
readpointer = 0;
if(filepath[0] == '/') readpointer++;
// if we are trying to enter directories "." or ".."
if(filepath[readpointer] == '.')
{
// directory '.'
if(filepath[readpointer+1] == 0)
{
dirname[0] = '.';
return((s8*)&filepath[readpointer]);
}
// directory '..'
if((filepath[readpointer+1] == '.') && (filepath[readpointer+2] == 0))
{
dirname[0] = '.';
dirname[1] = '.';
return((s8*)&filepath[readpointer]);
}
}
 
writepointer = 0;
// start seperating the dirname from the filepath.
readpointer = 0;
549,7 → 579,7
Partition.IsValid = 0; // mark data in partition structure as invalid
Partition.VolumeLabel[0]='\0';
UART1_PutString("ok");
SD_LoggingError = 100;
SD_WatchDog = 0;
return(returnvalue);
}
 
572,7 → 602,6
 
UART1_PutString("\r\n FAT16 init...");
Partition.IsValid = 0;
 
// declare the filepointers as unused.
for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
{
655,6 → 684,8
goto end;
}
Partition.IsValid = 1; // mark data in partition structure as valid
Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
strcpy(Partition.PathToCwd,"/");
result = 0;
end:
if(result != 0) Fat16_Deinit();
686,8 → 717,7
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
{
Fat16_Deinit();
retvalue = 0;
return(retvalue);
return(0);
}
}
return(retvalue);
726,7 → 756,7
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card
{
Fat16_Deinit();
return (cluster);
return (CLUSTER_UNDEFINED);
}
}
// read the next cluster from cache
748,6 → 778,7
}
 
 
 
/****************************************************************************************************************************************/
/* Function: FindNextFreeCluster(File_t *); */
/* */
774,7 → 805,7
if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector of fat from sd-card.
{
Fat16_Deinit();
return(free_cluster);
return(CLUSTER_UNDEFINED);
}
 
fat = (Fat16Entry_t *)file->Cache; // set fat pointer to file cache
787,7 → 818,7
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // and save the sector at the sd-card.
{
Fat16_Deinit();
return(free_cluster);
return(CLUSTER_UNDEFINED);
}
free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);
fat_entry = FAT16_ENTRIES_PER_SECTOR; // terminate the search for a free cluster in this sector.
1038,7 → 1069,6
// dir entries can be searched only in filesclusters that have
// a corresponding dir entry with adir-flag set in its attribute
// or direct within the root directory area
 
file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
// no current directory exist therefore assume searching in the root
if(file->DirectorySector == SECTOR_UNDEFINED)
1065,7 → 1095,7
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(direntry_exist);
return(0);
}
dir = (DirEntry_t *)file->Cache; // set pointer to directory
switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist
1093,7 → 1123,7
 
do // loop over all data clusters of the current directory entry
{
dir_sector = 0; // reset sector counter within a new cluster
dir_sector = 0;
do // loop over all sectors of a cluster or all sectors of the root directory
{
curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number
1101,7 → 1131,7
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
{
Fat16_Deinit();
return(direntry_exist);
return(0);
}
dir = (DirEntry_t *)file->Cache; // set pointer to directory
// search all directory entries within that sector
1198,7 → 1228,7
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(retvalue);
return(0);
}
dir = (DirEntry_t *)file->Cache; // set pointer to directory
switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist
1240,7 → 1270,7
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(retvalue);
return(0);
}
 
dir = (DirEntry_t *)file->Cache; // set pointer to directory
1266,7 → 1296,7
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to card
{
Fat16_Deinit();
return(retvalue);
return(0);
}
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.
1284,7 → 1314,7
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(retvalue);
return(0);
}
dir = (DirEntry_t *)file->Cache;
// create direntry "." to current dir
1303,7 → 1333,7
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(retvalue);
return(0);
}
}
retvalue = 1;
1351,6 → 1381,14
path = (s8*)filename; // start a the beginning of the filename string
file->DirectorySector = 0; // start at RootDirectory with file search
file->DirectoryIndex = 0;
/* if a path begins with a '/' at index 0 the search starts at the rootdirectory otherwise we will start relative to the cwd */
if(path[0] != '/')
{
/* is the current working directory the rootdirectory? */
if(Partition.CurrentWorkingDirectory == Partition.FirstRootDirSector) file->DirectorySector = 0;
/* otherwise we are working in an subdirectory */
else file->DirectorySector = Partition.CurrentWorkingDirectory;
}
// as long as the file was not found and the remaining path is not empty
while((*path != 0) && !file_exist)
{ // separate dirname and subpath from filepath string
1461,6 → 1499,7
File_t * fopen_(s8 * const filename, const s8 mode)
{
File_t *file = 0;
s8 *cptr;
 
if((!Partition.IsValid) || (filename == 0)) return(file);
 
1483,6 → 1522,15
file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector.
file->Attribute = 0; // the attribute of the file opened.
 
// bring the path into the correct syntax
cptr = filename;
// search the whole string
while(*cptr != 0)
{
// replace all '\' by '/'
if(*cptr == '\\') *cptr = '/';
cptr++;
}
// check if a real file (no directory) to the given filename exist
if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
{ // file exist
1560,7 → 1608,7
{ // if it could not be created
fclose_(file);
file = NULL;
}
}
break;
case 'r': // else opened for 'r'
default: // if unsupported mode
1663,7 → 1711,7
 
if( (!Partition.IsValid) || (file == NULL)) return(c);
// if the end of the file is not reached, get the next character.
if((0 < file->Size) && ((file->Position+1) < file->Size) )
if((0 < file->Size) && ((file->Position) < file->Size) )
{
curr_sector = file->FirstSectorOfCurrCluster; // calculate the sector of the next character to be read.
curr_sector += file->SectorOfCurrCluster;
1674,7 → 1722,7
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
{
Fat16_Deinit();
return(c);
return(EOF);
}
}
c = (s16) file->Cache[file->ByteOfCurrSector];
1740,8 → 1788,8
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
2005,7 → 2053,7
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
{
Fat16_Deinit();
return(pVolumeLabel);
return(NULL);
}
dir = (DirEntry_t *)file->Cache; // set pointer to directory
// search all directory entries within that sector
2042,3 → 2090,447
UnlockFilePointer(file);
return(pVolumeLabel);
}
 
 
 
#define ATTR_NONE 0x00 // normal file
#define ATTR_READONLY 0x01 // file is readonly
#define ATTR_HIDDEN 0x02 // file is hidden
#define ATTR_SYSTEM 0x04 // file is a system file
#define ATTR_VOLUMELABEL 0x08 // entry is a volume label
#define ATTR_LONG_FILENAME 0x0F // this is a long filename entry
#define ATTR_SUBDIRECTORY 0x10 // entry is a directory name
#define ATTR_ARCHIVE 0x20 // file is new or modified
 
 
/********************************************************************************************************************************************/
/* Function: u8 FindItem(Find_t); */
/* */
/* Description: This function looks for the item specified by global structure FindElement in the actual directory */
/* */
/* */
/* Returnvalue: TRUE if an matching element was found */
/********************************************************************************************************************************************/
 
u8 FindItem(Find_t *findelement)
{
u16 index = 0;
u16 max_dir_sector = 0;
u16 end_of_directory_not_reached = 1; // the directory has been read completely without a result.
u8 i = 0;
u8 readpointer = 0;
u8 writepointer = 0;
u8 retvalue = 0;
DirEntry_t *DirectoryEntry;
File_t file;
 
file.FirstSectorOfCurrCluster = findelement->fp.FirstSectorOfCurrCluster;
file.SectorOfCurrCluster = findelement->fp.SectorOfCurrCluster;
index = findelement->fp.DirectoryIndex;
 
// within the root directory area we can read sectors sequentially until the end of this area
if((Partition.FirstRootDirSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster < Partition.FirstDataSector))
{
max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
}
// within the data clusters we can read sectors sequentially only within the cluster
else if((Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster <= Partition.LastDataSector))
{
max_dir_sector = Partition.SectorsPerCluster; // limit max secters before next cluster
}
 
do
{ // search the next 16 rootentries in this sector of the roordirectory.
if(SD_SUCCESS != SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache)); // Read the Rootdirectory.
{
Fat16_Deinit();
return(0);
}
DirectoryEntry = (DirEntry_t *)file.Cache;
 
while((!retvalue)&&(index<16))
{
i=0;
if((u8) DirectoryEntry[index].Name[0] != 0xe5) // ignore deleted items.
{
while((i<=10)&&((DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i]=='*') || findelement->searchstring[i]=='?'))
{
i++;
}
}
if((DirectoryEntry[index].Attribute <= 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i==11))
{
for(readpointer=0;readpointer<=10;readpointer++)
{
if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8))
{
findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure.
writepointer++;
}
else
{
if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE)
{
if(readpointer < 8) readpointer=8;
if(DirectoryEntry[index].Name[readpointer] != ' ')
{
findelement->name[writepointer] = '.'; // then seperate the name and the extension by a '.' at index 8.
writepointer++;
findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure.
writepointer++;
}
else break;
}
else break;
}
/* terminate the namestring with 0 for debugpurposes*/
findelement->name[12] = 0;
}
findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster;
findelement->fp.DirectoryIndex = index;
findelement->fp.FirstSectorOfCurrCluster = file.FirstSectorOfCurrCluster;
findelement->fp.DirectorySector = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster);
findelement->fp.SectorOfCurrCluster = file.SectorOfCurrCluster;
findelement->fp.Size = DirectoryEntry[index].Size;
findelement->fp.Attribute = DirectoryEntry[index].Attribute;
retvalue = 1;
}
/* search the next sector */
index++;
}
/* this sector has been searched but we havn't found what we are looking for. Therefore we have to find the next sector */
if(!retvalue) // file not found in this sector so take next sector.
{
/* in the next sector we start looking for the specified entry beginning at index 0 */
index = 0;
/* there are still sectors to be read within the cluster or within the linear addresspace of the rootdirectory */
if(file.SectorOfCurrCluster < max_dir_sector-1) file.SectorOfCurrCluster++; else end_of_directory_not_reached = 0;
/* if we are looking for an directoryentry outside the rootdirectory and have reached the end of the cluster we have to get the next one */
if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster)
{
end_of_directory_not_reached = GetNextCluster(&file);
}
}
}
while((end_of_directory_not_reached) && (!retvalue) );
 
return(retvalue);
}
 
 
 
 
/********************************************************************************************************************************************/
/* Function: findnext_(Find_t *); */
/* */
/* Description: This function looks for the next item in the specified directory with a matching filename and fileattributes specified */
/* by function findfirst() */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
u8 findnext_(Find_t * findelement)
{
u8 itemfound = 0;
u8 index = 0;
 
findelement->fp.DirectoryIndex++;
 
/* before we start searching an element we clear the complete namestring within the structure FindElement */
for(index=0;index<11;index++) findelement->name[index] = 0;
 
if(FindItem(findelement))
{
itemfound = 1;
}
 
return(itemfound);
}
 
 
 
/********************************************************************************************************************************************/
/* Function: findfirst_(s8* filename, u8 attribmask, Find_t *); */
/* */
/* Description: This function looks for the first item in the specified directory with a matching filename and fileattributes */
/* The filename of the element found is transformed from 8.3 to a string */
/* */
/* */
/* Returnvalue: (1) if Element was found. (0) if no valid element was found */
/********************************************************************************************************************************************/
u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement)
{
u8 itemfound = 0;
u8 index = 0;
 
/* initialize the FindElement structure */
findelement->fp.FirstSectorOfFirstCluster = 0; // First sector of the first cluster of the file.
findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory; // First sector of the cluster which is edited at the moment.
findelement->fp.SectorOfCurrCluster = 0; // The sector within the current cluster.
findelement->fp.ByteOfCurrSector = 0; // The byte location within the current sector.
findelement->fp.Size = 0; // The size of the opend file in bytes.
findelement->fp.Position = 0; // Pointer to a character within the file 0 < fileposition < filesize
findelement->fp.DirectorySector = 0; // the sectorposition where the directoryentry has been made.
findelement->fp.DirectoryIndex = 0; // The index to the directoryentry within the specified sector.
findelement->attribfilter = 0;
findelement->attribmask = attribmask;
findelement->searchstring[0]=0;
 
/* seperate the name of the element to be found from the filepath and bring it to the 8.3*/
SeperateDirName(name, findelement->searchstring);
/* after the name of the element is in 8.3 we process the wildcards (*). After an * all following character are wildcards to */
for(index=0;index<8;index++)
{
/* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
if(findelement->searchstring[index] == '*')
{
/* */
while(++index <8) findelement->searchstring[index] = '*';
}
}
for(index=8;index<11;index++)
{
/* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
if(findelement->searchstring[index] == '*')
{
/* */
while(++index <11) findelement->searchstring[index] = '*';
}
}
/* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */
findelement->fp.DirectoryIndex--;
/* now lets search for the item within the direcory */
itemfound = findnext_(findelement);
 
return(itemfound);
}
 
 
/********************************************************************************************************************************************/
/* Function: u8 GetDirCount(s8* filepath); */
/* */
/* Description: This function counts the number of subdirectories the dirpath contains */
/* */
/* */
/* Returnvalue: then number of subdirectories within the specified path */
/********************************************************************************************************************************************/
u8 GetDirCount(u8 *dirpath)
{
u8 i=0;
u8 cnt=0;
 
while(dirpath[i] != 0 )
{
if(dirpath[i]=='/')
{
if(dirpath[i+1]!=0) cnt++; // ignore last'/'
}
i++;
}
i=0;
return(cnt);
}
 
 
/********************************************************************************************************************************************/
/* Funtion: char *GetSubDirectory (char *dirpath, char *directory) */
/* */
/* Description: this function returns a pointer to the beginning of the next subdirectory or NULL */
/* */
/* */
/* returnvalue: number of subdirectories in the filepath */
/********************************************************************************************************************************************/
u8 * GetSubDirectory(u8 *dirpath, u8 *directory)
{
u8 *cptr = dirpath;
u8 *dptr = directory;
u8 *retvalue = NULL;
/* if the first character of the path is an '/' we go to the next character */
if(*cptr == '/') cptr++;
/* search end of path or subdirectory*/
while((*cptr != 0) && (*cptr != '/'))
{
*dptr = *cptr;
dptr++;
cptr++;
}
if(*cptr!=0) retvalue = ++cptr;
*dptr = 0;
 
return(retvalue);
}
 
/********************************************************************************************************************************************/
/* Function: s8 *GetPath(void); */
/* */
/* Description: This function function returns a pointer to the absolute path of the active partition */
/* */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
 
s8 *GetPath(void)
{
return(Partition.PathToCwd);
}
 
/********************************************************************************************************************************************/
/* Function: void SetPathToRoot(void); */
/* */
/* Description: This function sets the path to the rootdirectory */
/* */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
 
void SetPathToRoot(void)
{
/* lets point to the rootdirectory */
strcpy(Partition.PathToCwd, "/");
}
 
/********************************************************************************************************************************************/
/* Function: void AppendDirToPath(s8* directory); */
/* */
/* Description: This function function appends the name of an directory to the Path to the CWD */
/* */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
 
void AppendDirToPath(s8* directory)
{
/* append the name of the directory to the path */
strcat(Partition.PathToCwd, directory);
/* append a '/' after the directoryname */
strcat(Partition.PathToCwd, "/");
}
 
/********************************************************************************************************************************************/
/* Function: RemoveLastDirFromPath(void); */
/* */
/* Description: This function removes the last directory from the path to the cwd */
/* */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
 
void RemoveLastDirFromPath(void)
{
/* a pointer to the beginning of the absolute path to the cwd */
s8 * cptr = Partition.PathToCwd;
/* lets find the end of the path to the cwd */
while(*cptr != 0 ) cptr++;
/* if the path is terminated with an '/' */
if((*(cptr-1)) == '/') *(cptr-1)=0;
/* now lets find the beginning of the last directorientry */
while((*cptr != '/' ) && cptr > Partition.PathToCwd) cptr--;
/* is there one subdirectory left within the path? */
if(cptr > Partition.PathToCwd)
{
/* we delete the direntry by terminating the path with 0 */
*cptr = 0;
}
/* there is no subdirectory left within the path. Therefore we create the root instead. */
else
{
*cptr = '/';
*(cptr+1) = 0;
}
}
 
/********************************************************************************************************************************************/
/* Function: chdir_(s8* filepath); */
/* */
/* Description: This function changed the current working directory to the directory specified by the filepath */
/* by function findfirst() */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
/*
#define ATTR_NONE 0x00 // normal file
#define ATTR_READONLY 0x01 // file is readonly
#define ATTR_HIDDEN 0x02 // file is hidden
#define ATTR_SYSTEM 0x04 // file is a system file
#define ATTR_VOLUMELABEL 0x08 // entry is a volume label
#define ATTR_LONG_FILENAME 0x0F // this is a long filename entry
#define ATTR_SUBDIRECTORY 0x10 // entry is a directory name
#define ATTR_ARCHIVE 0x20 // file is new or modified
*/
 
u8 chdir_(s8 *path)
{
u8 retvalue = 0; // the value returned by this function
u32 ultemp = 0; // temp. variable
u8 *directory = path; // pointer to a directoryname within the path
u8 dircount = 0; // the number of subdirectoryentries within the path
u8 cache[64]; // a buffer containing the name of the subdirectory we are actually looking for
Find_t fe; // The findelement needed for function findfirst to find the subdirectoryentry
s8 tp[256]; // temporarily we remember the actual path until the operation has finished successfully
u32 cwdt = 0;
s8 *cptr;
 
/* bring the path into the correct syntax */
cptr = path;
/* search the whole string */
while(*cptr != 0 )
{
if(*cptr == '\\') *cptr = '/';
cptr++;
}
/* lets remember the actual path */
strcpy(tp, Partition.PathToCwd);
cwdt = Partition.CurrentWorkingDirectory;
/* how many subdirectories are there within the path? */
dircount = GetDirCount(path);
/* if the path is absolute we begin at the rootdirectory */
if(path[0] == '/')
{
strcpy(Partition.PathToCwd, "/");
Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
/* if there is no other pathinformation we only switch to the rootdirectory. So theres nothing left todo.*/
if(!dircount) return(1);
}
/* now we parse through all the subdirectories within the path */
do
{
/* until all the subdirectories within the path have been processed */
if(dircount) dircount--;
/* this is the name of the next subdirectory we are looking for */
directory = GetSubDirectory(directory, cache);
/* search for the next subdirectory within the path */
if(findfirst_(cache, ATTR_SUBDIRECTORY, &fe))
{
/* we try to change into the directory "..". Now we have to delete the last direntry from the path */
if(strcmp(cache,"..") == 0) RemoveLastDirFromPath();
/* we try to change into the actual directory so there's nothing todo */
else if(cache[0] == '.') return(1);
/* otherwise we append the name of the directory we are changing in to the path */
else AppendDirToPath(cache);
/* The startcluster within an directoryentry specifies the position within the fat where the file or directory starts */
ultemp = (u32) fe.fp.FirstSectorOfFirstCluster;
/* the first 2 entries are reserved for '.' and '..' */
ultemp -= 2;
/* now we have to transform the position within the fat into the corrosponding sectoraddress relative to the beginning of the datasection of the active partition*/
ultemp *= Partition.SectorsPerCluster;
/* at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition */
ultemp += Partition.FirstDataSector;
/* the cwd now points to the specified directory */
Partition.CurrentWorkingDirectory = ultemp;
/* we found the folder specified by the foldername */
retvalue = 1;
}
}
/* do this until all subdirectories have been found or a subdirectory is missing */
while(dircount && retvalue );
 
/* if we could not change to the specified directory we restore the actual path */
if(!retvalue)
{
Partition.CurrentWorkingDirectory = cwdt;
strcpy(Partition.PathToCwd, tp);
}
return(retvalue);
}
/trunk/fat16.h
38,8 → 38,35
u8 State; // State of the filepointer (used/unused/...)
} File_t;
 
#define ATTR_NONE 0x00 // normal file
#define ATTR_READONLY 0x01 // file is readonly
#define ATTR_HIDDEN 0x02 // file is hidden
#define ATTR_SYSTEM 0x04 // file is a system file
#define ATTR_VOLUMELABEL 0x08 // entry is a volume label
#define ATTR_LONG_FILENAME 0x0F // this is a long filename entry
#define ATTR_SUBDIRECTORY 0x10 // entry is a directory name
#define ATTR_ARCHIVE 0x20 // file is new or modified
#define ATTR_ANY_FILE 0x3F // all files
 
 
 
//________________________________________________________________________________________________________________________________________
//
// Structure of an item used by functions findfirst and findnext
//________________________________________________________________________________________________________________________________________
 
typedef struct
{
File_t fp; // filepointer used to get access to the filesystemstructure
s8 searchstring[11]; // findfirst and findnext will only return elements within the specified directory matching this searchstring.
s8 name[13]; // the name of the element found within the specified directory
u8 active; // if the attribute active is set the name and the attributes of an element found within DirectoryEntryExist will be entered into the structure
u8 attribfilter;
u8 attribmask;
} __attribute__((packed)) Find_t;
 
//________________________________________________________________________________________________________________________________________
//
// API to the FAT16 filesystem
//
62,9 → 89,14
s16 fputs_(s8 * const string, File_t * const file);
s8 * fgets_(s8 * const string, s16 length, File_t * const file);
u8 feof_(File_t * const file);
u8 findfirst_(const s8* name, u8 attribmask, Find_t *);
u8 findnext_(Find_t *);
u8 chdir_(s8 *folder);
s8 *GetPath(void);
 
 
 
 
#endif //_FAT16_H
 
 
/trunk/logging.c
68,7 → 68,7
 
u8 SD_LoggingError = 0;
 
#define LOG_FLUSH_INTERVAL 2000 // 20s //##
#define LOG_FLUSH_INTERVAL 20000 // 20s //##
 
typedef enum
{
/trunk/main.h
14,7 → 14,7
 
#define VERSION_MAJOR 0
#define VERSION_MINOR 28
#define VERSION_PATCH 5
#define VERSION_PATCH 6
// 0 = A
// 1 = B
// 2 = C
/trunk/sdc.c
521,9 → 521,10
goto end;
}
//SSC_Disable(); // set SD_CS high
// here is the right place to inrease the SPI boud rate to maximum
//SSC_Enable(); // set SD_CS high
SSC_Disable(); // set SD_CS high
// here is the right place to inrease the SPI baud rate to maximum
SSC_Speed(2000);
SSC_Enable(); // set SD_CS high
 
// read CID register
result = SDC_GetCID((u8 *)&SDCardInfo.CID);
/trunk/spi_slave.c
722,13 → 722,13
/*
//+++++++++++++++++++++++++++++++++++++++++++++++++++
*/
/*
 
if(Parameter.User8 < 100) FC.StatusFlags = 0;
else
if(Parameter.User8 < 150) FC.StatusFlags = FC_STATUS_START;
else FC.StatusFlags = FC_STATUS_FLY | FC_STATUS_MOTOR_RUN;
BL_MinOfMaxPWM = 255;
*/
 
DebugOut.Analog[0] = FromFlightCtrl.AngleNick;
DebugOut.Analog[1] = FromFlightCtrl.AngleRoll;
DebugOut.Analog[2] = FromFlightCtrl.AccNick;
/trunk/ssc.c
119,10 → 119,30
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
void SSC_Speed(u32 speed)
{
SSP_InitTypeDef SSP_InitStructure;
 
SSP_Cmd(SSP1, DISABLE);
SSP_DeInit(SSP1);
SSP_StructInit(&SSP_InitStructure);
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola;
SSP_InitStructure.SSP_Mode = SSP_Mode_Master;
SSP_InitStructure.SSP_CPHA = SSP_CPHA_1Edge;
SSP_InitStructure.SSP_CPOL = SSP_CPOL_Low;
// Set Baud Rate (Prescaler)
// bit rate is BRCLK/SSP_ClockPrescaler/(1+SSP_ClockRate))
// With MSCLK = 48MHz = BRCLK we get for the SPICLK = 48Mhz / 20 / (1+5) = 400 kHz
SSP_InitStructure.SSP_ClockRate = 5; //5
SSP_InitStructure.SSP_ClockPrescaler = (48000 / (5+1)) / speed;
SSP_Init(SSP1, &SSP_InitStructure);
SSP_Cmd(SSP1, ENABLE);
}
 
 
void SSC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SSP_InitTypeDef SSP_InitStructure;
// WIU_InitTypeDef WIU_InitStructure;
// enable APB clock for SPI1
SCU_APBPeriphClockConfig(__SSP1 ,ENABLE);
151,18 → 171,7
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init (GPIO3, &GPIO_InitStructure);
// configure SPI1
SSP_DeInit(SSP1);
SSP_StructInit(&SSP_InitStructure);
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola;
SSP_InitStructure.SSP_Mode = SSP_Mode_Master;
SSP_InitStructure.SSP_CPHA = SSP_CPHA_1Edge;
SSP_InitStructure.SSP_CPOL = SSP_CPOL_Low;
// Set Baud Rate (Prescaler)
// bit rate is BRCLK/SSP_ClockPrescaler/(1+SSP_ClockRate))
// With MSCLK = 48MHz/2 = BRCLK we get for the SPICLK = 24Mhz / 8 / (1+5) = 500 kHz
SSP_InitStructure.SSP_ClockRate = 5; //5
SSP_InitStructure.SSP_ClockPrescaler = 4; //8
SSP_Init(SSP1, &SSP_InitStructure);
SSC_Speed(400);
SSC_Disable();
SSP_Cmd(SSP1, ENABLE);
 
/trunk/ssc.h
17,6 → 17,6
void SSC_Enable(void);
void SSC_Disable(void);
void SSC_ClearRxFifo(void);
void SSC_Speed(u32);
 
 
#endif //_SSC_H