📄 cardmng.c
字号:
/* NAME DATE REMARKS */
/* ========== ============ ==============================================*/
/* Victor 2004-07-29 create */
/****************************************************************************/
void SendBytes(UINT8 *str, UINT len)
{
UINT i;
UINT8 temp;
while(*(volatile UINT32 *)REG_SPI_STAT & 0x0040); //BSYF(D6)=1 means transmit is not completed
for(i = 0; i < len; i ++){
while(!(*(volatile UINT32 *)REG_SPI_STAT & 0x0010)); //TDEF(D4)=1 means transmit buffer empty
*(volatile UINT32 *)REG_SPI_TXD = (UINT16)str[i]; // send data
}
}
/****************************************************************************/
/* FUNCTION: ReceiveBytes */
/* DESCRIPTION:Receive bytes from card */
/* INPUTS: str store bytes received from card */
/* len number of bytes received from card */
/* OUTPUTS: */
/****************************************************************************/
/* NAME DATE REMARKS */
/* ========== ============ ==============================================*/
/* Victor 2004-07-29 create */
/****************************************************************************/
void ReceiveBytes(UINT8 *str, UINT len)
{
UINT i;
UINT8 temp;
// clear receive buffer full flag
while(*(volatile UINT32 *)REG_SPI_STAT & 0x0004){ //RDFF(D2)=1 means receive buffer full
temp = (UINT8)(*(volatile UINT32 *)REG_SPI_RXD); // receive data
}
for(i = 0; i < len; i ++){
while(!(*(volatile UINT32 *)REG_SPI_STAT & 0x0010)); //TDEF(D4)=1 means transmit buffer empty
*(volatile UINT32 *)REG_SPI_TXD = 0xffff; // send dummy data is used as triger for data receiving
while(!(*(volatile UINT32 *)REG_SPI_STAT & 0x0004)); //RDFF(D2)=1 means receive buffer full
str[i] = (UINT8)(*(volatile UINT32 *)REG_SPI_RXD); // receive data
}
}
/****************************************************************************/
/* FUNCTION: EnableCard */
/* DESCRIPTION:enable card */
/* INPUTS */
/* OUTPUTS: */
/****************************************************************************/
/* NAME DATE REMARKS */
/* ========== ============ ==============================================*/
/* Victor 2004-07-29 create */
/****************************************************************************/
void EnableCard(void)
{
MMC_CS_ENABLE
*((volatile UINT32 *)REG_SPI_CTL1) |= 0x0001; // set ENA(D0) to 1(SPI circuit is on)
}
/****************************************************************************/
/* FUNCTION: DisableCard */
/* DESCRIPTION:Disable card */
/* INPUTS */
/* OUTPUTS: */
/****************************************************************************/
/* NAME DATE REMARKS */
/* ========== ============ ==============================================*/
/* Victor 2004-07-29 create */
/****************************************************************************/
void DisableCard(void)
{
UINT i;
for(i = 0; i < MIN_NEC; i++){ //wait NEC
SendBytes(DUMMY, 1);
}
*((volatile UINT32 *)REG_SPI_CTL1) &= ~0x0001; // set ENA(D0) to 0(SPI circuit is off)
MMC_CS_DISABLE
}
/****************************************************************************/
/* FUNCTION: IsCardLocked */
/* DESCRIPTION:Check if card is locked */
/* INPUTS */
/* OUTPUTS: TRUE card is locked */
/* FALSE card is not locked */
/****************************************************************************/
/* NAME DATE REMARKS */
/* ========== ============ ==========================*/
/* Victor 2004-07-29 create */
/****************************************************************************/
BOOL IsCardLocked(void)
{
return FALSE; //608中都是TF卡 不会有写保护
if( MMC_IS_WP )
{
return TRUE;
}
return FALSE;
}
/****************************************************************************/
/* FUNCTION: SendCommand */
/* DESCRIPTION:SendCommand to card and receive response from card. */
/* Note: for data read/write, it will not disable the card */
/* INPUTS command command will be sent */
/* responseType type of command response */
/* response store the response from card */
/* OUTPUTS: TRUE command send success */
/* FALSE time out */
/****************************************************************************/
/* NAME DATE REMARKS */
/* ========== ============ =========================*/
/* Victor 2004-07-29 create */
/****************************************************************************/
BOOL SendCommand(UINT8 *command, UINT responseType, UINT8 *response)
{
UINT i;
SendBytes(DUMMY, 1); //Null operation, output some OSCLK
EnableCard(); //SET CS = 'L'
for(i = 0; i < MIN_NCS; i++){ //wait NCS
SendBytes(DUMMY, 1);
}
SendBytes(command, 6); //SEND COM
for(i = 0; i < MIN_NCR; i++){ //wait NCR(min)
SendBytes(DUMMY, 1);
}
//check the response token
for( i = 0; i < MAX_NCR; i++ ){ //wait NCR(max)
ReceiveBytes(response, 1);
if(!(*response & 0x80)){
break; // is a response token
}
}
if(i == MAX_NCR){ // time out
DisableCard(); //SET CS = 'H'
return FALSE;
}
switch(responseType){
case R1_FORMAT:
break;
case R1B_FORMAT:
break;
case R2_FORMAT:
ReceiveBytes(response+1, 1);
break;
case R3_FORMAT:
ReceiveBytes(response+1, 4);
break;
case RDATA_FORMAT:
return TRUE; // Can't disable card. The caller must disable card.
}
DisableCard(); //SET CS = 'H'
return TRUE;
}
/****************************************************************************/
/* FUNCTION: ResetCard */
/* DESCRIPTION:reset card. It will initialize the card and make sure the */
/* card has compatible VDD voltage range. */
/* INPUTS */
/* OUTPUTS: CARD_ERR_NO reset OK */
/* CARD_ERR_TIMEOUT time out */
/* CARD_ERR_CMDILLEGAL command is illegal */
/* CARD_ERR_BUSY card is busy */
/* CARD_ERR_VOLTAGE card has incompatible voltage range */
/****************************************************************************/
/* NAME DATE REMARKS */
/* ========== ============ ==============================================*/
/* Victor 2004-07-29 create */
/****************************************************************************/
INT ResetCard(void)
{
UINT8 r1; // response format R1
UINT8 r3[5]; // response format R3
UINT i, j;
//reset the card: send COM0 go to idle state
for(i = 0; i < 5; i++){
if(SendCommand((UINT8 *)ucpCmd0, R1_FORMAT, &r1) != FALSE){
if(r1 != 0x01){
return CARD_ERR_CMDILLEGAL; // command is illegal
}else{
break;
}
}
}
if(i == 5){
return CARD_ERR_TIMEOUT; // Time out
}
// send COM1 repeat for card go to ready state
for(i = 0; i < 200; i++){
if(SendCommand((UINT8 *)ucpCmd1, R1_FORMAT, &r1) != TRUE){ //send cmd1
return CARD_ERR_TIMEOUT; // Time out
}
if(r1 == 0x00){ // MMC ready
break;
}
}
if(i == 200){
return CARD_ERR_TIMEOUT; // Time out
}
_getOCR:
// make sure the card has compatible VDD voltage range
// Get VDD voltage window(OCR)
if(SendCommand((UINT8 *)ucpCmd58, R3_FORMAT, r3) == TRUE){ //SEND COM58
if(r3[0] != 0x00){
return CARD_ERR_CMDILLEGAL; // command is illegal
}
/*
if(!(r3[1] & 0x80)){ // bit 31 of OCR is busy signal
return CARD_ERR_BUSY; // power up routine has not finished
}
*/
((UINT8 *)(®OCR))[0] = r3[4];
((UINT8 *)(®OCR))[1] = r3[3];
((UINT8 *)(®OCR))[2] = r3[2];
((UINT8 *)(®OCR))[3] = r3[1];
if((regOCR & MASTER_VDD_WIN) == MASTER_VDD_WIN){
return CARD_ERR_NO; // VDD voltage range is compatible
}else{
return CARD_ERR_VOLTAGE; // VDD voltage range is not compatible
}
}else{
return CARD_ERR_TIMEOUT; // Time out
}
}
/****************************************************************************/
/* FUNCTION: ReadCSD_CID */
/* DESCRIPTION:read registor CSD or CID */
/* INPUTS cmd command for read CSD or CID */
/* buf store CSD or CID */
/* len length of CSD or CID */
/* OUTPUTS: CARD_ERR_NO read OK */
/* CARD_ERR_TIMEOUT time out */
/* CARD_ERR_CMDILLEGAL command is illegal */
/****************************************************************************/
/* NAME DATE REMARKS */
/* ========== ============ ==============================================*/
/* Victor 2004-07-29 create */
/****************************************************************************/
INT ReadCSD_CID(UINT8 *cmd, UINT8 *buf, UINT len)
{
UINT8 r1; // response format R1
UINT i;
//send CMD9/CMD10
if(SendCommand(cmd, RDATA_FORMAT, &r1) == FALSE){
return CARD_ERR_TIMEOUT; // time out
}
if(r1 != 0x00){
DisableCard(); //SET CS = 'H'
return CARD_ERR_CMDILLEGAL; // command is illegal
}
for(i = 0; i < MIN_NCX; i++){ //wait NCX(min)
SendBytes(DUMMY, 1);
}
//check the response data token
for(i = 0; i < MAX_NCX; i++){ //wait NCX(max)
ReceiveBytes(&r1, 1);
if(r1 == SINGLE_READ_START){
break; // data token: data begin to be transmitted
}
}
if(i == MAX_NCX){
return CARD_ERR_TIMEOUT; // time out
}
// receive CSD/CID
ReceiveBytes(buf, len);
DisableCard(); //SET CS = 'H'
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -