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

📄 sd.c

📁 增强型51单片机fs7821sd卡、mmc卡读写程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
**********************************************************************************************
* Project:	TK7821
* File:		sd.c
* Contents: 
*          The SD access module 
*
* $Date: 02/25/05    Jason    v0.1
*        05/12/05    Mingo    v0.2   www.fameg.com
*
* Copyright (c) 2005 Fameg, Inc. All rights reserved
***********************************************************************************************
*/

#include <reg51.h>
#include <stdio.h>
#include <string.h>
#include "Device.h"
#include "UsbDisk.h"
#include "Storage.h"

#define MAX_CMD_LEN          6
#define MAX_RESP_LEN         17 // Max response length = 136 bits
#define RSP_LEN              6     
#define LONG_RSP_LEN         17
#define CARD_CMD_START       0x40
#define CARD_PWRUP_FINISH    0x80
#define OPERATION_VOL_RANGE  0x00FF0000
#define GOOD_CRC16_STS       0x02

/* SD_COMMAND */
#define SD_CMD_ONLY         1
#define SD_CMD_SHORT_RSP    2 
#define SD_CMD_LONG_RSP     3
#define SD_CMD_TX_DATA      4
#define SD_CMD_TX_DATA_ONLY 5 
#define SD_CMD_RX_DATA      6
#define SD_CMD_RX_DATA_ONLY 7 

#define IDLE_STATE          0  
#define READY_STATE         1
#define IDENTIFY_STATE      2
#define STANDBY_STATE       3
#define TRANSFER_STATE      4  
#define DATA_STATE          5
#define RECEIVE_STATE       6
#define PRGROGAM_STATE      7
#define DISCONNECT_STATE    8  

#define BUS_WIDTH_1BIT      0x00
#define BUS_WIDTH_4BIT      0x02

//      Command Name      Index   MMC-3.1 MMC-4.0 SD-1.01  Resp
#define GO_IDLE_STATE        0    //  V      V      V      -
#define SEND_OP_COND         1    //  V      V             R3 (OCR)
#define ALL_SEND_CID         2    //  V      V      V      R2
#define SEND_RELATIVE_ADDR   3    //  R1     R1     R6     See SdGetRespType()
#define SET_DSR              4    //  V      V      V      - 
#define SWITCH               6    //         V             R1
#define SELECT_CARD          7    //  V      V      V      R1
#define SEND_EXT_CSD         8    //         V             R1
#define SEND_CSD             9    //  V      V      V      R2
#define SEND_CID             10   //  V      V      V      R2
#define READ_DAT_UNTIL_STOP  11   //  V      V             R1
#define STOP_TRANS           12   //  V      V      V      R1
#define SEND_STATUS          13   //  V      V      V      R1
#define GO_INACTIVE_STATE    15   //  V      V      V      - 
#define SET_BLOCKLEN         16   //  V      V      V      R1
#define READ_BLOCK           17   //  V      V      V      R1
#define READ_MUL_BLOCK       18   //  V      V      V      R1
#define WRITE_DAT_UNTIL_STOP 20   //  V      V             R1
#define SET_BLOCK_COUNT      23   //  V      V             R1
#define WRITE_BLOCK          24   //  V      V      V      R1
#define WRITE_MUL_BLOCK      25   //  V      V      V      R1
#define PROGRAM_CID          26   //  V      V             R1
#define PROGRAM_CSD          27   //  V      V      V      R1
#define SET_WRITE_PROT       28   //  V      V      V      R1
#define CLR_WRITE_PROT       29   //  V      V      V      R1
#define SEND_WRITE_PROT      30   //  V      V      V      R1
#define ERASE_WR_BLK_START   32   //                V      R1
#define ERASE_WR_BLK_END     33   //                V      R1
#define ERASE_GROUP_START    35   //  V      V             R1
#define ERASE_GROUP_END      36   //  V      V             R1
#define ERASE                38   //  V      V      V      R1
#define FAST_IO              39   //  V      V             R4
#define GO_IRQ_STATE         40   //  V      V             R5
#define LOCK_UNLOCK          42   //  V      V      V      R1
#define APP_CMD              55   //  V      V      V      R1
#define GEN_CMD              56   //  V      V      V      R1

//      ACMD Name         Index   MMC-3.1 MMC-4.0 SD-1.01  Resp
#define SET_BUS_WIDTH        6    //                V      R1
#define SEND_SD_STATUS       13   //                V      R1
#define SEND_NUM_WR_BLOCKS   22   //                V      R1
#define SET_WR_BLK_ERASE_CNT 23   //                V      R1
#define SD_SEND_OP_COND      41   //                V      R3 (OCR)
#define SET_CLR_CARD_DETECT  42   //                V      R1
#define SEND_SCR             51   //                V      R1

// ??? According to Spec of MMC3.1, MultiMediaCard returns response of
//     type R1 to APP_CMD (CMD55). But, according to Spec of SD1.01 
//     page 23, MultiMediaCard will not respond to APP_CMD - CMD55. 
//     Is this a confliction ? 


#define SdHiClk() CSRWrite(SD_BASE + SD_CLK_CTRL, \
                     (CSRRead(SD_BASE + SD_CLK_CTRL) | SD_CLK_SEL) | SD_CLK_EN);
#define SdLoClk()  CSRWrite(SD_BASE + SD_CLK_CTRL, \
                     (CSRRead(SD_BASE + SD_CLK_CTRL) & ~SD_CLK_SEL) | SD_CLK_EN); 
#define SdStopClk() CSRWrite(SD_BASE + SD_CLK_CTRL, \
                     CSRRead(SD_BASE + SD_CLK_CTRL) & ~SD_CLK_EN);                      
#define IsCardBusy() (CSRRead(SD_BASE + SD_STATUS) & SD_BUSY)     
#define SdWriteProtect() (!(CSRRead(SD_BASE + SD_STATUS) & SD_WPD))
#define SdCardExist() (CSRRead(SD_BASE + SD_STATUS) & SD_CARD_STS)
#define SdCtrlReset() CSRWrite(SD_BASE + SD_CLK_CTRL, SD_RESET | SD_CLK_EN)
#define SdWaitCard()\
{\
  CmdTimer = SD_CMD_TIMEOUT;\
  while (IsCardBusy() && CmdTimer);\
}

#ifdef PMOS
  #define SdPowerOn() {SD_POWER_CTRL = 0; Delay(50);}
  #define SdPowerOff() SD_POWER_CTRL = 1
#else
  #define SdPowerOn()
  #define SdPowerOff()
#endif

typedef enum {CARD_SD, CARD_MMC} TCARD_TYPE;

/*************************************************
   Global Variables
*************************************************/
xdata BYTE SdGetFlashInfoTimer = 0;

/*************************************************
   Local Variables
*************************************************/
static xdata UINT32 SdAvailableBlocks = 0;
static xdata TCARD_TYPE CardType = CARD_SD;
static idata BYTE SdCmdBuf[MAX_CMD_LEN];
static xdata BYTE SdRespBuf[MAX_RESP_LEN]; 
static idata UINT32 RCA = 0;

#define TYPE_RESP_NO      0
#define TYPE_RESP_R1      1
#define TYPE_RESP_R2      2
#define TYPE_RESP_R3      3
#define TYPE_RESP_R4      4
#define TYPE_RESP_R5      5
#define TYPE_RESP_R6      6

xdata bool IsAppCmd = false;

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_BLOCKLEN         : 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, PBYTE CmdBuf)
{
    BYTE RespType , RespLen , CmdType;
    BYTE Status;
    BYTE i;
    BYTE RetryCount = 0;

    RespType = SdGetRespType(CmdIndex);

    if((CmdIndex == READ_BLOCK)||
       (CmdIndex == READ_MUL_BLOCK))
    {
        RespLen = 6;
        CmdType = SD_CMD_RX_DATA;
    }
    else if((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;
    }

    for( ; RetryCount < 3; RetryCount++)
    {
        CmdBuf[0] = CARD_CMD_START | CmdIndex;
        for(i = 0; i < 5; i++)
            CSRWrite(SD_BASE + SD_CMDBUF_BASE + i, CmdBuf[i]);

        CSRWrite(SD_BASE + SD_COMMAND, CmdType);

        //CmdTimer = SD_CMD_TIMEOUT;
        CmdTimer = 5; // 50ms
        while(CmdTimer > 0)
        {
            Status = CSRRead(SD_BASE + SD_IE);
            if(Status & SD_COMPLETE)
            {
                CSRWrite(SD_BASE + SD_IE, ~SD_COMPLETE); // Clear INT
                break;
            }
        }
        if(CmdTimer == 0) // Timeout
        {
            SdCtrlReset(); // ???
            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.
            CSRWrite(SD_BASE + SD_IE, ~SD_CRC7_ERR);
            for(i = 0; i < RespLen; i++)
                SdRespBuf[i] = CSRRead(SD_BASE + SD_RESPBUF_BASE + i);
            return STATUS_SUCCESS;
        }

        if(CSRRead(SD_BASE + SD_IE) & SD_CRC7_ERR) // CRC7 Error
        {
            CSRWrite(SD_BASE + SD_IE, ~SD_CRC7_ERR); // Clear INT
            continue;
        }

        for(i = 0; i < RespLen; i++)
            SdRespBuf[i] = CSRRead(SD_BASE + SD_RESPBUF_BASE + 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

⌨️ 快捷键说明

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