⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileio.c

📁 SD卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************
 *
 *       PIC18 C18 Secure Digital and Multimedia Cards Interface
 *
 ******************************************************************************
 * FileName:        fileio.c
 * Dependencies:    generic.h
 *					fileio.h
 *					sdmmc.h
 *					string.h
 *					stdlib.h
 *					ctype.h
 *					_FATDefs.h
 * Processor:       PIC18
 * Compiler:        C18
 * Company:         Microchip Technology, Inc.
 *
 
 * Author   zhouyi 2008.8.11    
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*********************************************************************************/

#include "fileio.h"
#include "sdmmc.h"
#include "generic.h"
#include "string.h"
#include "stdlib.h"
#include "ctype.h"
#include "_FATDefs.h"


// Define arrays for file allocation
#ifndef FAT16_DYNAMIC_MEM
	MYFILE	gFileArray[FAT16_MAX_FILES_OPEN];
	BYTE 	gFileSlotOpen[FAT16_MAX_FILES_OPEN];
#endif

// DOS directory entry structure
typedef struct __DIRENTRY
{
        char        DIR_Name[DIR_NAMESIZE];      // Name
        char        DIR_Extension[DIR_EXTENSION]; // Extension
        BYTE          DIR_Attr;         // Attributes
        BYTE          DIR_NTRes;        // reserved by NT
        BYTE          DIR_CrtTimeTenth; // millisecond stamp
        WORD         DIR_CrtTime;      // time created
        WORD         DIR_CrtDate;      // date created
        WORD         DIR_LstAccDate;   // Last Access date
        WORD         DIR_FstClusHI;    // high word of this enty's first cluster number
        WORD         DIR_WrtTime;      // last update time
        WORD         DIR_WrtDate;      // last update date
        WORD         DIR_FstClusLO;    // low word of this entry's first cluster number
        DWORD         DIR_FileSize;     // file size in DWORD
}_DIRENTRY;

typedef _DIRENTRY * DIRENTRY;

// directory entry management
#define DIR_ESIZE   32      // size of a directory entry (BYTEs)
#define DIR_NAME    0       // offset of file name
#define DIR_EXT     8       // offset of file extension
#define DIR_ATTRIB  11      // offset of attribute( 00ARSHDV) (BYTE)
#define DIR_TIME    22      // offset of last use time  (WORD)
#define DIR_DATE    24      // offset of last use date  (WORD)
#define DIR_CLST    26      // offset of first cluster in FAT (WORD)
#define DIR_SIZE    28      // offset of file size (DWORD)
#define DIR_DEL     0xE5    // marker of a deleted entry
#define DIR_EMPTY   0       // marker of last entry in directory

// number of directory entries in one sector
#define DIRENTRIES_PER_SECTOR   0x10

#define RAMwrite( a, f, d) *(a+f) = d
#define RAMread( a, f)  *(a+f)
#define RAMreadW( a, f) *(WORD *)(a+f)
#define RAMreadD( a, f) *(DWORD *)(a+f)

extern unsigned char BSR;
MYFILE *gBufferOwner = NULL;
WORD lastClusterRead = 0xFFFF;

// internal errors
#define CE_FAT_EOF              60   // fat attempt to read beyond EOF
#define CE_EOF                  61   // reached the end of file   

// since we use an address generator, FILE is not actually the cast of what we pass
typedef MYFILE        * FILEOBJ;

#define FILEEXTPAGESIZE         sizeof(_FILEEXTND)

#define SIZEOF(s,m)             ((size_t) sizeof(((s *)0)->m)) 


// Private functions

WORD FATread( DISK *dsk, WORD ccls);
DIRENTRY Cache_File_Entry( FILEOBJ fo, WORD * curEntry, BYTE ForceRead);
BYTE Fill_File_Object(FILEOBJ fo, WORD *fHandle);
DWORD Cluster2Sector(DISK * disk, WORD cluster);
BYTE FAT_erase_cluster_chain (WORD cluster, DISK * dsk);
WORD FATfindEmptyCluster(FILEOBJ fo);
WORD FATReadQueued( DISK *dsk, WORD ccls);
DIRENTRY LoadDirAttrib(FILEOBJ fo, WORD *fHandle);
void IncrementTimeStamp(DIRENTRY dir);
BYTE FindEmptyEntries(FILEOBJ fo, WORD *fHandle);
BYTE PopulateEntries(FILEOBJ fo, char *name , WORD *fHandle);
CETYPE FILECreateHeadCluster( FILEOBJ fo, WORD *cluster);
BYTE EraseCluster(DISK *disk, WORD cluster);
void FileObjectCopy(FILEOBJ foDest,FILEOBJ foSource);
CETYPE CreateFirstCluster(FILEOBJ fo);
BYTE isShort ( char aChar);
extern BYTE WriteProtectState(void);
BYTE ValidateChars (char * FileName);
BYTE FormatFileName( const char* fileName, char* fN2 );

CETYPE __fread( MYFILE *fo, BYTE * dest, WORD count, WORD *pBytesRead);
CETYPE __fclose(FILEOBJ fo);
CETYPE __fwrite( MYFILE* fo, void * src, WORD count, WORD* pBytesWritten );
CETYPE __fseek (FILEOBJ fo, DWORD offset, BYTE origin);
MYFILE * __fopen (const char * fileName, const char *mode, MYFILE* filePtr );

CETYPE CreateFileEntry(FILEOBJ fo, WORD *fHandle);
CETYPE FILEfind( FILEOBJ foDest, FILEOBJ foCompareTo, BYTE cmd);
BYTE FILEget_next_cluster(FILEOBJ fo, WORD n);
BYTE FILEallocate_new_cluster( FILEOBJ fo);
CETYPE FILEopen (FILEOBJ fo, WORD *fHandle, char type);
CETYPE FILEerase( FILEOBJ fo, WORD *fHandle, BYTE EraseClusters);

/******************************************************************************
 * Function:        int FAT16Init()
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          int:	True if initialization successful, otherwise false
 *
 * Side Effects:    None
 *
 * Overview:        Initialize the static memory slots for holding
 *					file structures; only used when FAT16_DYNAMIC_MEM is
 *					not defined
 *
 * Note:            None
 *****************************************************************************/
unsigned char FAT16Init()
{
char result;

#ifndef FAT16_DYNAMIC_MEM
	int fIndex;

	for( fIndex = 0; fIndex < FAT16_MAX_FILES_OPEN; fIndex++ )
		gFileSlotOpen[fIndex] = TRUE;

//#else
//	SRAMInitHeap();

#endif
	result = MediaInit();
	return 	result;
//    ceer = result;
  
    
}

/******************************************************************************
 * Function:        FILE * my_fopen (const char * fileName, const char *  mode)
 *
 * PreCondition:    For read or append mode, file exists
 *
 * Input:           fileName	- The name of the file to open (stored in RAM)
 *					mode	- WRITE - Create a new file or replace an existing file
 *							  READ - Read data from an existing file
 *							  APPEND - Append data to an existing file
 *
 * Output:			FILE *	- The pointer to the file object
 *
 * Side Effects:    None
 *
 * Overview:        User called file open function (with fileName and mode 
 *					defined in RAM)
 *
 * Note:            None
 *****************************************************************************/
MYFILE * my_fopen( const char * fileName, const char *mode )
{

	MYFILE* 	filePtr;
	MYFILE* 	pFile;
	int		fIndex;

#ifdef FAT16_DYNAMIC_MEM
	filePtr = (MYFILE *) FAT16_malloc(sizeof(MYFILE));
#else

	filePtr = NULL;

	//Pick available file structure
	for( fIndex = 0; fIndex < FAT16_MAX_FILES_OPEN; fIndex++ )
	{
		if( gFileSlotOpen[fIndex] )	//this slot is available
		{
			gFileSlotOpen[fIndex] = FALSE;
			filePtr = &gFileArray[fIndex];
			break;
		}
	}

	if( filePtr == NULL )
		return NULL;		//no file structure slot available

#endif

	//try to open the file
	pFile = __fopen( fileName, mode, filePtr );

#ifdef FAT16_DYNAMIC_MEM

	if( pFile == NULL )
		FAT16_free( (unsigned char *)filePtr );
#else

	if( pFile == NULL )
		gFileSlotOpen[fIndex] = TRUE;	//put this slot back to the pool

#endif

	return pFile;
}

/******************************************************************************
 * Function:        CETYPE FILEfind( FILEOBJ foDest, FILEOBJ foCompareTo, BYTE cmd)
 *
 * PreCondition:    DISKmount function has been executed, foCompareTo loaded with
 *					file name
 *
 * Input:           foDest			- FILEOBJ containing information of file found
 *					foCompareTo		- FILEOBJ containing name of file to be found
 *					cmd				- 1 - search for a matching entry
 *									  2 - search for an empty entry
 *                  
 * Output:          CE_GOOD				- File found
 *                  CE_FILE_NOT_FOUND	- File not found 
 *
 * Side Effects:    None
 *
 * Overview:        Find a file given a name as passed via foCompareTo, place found in foDest
 *
 * Note:            None
 *****************************************************************************/

CETYPE FILEfind( FILEOBJ foDest, FILEOBJ foCompareTo, BYTE cmd)
{
    WORD	attrib,fHandle = 0;            // current entry counter
    BYTE	state,index;              // state of the current object
    CETYPE	statusB = CE_FILE_NOT_FOUND;           
    BYTE	character,test;

    // reset the cluster
    foDest->dirccls = foDest->dirclus;

    if(	Cache_File_Entry(foDest, &fHandle, TRUE) == NULL)
    {
        statusB = CE_BADCACHEREAD;
    }
    else
    {
        // Loop until you reach the end or find the file 
		while(1)
		{
			if(statusB!=CE_GOOD)
			{
				state = Fill_File_Object(foDest, &fHandle);
				if(state == NO_MORE)
				{
					break;
				}
			}
			else
			{
				break;
			}

            if(state == FOUND)
            {
                /* We got something */
                // get the attributes
                attrib = foDest->attributes;
            
           		attrib &= ATTR_MASK;
        
                // see if we are a volume id or hidden, ignore
                if((attrib != ATTR_VOLUME) && (attrib & ATTR_HIDDEN) != ATTR_HIDDEN)
                {
                    statusB = CE_GOOD;
                    character = (BYTE)'m'; // random value
                    
                    // search for one. if status = TRUE we found one
                    for(index = 0; (statusB == CE_GOOD) && index < DIR_NAMECOMP; index++)
                    {
                        // get the source character 
                        character = foDest->name[index];
                        // get the destination character
                        test = foCompareTo->name[index];
                        if(tolower(character) != tolower(test))
                            statusB = CE_FILE_NOT_FOUND; // Nope its not a match
                            
                     }// for loop
                     
               } // not dir nor vol
                    
            } // not found
            else 
            {
                /*** looking for an empty/re-usable entry ***/
                if ( cmd == 0) 
                    statusB = CE_GOOD;
            } // found or not    
            
            // just increment it no matter what happened
            fHandle++;
              
        }// while 
    }
    
    return(statusB);
} // FILEFind


/******************************************************************************
 * Function:        WORD FATread( DISK *dsk, WORD ccls)
 *
 * PreCondition:    None
 *
 * Input:           dsk			- Disk structure
 *					ccls		- Current cluster
 *                  
 * Output:          0000 	- cluster is empty
 *                  0FF8 	- last cluster in a chain
 *					0xxx	- next cluster in a chain
 *					FFFF 	- FAIL
 *
 * Side Effects:    None
 *
 * Overview:        Reads the content of a cluster link in FAT
 *
 * Note:            None
 *****************************************************************************/

