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

📄 cf.c

📁 使用PIC24 16位单片机 读写SD卡 支持FAT32
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
**
** Compact Flash access routines
**
** 
*/
#include "CF.h"         // compact flash interface
#include "generic.h"
#include "fileio.h"


BYTE gblCFBuf [MEDIA_SECTOR_SIZE];

DISK glbDiskData;


// BPB FAT12
typedef struct __BPB_FAT12 {
        SWORD BS_jmpBoot;        // Jump Command
        BYTE  BS_OEMName[8];     // OEM name
        WORD BPB_BytsPerSec;     // BYTEs per sector
        BYTE  BPB_SecPerClus;     // sectors per allocation unit
        WORD BPB_RsvdSecCnt;     // number of reserved sectors after start
        BYTE  BPB_NumFATs;        // number of FATs
        WORD BPB_RootEntCnt;     // number of root directory entries
        WORD BPB_TotSec16;       // total number of sectors
        BYTE  BPB_Media;          // media descriptor
        WORD BPB_FATSz16;         // number of sectors per FAT
        WORD BPB_SecPerTrk;      // sectors per track
        WORD BPB_NumHeads;       // number of heads
        DWORD BPB_HiddSec;        // number of hidden sectors
        BYTE  BS_Reserved0;       // Nothing
        BYTE  BS_DrvNum;          // Int 13 drive number
        BYTE  BS_Reserved1;       // Nothing
        BYTE  BS_BootSig;         // 0x29
        BYTE  BS_VolID[4];        // Volume Id
        BYTE  BS_VolLab[11];       // Volume Label
        BYTE  BS_FilSysType[8];   // File system type, not used for determination   
}_BPB_FAT12;

typedef _BPB_FAT12 * BPB_FAT12;

// BPB FAT32
typedef struct __BPB_FAT32 {
        SWORD BPB_jmpBoot;        // Jump Command
        BYTE  BPB_OEMName[8];     // OEM name
        WORD BPB_BytsPerSec;     // BYTEs per sector
        BYTE  BPB_SecPerClus;     // sectors per allocation unit
        WORD BPB_RsvdSecCnt;     // number of reserved sectors after start
        BYTE  BPB_NumFATs;        // number of FATs
        WORD BPB_RootEntCnt;     // number of root directory entries
        WORD BPB_TotSec16;       // total number of sectors
        BYTE  BPB_Media;          // media descriptor
        WORD BPB_FATSz16;         // number of sectors per FAT
        WORD BPB_SecPerTrk;      // sectors per track
        WORD BPB_NumHeads;       // number of heads
        DWORD BPB_HiddSec;        // number of hidden sectors
        DWORD BPB_TotSec32;       // New 32bit total sec count
        DWORD BPB_FATSz32;        // Sectors occupied by one FAT
        WORD BPB_ExtFlags;       // Presently active FAT as defined by bits 0-3 if bit 7 is 1
        WORD BPB_FSVers;         // FAT32 filesystem version, should be 0:0
        DWORD BPB_RootClus;       // start cluster of the root directory (should be 2)
        WORD BPB_FSInfo;         // filesystem info structure sector
        WORD BPB_BkBootSec;      // backup boot sector normally 6
        BYTE  BPB_Reserved[12];   // Reserved memory
        BYTE  BS_DrvNum;          // Int 13 drive number
        BYTE  BS_Reserved1;       // Nothing
        BYTE  BS_BootSig;         // 0x29
        BYTE  BS_VolID[4];        // Volume Id
        BYTE  BS_VolLab[11];       // Volume Label
        BYTE  BS_FilSysType[8];   // File system type, not used for determination  
}_BPB_FAT32;

typedef _BPB_FAT32 * BPB_FAT32;

// BPB FAT16
typedef struct __BPB_FAT16 {
        SWORD BS_jmpBoot;        // Jump Command
        BYTE  BS_OEMName[8];     // OEM name
        WORD BPB_BytsPerSec;     // BYTEs per sector
        BYTE  BPB_SecPerClus;     // sectors per allocation unit
        WORD BPB_RsvdSecCnt;     // number of reserved sectors after start
        BYTE  BPB_NumFATs;        // number of FATs
        WORD BPB_RootEntCnt;     // number of root directory entries
        WORD BPB_TotSec16;       // total number of sectors
        BYTE  BPB_Media;          // media descriptor
        WORD BPB_FATSz16;         // number of sectors per FAT
        WORD BPB_SecPerTrk;      // sectors per track
        WORD BPB_NumHeads;       // number of heads
        DWORD BPB_HiddSec;        // number of hidden sectors
        DWORD BPB_TotSec32;       // New 32bit total sec count
        BYTE  BS_DrvNum;          // Int 13 drive number
        BYTE  BS_Reserved1;       // Nothing
        BYTE  BS_BootSig;         // 0x29
        BYTE  BS_VolID[4];        // Volume Id
        BYTE  BS_VolLab[11];       // Volume Label
        BYTE  BS_FilSysType[8];   // File system type, not used for determination     
}_BPB_FAT16;

