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

📄 sd.c

📁 FS7805 使用SD卡的demo
💻 C
📖 第 1 页 / 共 2 页
字号:

#include "fs7805.h"
#include "fs7805regs.h"
#include "sd.h" 
#include "include.h"
static INT32U xdata SdAvailableBlocks = 0;
static TCARD_TYPE xdata CardType = CARD_SD;
BYTE idata SdCmdBuf[5];
BYTE xdata SdRespBuf[17]; 
BYTE xdata SdRespBufForProgCsd[17];
static INT32U idata RCA = 0;
static BOOL MmcProtol;

INT32U SectorStart  = 0;
INT16U SectorCount  = 0;

BYTE CmdTimer;

void SdInit()
{
	SYSIO_CFG=SYSIO_CFG|bmSD_EN; //enable SDMI interface
	SDMI_CTL&=~bmSD_AUTO_CLK_EN; //
	SDMI_CTL   |= bmSD_CLK_40;//
}

void SdLowClk()
{
	SDMI_CTL=(SDMI_CTL&~bmSD_CLK_SEL)|bmSD_CLK_EN;
}

void SdHiClk()
{
	SDMI_CTL=(SDMI_CTL|bmSD_CLK_SEL)|bmSD_CLK_EN;
}

void SdStopClk()
{
	SDMI_CTL=SDMI_CTL & ~bmSD_CLK_EN & ~bmSD_AUTO_CLK_EN;
}

void SdWaitCard()
{
	while(SDMI_ST&bmSD_BUSY);
}

BYTE SdGetRespType(BYTE CmdIndex)
{
    if(CmdIndex == SEND_RELATIVE_ADDR)
    {
        //if(CardType == CARD_SD)
            return TYPE_RESP_R6;
        //else
        //    return TYPE_RESP_R1;
    }
    switch(CmdIndex)
    {
        case GO_IDLE_STATE        : return TYPE_RESP_NO; break;
        case SEND_OP_COND         : return TYPE_RESP_R3; break;
        case ALL_SEND_CID         : return TYPE_RESP_R2; break;
        case SET_DSR              : return TYPE_RESP_NO; break;
        case SWITCH               : return TYPE_RESP_R1; break;
        case SELECT_CARD          : return TYPE_RESP_R1; break;
        case SEND_EXT_CSD         : return TYPE_RESP_R1; break;
        case SEND_CSD             : return TYPE_RESP_R2; break;
        case SEND_CID             : return TYPE_RESP_R2; break;
        case READ_DAT_UNTIL_STOP  : return TYPE_RESP_R1; break;
        case STOP_TRANS           : return TYPE_RESP_R1; break;
        case SEND_STATUS          : return TYPE_RESP_R1; break;
        case GO_INACTIVE_STATE    : return TYPE_RESP_NO; break;
        case SET_BLOCK_LEN        : return TYPE_RESP_R1; break;
        case READ_BLOCK           : return TYPE_RESP_R1; break;
        case READ_MUL_BLOCK       : return TYPE_RESP_R1; break;
        case WRITE_DAT_UNTIL_STOP : return TYPE_RESP_R1; break;
        case SET_BLOCK_COUNT      : return TYPE_RESP_R1; break;
        case WRITE_BLOCK          : return TYPE_RESP_R1; break;
        case WRITE_MUL_BLOCK      : return TYPE_RESP_R1; break;
        case PROGRAM_CID          : return TYPE_RESP_R1; break;
        case PROGRAM_CSD          : return TYPE_RESP_R1; break;
        case SET_WRITE_PROT       : return TYPE_RESP_R1; break;
        case CLR_WRITE_PROT       : return TYPE_RESP_R1; break;
        case SEND_WRITE_PROT      : return TYPE_RESP_R1; break;
        case ERASE_WR_BLK_START   : return TYPE_RESP_R1; break;
        case ERASE_WR_BLK_END     : return TYPE_RESP_R1; break;
        case ERASE_GROUP_START    : return TYPE_RESP_R1; break;
        case ERASE_GROUP_END      : return TYPE_RESP_R1; break;
        case ERASE                : return TYPE_RESP_R1; break;
        case FAST_IO              : return TYPE_RESP_R4; break;
        case GO_IRQ_STATE         : return TYPE_RESP_R5; break;
        case LOCK_UNLOCK          : return TYPE_RESP_R1; break;
        case APP_CMD              : return TYPE_RESP_R1; break;
        case GEN_CMD              : return TYPE_RESP_R1; break;
        // APP_CMDs
        case SEND_NUM_WR_BLOCKS   : return TYPE_RESP_R1; break;
        case SD_SEND_OP_COND      : return TYPE_RESP_R3; break;
        case SEND_SCR             : return TYPE_RESP_R1; break;
        default                   : return TYPE_RESP_NO; break;
    }
    // Following commands are with identical index and response type:
    //   1. SET_BUS_WIDTH        (ACMD6)    Response R1
    //      SWITCH               (CMD6)     Response R1
    //   2. SEND_SD_STATUS       (ACMD13)   Response R1
    //      SEND_STATUS          (CMD13)    Response R1
    //   3. SET_WR_BLK_ERASE_CNT (ACMD23)   Response R1
    //      SET_BLOCK_COUNT      (CMD23)    Response R1
    //   4. SET_CLR_CARD_DETECT  (ACMD42)   Response R1
    //      LOCK_UNLOCK          (CMD42)    Response R1
}

