?? sd.c
字號:
/*
**********************************************************************************************
* 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 + -