#define BSI_BOOTJMP			0
#define BSI_OEM_NAME		3
#define BSI_BytesPerSec		11
#define BSI_SecPerClus		13
#define BSI_RsvdSecCount 	14
#define BSI_NumFATs			16
#define BSI_RootEntCnt		17
#define BSI_TotSec16 		19
#define BSI_Media 			21
#define BSI_FATSz16 		22
#define BSI_SecPerTrk 		24
#define BSI_NumHeads 		26
#define BSI_HiddSec 		28
#define BSI_TotSec32 		32
#define BSI_DrvNum 			36
#define BSI_Reserved1 		37
#define BSI_BootSig 		38
#define BSI_VolID 			39
#define BSI_VolLab 			43
#define BSI_FilSysType 		54

typedef _BPB_FAT16 * BPB_FAT16;

// PTE_FAT - Partition Table Entry

typedef struct _PTE_FAT
{
    BYTE      PTE_BootDes;            // Boot Descriptor, 0x80
    SWORD     PTE_FrstPartSect;       // First Partion Sector
    BYTE      PTE_FSDesc;             // File System Descriptor 
    SWORD     PTE_LstPartSect;        // Last Partion Sector
    DWORD     PTE_FrstSect;           // First Sector Position
    DWORD     PTE_NumSect;            // Number of Sectors in partion
}PTE_FAT;

// PT_FAT - Partition Table 
typedef struct __PT_FAT
{
    BYTE      ConsChkRtn[446];
    PTE_FAT Partition0;
    PTE_FAT Partition1;
    PTE_FAT Partition2;
    PTE_FAT Partition3;
    BYTE      Signature0;     // 0x55
    BYTE      Signature1;     // 0xAA
}_PT_FAT;

typedef _PT_FAT *  PT_FAT;

typedef struct __BS
{
    union
    {
        _BPB_FAT32  FAT_32;	
        _BPB_FAT16  FAT_16;	
        _BPB_FAT12  FAT_12;	
    }FAT;    
    BYTE  	Reserved[MEDIA_SECTOR_SIZE-sizeof(_BPB_FAT32)-2];
    BYTE      Signature0;     // 0x55
    BYTE      Signature1;     // 0xAA
}_BS;

typedef _BS * BS;

// Master Boot Record offsets
#define FO_MBR          0L  // master boot record sector LBA

#ifndef EOF
#define EOF         (-1)
#endif

#define RAMread( a, f)  *(a+f)

#define FAT_GOOD_SIGN_0     0x55
#define FAT_GOOD_SIGN_1     0xAA
#define BOOTABLE            0x80
#define NON_BOOTABLE        0x00

CETYPE StartupCard(DISK *dsk);
CETYPE DISKmount( DISK *dsk, BYTE* b);
CETYPE LoadMBR(DISK *dsk);
BYTE LoadBootSector(DISK *dsk);
void StopCard (DISK * dsk);
BYTE ReadByte( BYTE* pBuffer, WORD index );
WORD ReadWord( BYTE* pBuffer, WORD index );
DWORD ReadDWord( BYTE* pBuffer, WORD index );
CETYPE StartupCard(DISK *dsk)
{
	CETYPE	        error;
	BYTE *	buffer = gblCFBuf;

	if((error = DISKmount( dsk, buffer)) == CE_GOOD)
	{
	}
	else
	{
		// there was an issue so turn off the card
		StopCard(dsk);
	}

	return(error);
}

CETYPE DISKmount( DISK *dsk, BYTE* b)
{
	BYTE          i;
	CETYPE        error = CE_GOOD;

	dsk->mount = FALSE; // default invalid
	dsk->buffer = b;    // assign buffer


	// Load the Master Boot Record (partition)
	if((error = LoadMBR(dsk)) == CE_GOOD)
	{
		// Now the boot sector
		if((error = LoadBootSector(dsk)) == CE_GOOD)
			dsk->mount = TRUE; // Mark that the DISK mounted successfully
	}

	return(error);
} // -- mount




CETYPE LoadMBR(DISK *dsk)
{
    PT_FAT  Partition;
    CETYPE error = CE_GOOD;
    BYTE type;

    // Get the partition table from the MBR
    if ( SECTORread( FO_MBR, dsk->buffer) != TRUE) 
        error = CE_BAD_SECTOR_READ;
    else
    {
		// assign it the partition table strucutre
    	Partition = (PT_FAT)dsk->buffer;
    
        // Ensure its good
        if((Partition->Signature0 != FAT_GOOD_SIGN_0) || (Partition->Signature1 != FAT_GOOD_SIGN_1))
        {
            error = CE_BAD_PARTITION;
        }
        else
        {    
            /*    Valid Master Boot Record Loaded   */

            // Get the 32 bit offset to the first partition 
            dsk->firsts = Partition->Partition0.PTE_FrstSect; 

            // check if the partition type is acceptable
           	type = Partition->Partition0.PTE_FSDesc;

            switch (type)
            {
                case 0x01:
                    dsk->type = FAT12;
                   	error = CE_CARDFAT12;
                    
                    break;
               
				case 0x04:
                case 0x06:
                case 0x0E:
                    dsk->type = FAT16;
                    break;
                
                case 0x0B:
                case 0x0C:
                    dsk->type = FAT32; // and error out				
                    error = CE_CARDFAT32;
                    break;
                    
                default:
                    error = CE_BAD_PARTITION;
            } // switch
        }
    }

    return(error);
}// -- LoadMBR



BYTE LoadBootSector(DISK *dsk)
{
    WORD     RootDirSectors;
    DWORD     TotSec,DataSec;
    BYTE      error = CE_GOOD;
    BS		BootSec;        // boot sector, assume its FAT16 til we know better
	BYTE *	test1;
	WORD *	test2;
	SWORD *	test3;
	DWORD *	test4;

	WORD   BytesPerSec;
                    
    // Get the Boot sector
    if ( SECTORread( dsk->firsts, dsk->buffer) != TRUE) 

        error = CE_BAD_SECTOR_READ;  
    else
    {
        // Assign the type
        BootSec = (BS)dsk->buffer;

        //Verify the Boot Sector is valid
        if((BootSec->Signature0 != FAT_GOOD_SIGN_0) || (BootSec->Signature1 != FAT_GOOD_SIGN_1))
        {
            error = CE_NOT_FORMATTED;
        }
        else
        {     
            // determine the number of sectors in one FAT (FATSz)
			dsk->fatsize = ReadWord( dsk->buffer, BSI_FATSz16 ); 

			// Figure out the total number of sectors
	        TotSec = ReadWord( dsk->buffer, BSI_TotSec16 );
			if( TotSec == 0 )
				TotSec = ReadDWord( dsk->buffer, BSI_TotSec32 );
            	                       
	        // 6.  get the full partition/drive layout
	        // 6.1 determine the size of a cluster
	        dsk->SecPerClus = ReadByte( dsk->buffer, BSI_SecPerClus );
	        	        
	        // 6.2 determine fat, root and data lbas
	        // FAT = first sector in partition (boot record) + reserved records
	        dsk->fat        = dsk->firsts + ReadWord( dsk->buffer, BSI_RsvdSecCount );
	        
	        // 6.3 fatcopy is the number of FAT tables 
	        dsk->fatcopy    = ReadByte( dsk->buffer, BSI_NumFATs );

	        // 6.4 MAX ROOT is the maximum number of entries in the root directory
	        dsk->maxroot    = ReadWord( dsk->buffer, BSI_RootEntCnt );   
	        
            // "root" Is the sector location of the root directory
            dsk->root = dsk->fat + (dsk->fatcopy * dsk->fatsize);

			BytesPerSec = ReadWord( dsk->buffer, BSI_BytesPerSec );

			if( BytesPerSec == 0 || (BytesPerSec & 1) == 1 ) //cannot be 0 or odd
				return( CE_NOT_FORMATTED );
	                        
	        RootDirSectors = ((dsk->maxroot * 32) + (BytesPerSec - 1)) / BytesPerSec;               

			// figure out how many data sectors there is 
            DataSec = TotSec - (dsk->root + RootDirSectors);
	        
	        dsk->maxcls = DataSec / dsk->SecPerClus;
	        
	        // Straight out of MS FAT Hardware White Paper
	        if(dsk->maxcls < 4085)
	        {
	            /* Volume is FAT12 */
	            dsk->type = FAT12;
                error = CE_CARDFAT12;
    	    }
    	    else 
			{
				if(dsk->maxcls < 65525)
	    	    {
	    	        /* Volume is FAT16 */

⌨️ 快捷键说明

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