STATUS SdSendCmd(BYTE CmdIndex, BYTE *CmdBuf)
{
    BYTE RespType , RespLen , CmdType;
    BYTE i;
    BYTE RetryCount = 0;

	RespType = SdGetRespType(CmdIndex);

	if(	(CmdIndex == GEN_CMD)||
		(CmdIndex == SEND_NUM_WR_BLOCKS)||
		(CmdIndex == SEND_SCR)||
		(CmdIndex == SEND_EXT_CSD)||
		(CmdIndex == READ_BLOCK)||
		(CmdIndex == READ_MUL_BLOCK)||
		(CmdIndex == READ_DAT_UNTIL_STOP)/*||
		(CmdIndex == SEND_WRITE_PROT)*/)	  //2006.05.21
    {
        RespLen = 6;
        CmdType = SD_CMD_RX_DATA;
    }
    else if((CmdIndex == PROGRAM_CSD)||
    		(CmdIndex == LOCK_UNLOCK)||
			(CmdIndex == WRITE_BLOCK)||
            (CmdIndex == WRITE_MUL_BLOCK))
    {
        RespLen = 6;
        CmdType = SD_CMD_TX_DATA;
    }
    else if(RespType == TYPE_RESP_NO)
    {
        RespLen = 0;
        CmdType = SD_CMD_ONLY;
    }
    else if(RespType == TYPE_RESP_R2)
    {
        RespLen = 17;
        CmdType = SD_CMD_LONG_RSP;
    }
	
    else    
    {
        RespLen = 6;
        CmdType = SD_CMD_SHORT_RSP;
    }

	if (CmdIndex == 0x5)
	{
        RespLen = 6;
        CmdType = SD_CMD_SHORT_RSP;

	}

	for( ; RetryCount < 3; RetryCount++)
    {
 		SDMCMDRESBUF00=0x40|CmdIndex; //The First byte
		for(i = 1; i <= 4; i++)	//The next 4 bytes
     	   	((BYTE xdata *)(&SDMCMDRESBUF00))[i]=CmdBuf[i];

		SDMI_CMD=CmdType;
		
		CmdTimer = 5; // 50ms
        //while((SDMI_INT&bmSD_COMPLETE_INT)==0);
		//SDMI_INT&=~bmSD_COMPLETE_INT;
		while(CmdTimer > 0)
        {	
			if((SDMI_INT&bmSD_COMPLETE_INT)!=0) //wait for command is completed.
			{
				SDMI_INT&=~bmSD_COMPLETE_INT;
				break;
			}
		}//*/
		if(CmdTimer == 0) // Timeout
        {
            SdCtrlReset(); // ???
			            
            //MMCerror2++;
            continue;
        }

        if(RespType == TYPE_RESP_NO)
            return STATUS_SUCCESS;

        if(RespType == TYPE_RESP_R3)
        {
            // The response type of SD_SEND_OP_COND (ACMD41) and 
            // SEND_OP_COND (CMD1) are both R3, which is not protected
            // by CRC7. But hardware could still report CRC7 error for
            // these command's response. So, to prevent from affecting 
            // next command, we clear CRC7-ERR INT bit here.
            SDMI_ST&=~bmSD_CRC7_ERR;
            for(i = 0; i < RespLen; i++)
                SdRespBuf[i] = ((BYTE xdata *)(&SDMCMDRESBUF00))[i];
            return STATUS_SUCCESS;
        }

        if(SDMI_ST&bmSD_CRC7_ERR) // CRC7 Error
        {
            SDMI_ST&=~bmSD_CRC7_ERR; // Clear INT
            continue;
        }

        for(i = 0; i < RespLen; i++)
            SdRespBuf[i] = ((BYTE xdata *)(&SDMCMDRESBUF00))[i];

        if(RespType == TYPE_RESP_R1)
        {
            // Check following error bits in Card Status:
            //   31 OUT_OF_RANGE         SdRespBuf[1].7
            //   30 ADDRESS_ERROR        SdRespBuf[1].6
            //   29 BLOCK_LEN_ERROR      SdRespBuf[1].5
            //   28 ERASE_SEQ_ERROR      SdRespBuf[1].4
            //   27 ERASE_PARAM          SdRespBuf[1].3
            //   26 WP_VIOLATION         SdRespBuf[1].2
            //   24 LOCK_UNLOCK_FAILED   SdRespBuf[1].0
            //   23 COM_CRC_ERR          SdRespBuf[2].7
            //   22 ILLEGAL_COMMAND      SdRespBuf[2].6
            //   21 CARD_ECC_FAILED      SdRespBuf[2].5
            //   20 CC_ERROR             SdRespBuf[2].4
            //   19 ERROR                SdRespBuf[2].3
            if( ( (SdRespBuf[1] & 0xFD) == 0 ) && // 8'b1111_1101
                ( (SdRespBuf[2] & 0xF8) == 0 )  ) // 8'b1111_1000
                return STATUS_SUCCESS;            // No error
            else
            if( ( SdRespBuf[1] == 0x80 ) && 	//ignor OUT_OF_RANGE error
                ( SdRespBuf[2] == 0 )  && 		// when multi read last 5 blocks
				(( SectorStart >= SdAvailableBlocks-5)||
				( SectorStart <= SdAvailableBlocks))) //see MMC 4.0 SPEC--4.6.3(page 49)
                return STATUS_SUCCESS;   //         
			 else 						 //
                continue;
        }
        else
            return STATUS_SUCCESS;
    }
    return STATUS_FLASH_ERROR;
}

STATUS SdSendAppCmd(BYTE AppCmdIndex, BYTE *CmdBuf)
{
    STATUS Status;
    int RetryCount;
    BYTE CmdBuf55[5]; // for APP_CMD (CMD55)
 
    for(RetryCount = 0; RetryCount < 3; RetryCount++)
    {
        *((INT32U *)(&CmdBuf55[1])) = RCA;
        Status = SdSendCmd(APP_CMD,CmdBuf55);
        
        if(Status != STATUS_SUCCESS)
        {
                continue;
        }
        
        Status = SdSendCmd(AppCmdIndex,CmdBuf);
        
        if(Status != STATUS_SUCCESS)
            continue;
        else
            return STATUS_SUCCESS;
    }
    return STATUS_FLASH_ERROR;
}

STATUS SdReset()
{
	STATUS Status;
    int i;

	SdLowClk();
	Delay1ms(150);
	for(i = 1; i <= 4; i++)
        SdCmdBuf[i]=0;
    Status = SdSendCmd(GO_IDLE_STATE,SdCmdBuf);
    return Status;
}

STATUS SdCardDetect()
{
	STATUS Status;
    INT16U RetryCount;

	*(INT32U *)(&SdCmdBuf[1])=OPERATION_VOL_RANGE;
	Status = SdSendAppCmd(SD_SEND_OP_COND, SdCmdBuf);

	if(Status == STATUS_SUCCESS)
    {
        CardType = CARD_SD;	
 
        // Check if card power-up operation finished
        if(SDMCMDRESBUF01 & CARD_PWRUP_FINISH)
            return STATUS_SUCCESS;

        // Wait until card power-up operation finished
        for(RetryCount = 0; RetryCount < 500; RetryCount++)
        {
            *((INT32U idata *)(&SdCmdBuf[1])) = OPERATION_VOL_RANGE;
            
            Status = SdSendAppCmd(SD_SEND_OP_COND, SdCmdBuf);
            
            if(Status != STATUS_SUCCESS)
                continue;
                
            if(SDMCMDRESBUF01 & CARD_PWRUP_FINISH)
                return STATUS_SUCCESS;           
        }
        return STATUS_FLASH_ERROR;
    }

	else
    {
        CardType = CARD_MMC;   	
        
        // Wait until card power-up operation finished
        for(RetryCount = 0; RetryCount < 500; RetryCount++)
        {            
			*((INT32U *)(&SdCmdBuf[1])) = OPERATION_VOL_RANGE;
    
            Status = SdSendCmd(SEND_OP_COND, SdCmdBuf);

            if(Status != STATUS_SUCCESS)
                continue;
                
            if(SdRespBuf[1] & CARD_PWRUP_FINISH)
                return STATUS_SUCCESS;           
        }
        return STATUS_FLASH_ERROR;
    }
    return Status;
}

STATUS SdGoIdentifyState()
{
    STATUS Status;
    int i;

    for(i = 1; i <= 4; i++)
    	SdCmdBuf[i] = 0;
    Status = SdSendCmd(ALL_SEND_CID,SdCmdBuf);
    return Status;
}

STATUS SdGoStandbyState()
{
    STATUS Status;
    int i;
  	
    if(CardType == CARD_SD)
    {
        for(i = 1; i <= 4; i++)
            SdCmdBuf[i] = 0;
    }
    else
    {
        RCA = 0x00010000;	
        *((INT32U idata *)(&SdCmdBuf[1])) = RCA;
    }

    Status = SdSendCmd(SEND_RELATIVE_ADDR,SdCmdBuf);

    if(CardType == CARD_SD)
        RCA = *((INT32U *)(&SdRespBuf[1])) & 0xffff0000;

    return STATUS_SUCCESS;
}

//--------------------------------------------------------------------
STATUS SdReadCSD()			
{
    STATUS Status;	
    BYTE READ_BL_LEN;
    BYTE C_SIZE_MUTI;
    INT32U C_SIZE;
	int i;
     
    *((INT32U *)(&SdCmdBuf[1])) = RCA;
    
    Status = SdSendCmd(SEND_CSD,SdCmdBuf);
	for(i=0;i<17;i++)
		SdRespBufForProgCsd[i]=SdRespBuf[i];
    if(Status != STATUS_SUCCESS)
        return Status;
          
	if(SdRespBuf[1] & 0x3c)//check MMC3.1 or MMC4.0
		MmcProtol = TRUE;
	else
		MmcProtol = FALSE;
	
    READ_BL_LEN = SdRespBuf[6] & 0xf;
    C_SIZE = SdRespBuf[7] & 0x3;
    C_SIZE <<= 8;
    C_SIZE |= SdRespBuf[8];
    C_SIZE <<= 2;
    C_SIZE |= (SdRespBuf[9] >> 6);

⌨️ 快捷键说明

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