WORD FATread( DISK *dsk, WORD ccls)
{

	WORD p, c ;
	DWORD l;
	
	if( dsk->type != FAT16 )
		return CLUSTER_FAIL;

    // get address of current cluster in fat
    p = ccls;
    // cluster = 0xabcd
    // packed as:     0   |   1    |   2   |  3    |
    // word p       0   1 |  2   3 | 4   5 | 6   7 |..
    //              cd  ab|  cd  ab| cd  ab| cd  ab|


    l = dsk->fat + (p >> 8 );   // 256 clusters per sector

	if ((gBufferOwner != (MYFILE *) 0xAA55) || 
			(lastClusterRead != l))
	{
    // load the fat sector containing the cluster
		gBufferOwner = (MYFILE *)0xAA55; //reset buffer owner
	    if ( !SECTORread( l, dsk->buffer) )
    	    return CLUSTER_FAIL;
		lastClusterRead = l;
	}
    // get the next cluster value
    c = RAMreadW( dsk->buffer, ((p & 0xFF)<<1));

    // Normalize it so 0xFFFF is an error
    if(c >= LAST_CLUSTER_FAT16)
        c = LAST_CLUSTER;

    return c;

} // FATread

/******************************************************************************
 * Function:        CETYPE FILEopen (FILEOBJ fo, WORD *fHandle, char type)
 *
 * PreCondition:    FILEfind returns true for read or append, fo contains file data
 *
 * Input:           fo			- File to be opened
 *					fHandle		- Location of file
 *					type		- WRITE - Create a new file or replace an existing file
 *								  READ - Read data from an existing file
 *								  APPEND - Append data to an existing file
 *                  
 * Output:			CE_GOOD				- FILEopen successful
 *					CE_NOT_INIT			- Card is not yet initialized because of some error
 *					CE_FILE_NOT_FOUND	- Could not find the file on the card
 *					CE_BAD_SECTOR_READ	- A bad read occured of a sector  
 *					
 *
 * Side Effects:    None
 *
 * Overview:        Opens a file to perform operations on
 *
 * Note:            None
 *****************************************************************************/

CETYPE FILEopen (FILEOBJ fo, WORD *fHandle, char type)
{
	DISK   *dsk;		//Disk structure
	BYTE 	r;					//Result of search for file
	DWORD 	l;					//lba of first sector of first cluster
	CETYPE 	error = CE_GOOD;

	dsk = (DISK *)(fo->dsk);
	if (dsk->mount == FALSE)
		error = CE_NOT_INIT;
	else
	{
        // load the sector
    	Cache_File_Entry(fo, fHandle, TRUE);
       
        // Fill up the File Object with the information pointed to by fHandle
        r = Fill_File_Object(fo, fHandle);
		if (r != FOUND)
			error = CE_FILE_NOT_FOUND;
		else
		{
			fo->seek = 0;               // first byte in file
			fo->ccls = fo->cluster;     // first cluster
			fo->sec = 0;                // first sector in the cluster
			fo->pos = 0;                // first byte in sector/cluster
			
    	    if  ( r == NOT_FOUND)
    	    {
    	        error = CE_FILE_NOT_FOUND;
			}
			else
			{   
			    // Determine the lba of the selected sector and load 
			    l = Cluster2Sector(dsk,fo->ccls);

				gBufferOwner = fo;
				if ( !SECTORread( l, dsk->buffer))
					error = CE_BAD_SECTOR_READ;                         
			} // -- found

			fo->Flags.FileWriteEOF = FALSE;
			// Set flag for operation type
			if (type == 'w' || type == 'a')
			{
				fo->Flags.write = 1;	//write or append
			}
			else
			{
				fo->Flags.write = 0;	//read
			} // -- flags
		} // -- r = Found
	} // -- Mounted
	return (error);
} // -- FILEopen
			
/******************************************************************************
 * Function:        CETYPE __fread ( MYFILE *fo, BYTE *pDest, WORD count, WORD *pBytesRead )
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -