📄 sdmmc.c
字号:
/******************************************************************************
*
* Secure Digital and Multimedia Cards Interface
*
******************************************************************************
* FileName: sdmmc.c
* Dependencies: Compiler.h
* spi.h
* sdmmc.h
* sdmmc_lld.h
* string.h
* Processor: PIC24FJ128
* Compiler: C30
* Company: Microchip Technology, Inc.
* zhouyi
* Software License Agreement
*
*
*****************************************************************************/
#include "sdmmc.h"
#include "generic.h"
#include "sdmmc_lld.h"
#include "string.h"
#include "sdhal.h"
/******************************************************************************
* Global Variables
*****************************************************************************/
BYTE gblSDMMCBuf[MEDIA_SECTOR_SIZE];
DISK glbDiskData;
#define Yield Nop()
#define SD_CMD_IDLE 0
#define SD_CMD_SEND_OP_COND 1
#define SD_CMD_SET_BLOCK_LEN 16
#define SD_CMD_READ_BLOCK 17
#define SD_CMD_WRITE_BLOCK 24
#define SD_CARD_SYSTEM // Does this mean we are supporting more than one cards? - NR
typedef enum
{
GO_IDLE_STATE,
SEND_OP_COND,
SEND_CSD,
SEND_CID,
STOP_TRANSMISSION,
SEND_STATUS,
SET_BLOCKLEN,
READ_SINGLE_BLOCK,
READ_MULTI_BLOCK,
WRITE_SINGLE_BLOCK,
WRITE_MULTI_BLOCK,
TAG_SECTOR_START,
TAG_SECTOR_END,
UNTAG_SECTOR,
TAG_ERASE_GRP_START,
TAG_ERASE_GRP_END,
UNTAG_ERASE_GRP,
ERASE,
LOCK_UNLOCK,
SD_APP_OP_COND,
APP_CMD,
READ_OCR,
CRC_ON_OFF
}sdmmc_cmd;
/*********************************************************************
* sdmmc_cmdtable
* - Provides information for all the sdmmc commands that we support
*
* Notes: We turn off the CRC as soon as possible, so the commands with
* 0xFF don't need to be calculated in runtime
*********************************************************************/
const typMMC_CMD sdmmc_cmdtable[] =
{
// cmd crc response
{cmdGO_IDLE_STATE, 0x95, R1, NODATA},
{cmdSEND_OP_COND, 0xF9, R1, NODATA},
{cmdSEND_CSD, 0xAF, R1, MOREDATA},
{cmdSEND_CID, 0x1B, R1, MOREDATA},
{cmdSTOP_TRANSMISSION, 0xC3, R1, NODATA},
{cmdSEND_STATUS, 0xAF, R2, NODATA},
{cmdSET_BLOCKLEN, 0xFF, R1, NODATA},
{cmdREAD_SINGLE_BLOCK, 0xFF, R1, MOREDATA},
{cmdREAD_MULTI_BLOCK, 0xFF, R1, MOREDATA},
{cmdWRITE_SINGLE_BLOCK, 0xFF, R1, MOREDATA},
{cmdWRITE_MULTI_BLOCK, 0xFF, R1, MOREDATA},
{cmdTAG_SECTOR_START, 0xFF, R1, NODATA},
{cmdTAG_SECTOR_END, 0xFF, R1, NODATA},
{cmdUNTAG_SECTOR, 0xFF, R1, NODATA},
{cmdTAG_ERASE_GRP_START, 0xFF, R1, NODATA},
{cmdTAG_ERASE_GRP_END, 0xFF, R1, NODATA},
{cmdUNTAG_ERASE_GRP, 0xFF, R1, NODATA},
{cmdERASE, 0xDF, R1b, NODATA},
{cmdLOCK_UNLOCK, 0x89, R1b, NODATA},
{cmdSD_APP_OP_COND, 0xE5, R1, NODATA},
{cmdAPP_CMD, 0x73, R1, NODATA},
{cmdREAD_OCR, 0x25, R3, NODATA},
{cmdCRC_ON_OFF, 0x25, R1, NODATA}
};
// 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 union _MMCstate
{
struct
{
BYTE isSDMMC : 1; // set if it is a SDMMC
BYTE isWP : 1; // set if it is write protected
};
BYTE _byte;
}MMCSTATE;
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;
typedef union _CARDSTATUS
{
struct
{
BYTE CS_Inserted:1; // Card is inserted and initialized
BYTE CS_Reset:1; // Card has just been reset
BYTE CS_SDMMC:1; // Card is of the SDMMC type
BYTE CS_WP:1; // Card is write Protected
BYTE CS_Failure:1; // There was a failure initializing the card
};
WORD _word;
}CARDSTATUS;
// Master Boot Record offsets
#define FO_MBR 0L // master boot record sector LBA
#ifndef EOF
#define EOF (-1)
#endif
#define FAT_GOOD_SIGN_0 0x55
#define FAT_GOOD_SIGN_1 0xAA
#define BOOTABLE 0x80
#define NON_BOOTABLE 0x00
/******************************************************************************
* Prototypes
*****************************************************************************/
BYTE DISKmount( DISK *dsk, BYTE* b, MMCSTATE *Flag);
BYTE LoadMBR(DISK *dsk);
BYTE LoadBootSector(DISK *dsk);
extern void Delayms(BYTE milliseconds);
void StopCard(DISK *dsk, CARDSTATUS *cs);
BYTE StartupCard(DISK *dsk, CARDSTATUS *CardStatus);
BYTE ReadMedia(void);
BYTE MediaInitialize(void);
MMC_RESPONSE SendMMCCmd(BYTE cmd, DWORD address);
BYTE ReadByte( BYTE* pBuffer, WORD index );
WORD ReadWord( BYTE* pBuffer, WORD index );
DWORD ReadDWord( BYTE* pBuffer, WORD index );
void OpenSPI( unsigned char sync_mode, unsigned char bus_mode, unsigned char smp_phase);
void CloseSPI( void );
unsigned char WriteSPI( unsigned char data_out );
BYTE SD_ReadRegister(WORD len, BYTE *recbuf);
BYTE SD_GetCardInfo();
void SD_SPIDelay(char value)
{
char i;
for(i = 0; i < value; i++)
WriteSPI(0xFF);
//Nop();
return;
}
/******************************************************************************
* Function: BYTE MediaDetect(void)
*
* PreCondition: MediaInit function has been executed.
*
* Input: void
*
* Output: TRUE - Card detected
* FALSE - No card detected
*
* Side Effects: None
*
* Overview: None
*
* Note: None
*****************************************************************************/
BYTE MediaDetect()
{
// give it a debounce here
Delayms(10);
// return(!SD_CD);
return 1;
}//end MediaDetect
/******************************************************************************
* Function BYTE MediaInit (void)
* KETTER
******************************************************************************/
BYTE MediaInit ()
{
BYTE result;
CARDSTATUS cs;
//Write Protect - input
init_spi1();
// StartupCard (&glbDiskData, &cs) == CE_GOOD
result = StartupCard(&glbDiskData, &cs);
return ( result );
}
/******************************************************************************
* Function: BYTE MediaInitialize(MMCSTATE *Flag)
*
* PreCondition: None
*
* Input: None
*
* Output: mmcValid - Everything is fine
* mmcCardInitCommFailure - Communication has never been established with card
* mmcCardNotInitFailure - Card did not go into an initialization phase
* mmcCardInitTimeout - Card initialization has timedout
* mmcCardTypeInvalid - Card type was not able to be defined
* mmcCardBadCmd - Card did not reconized the command
* mmcCardTimeout - Card timedout during a read, write or erase sequence
* mmcCardCRCError - A CRC error has occurred during a read, data should be invalidated
* mmcCardDataRejected - Card and data sent's CRC did not match
*
* Side Effects: Variable 'gblMMC_media' is updated
*
* Overview: MediaInitialize initializes the media card and supporting variables.
*
* Note: goto's were used for errro conditions
*****************************************************************************/
BYTE MediaInitialize(void)
{
MMC_RESPONSE response;
BYTE status = TRUE;
int timeout = 0xfff,i=0;
CS_LOW;
SD_SPIDelay(100); //delay more than 74 clock
CS_HIGH;
WriteSPI(0xff);
WriteSPI(0xff);
i = 0xfff;
do
{
response = SendMMCCmd(GO_IDLE_STATE,0x0);//GO_IDLE_STATE
i--;
}while((response.r1._byte != 0x01)&&( i > 0));
if((response.r1._byte != 0x01)||(i <= 0)) //0x01=No Err&Busy Initializing
{
status = FALSE; // we have not got anything back from the card
goto InitError;
}
do
{
response = SendMMCCmd(APP_CMD ,0x0);
response = SendMMCCmd(SD_APP_OP_COND ,0x0);//SEND_OP_COND SD_APP_OP_COND
timeout--;
}while((response.r1._byte != 0x00)&&(timeout > 0));
if(response.r1._byte != 0x00)
{
timeout = 0xfff;
do
{
response = SendMMCCmd(SEND_OP_COND ,0x0);
}while((response.r1._byte != 0x00)&&(timeout > 0));
if(timeout <= 0x00)
{
status = FALSE;
goto InitError;
}
}
//SD_GetCardInfo();
for(timeout = 0xFF; timeout > 0 && SECTORread(0,gblSDMMCBuf) != TRUE; timeout--)
{;}
//SECTORwrite(10,(void *)"zhouyi");
//SECTORread(10,gblSDMMCBuf);
if(timeout == 0)
{
status = FALSE;
goto InitError;
}
return(status);
InitError:
CS_HIGH; // deselect the devices
return(status);
}//end MediaInitialize
//----------------------------------------------------------------------
// ShutdownMedia
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -