00001
00002
00003
00004
00005
00006
00014
00015
00016 #include "microsd.h"
00017 #include "xspi_l.h"
00018 #include "xio.h"
00019
00020
00021
00033 Xuint8 Microsd_crc7(Xuint8 *MessBuff)
00034 {
00035 int i;
00036 Xuint8 Upper8;
00037 Xuint32 Lower32;
00038
00039 Upper8 = MessBuff[0];
00040 Lower32 = ( (Xuint32) MessBuff[1] << 24 ) |
00041 ( (Xuint32) MessBuff[2] << 16 ) |
00042 ( (Xuint32) MessBuff[3] << 8 ) |
00043 ( (Xuint32) MessBuff[4] );
00044
00045 for(i = 0; i < 40; i++)
00046 {
00047 if(Upper8 & 0x80)
00048 Upper8 ^= G_POLY7;
00049
00050
00051 Upper8 <<= 1;
00052
00053 if(Lower32 & 0x80000000)
00054 Upper8 |= 0x01;
00055
00056 Lower32 <<= 1;
00057 }
00058
00059 return Upper8;
00060 }
00061
00062
00076 Xuint16 Microsd_crc16(Xuint8 *MessBuff, unsigned int len)
00077 {
00078 Xuint16 crc = 0;
00079 int byten, bitn, xorFlag;
00080
00081 if(len <= 1) {
00082 xil_printf("crc16() does not handle 1-byte messages.\r\n"); return 0; }
00083
00084 for(byten = 0; byten < len+2; byten++)
00085 for(bitn = 0; bitn < 8; bitn++)
00086 {
00087 xorFlag = crc & 0x8000;
00088 crc <<= 1;
00089
00090 if((byten < len) && (MessBuff[byten] & (0x80 >> bitn)))
00091 crc |= 0x0001;
00092
00093 if(xorFlag)
00094 crc ^= G_POLY16;
00095
00096 }
00097
00098 return crc;
00099 }
00100
00101
00120 Xuint8 Microsd_GetRespToken(Microsd *SDPtr, Xuint8 *RecvBuff,
00121 unsigned int NumBytes)
00122 {
00123 int i = 0;
00124 Xuint8 Resp, IdleBuff = 0xFF;
00125
00126 do {
00127 Microsd_SpiTransfer(SDPtr, &IdleBuff, &Resp, 1);
00128 while( !(XSpi_mGetStatusReg(SDPtr->SpiBaseAddr) & XSP_SR_TX_EMPTY_MASK) );
00129 } while( Resp == 0xFF && ++i < 1000);
00130
00131 if(i == 1000) {
00132 xil_printf("Microsd_CheckResponse() timed-out!\r\n"); return 0xFF; }
00133
00134 for(i = 0; i < NumBytes; i++)
00135 Microsd_SpiTransfer(SDPtr, &IdleBuff, &RecvBuff[i], 1);
00136
00137 return Resp;
00138 }
00139
00140
00150 void Microsd_Initialize(Microsd *SDPtr, Xuint32 BaseAddr)
00151 {
00152 SDPtr->SpiBaseAddr = BaseAddr;
00153 SDPtr->Status = 0x00;
00154 }
00155
00156
00167 void Microsd_FlushRxFifo(Microsd *InstPtr)
00168 {
00169 Xuint8 temp;
00170
00171 while( !(XSpi_mGetStatusReg(InstPtr->SpiBaseAddr) & XSP_SR_RX_EMPTY_MASK) )
00172 {
00173 temp = XSpi_mRecvByte(InstPtr->SpiBaseAddr);
00174 xil_printf("This byte was thrown away by FlushRxFifo(): %02X\r\n", temp);
00175 }
00176
00177 }
00178
00179
00194 Xuint8 Microsd_ReadBlock(Microsd *SDPtr, Xuint32 addr, Xuint8 data[], int len)
00195 {
00196 int i;
00197 Xuint8 Response, IdleBuff = 0xFF;
00198 Xuint16 myCRC, crc;
00199
00200 if( !(SDPtr->Status & SD_STATUS_READY_MASK) ) {
00201 xil_printf("Card was not initialized.\r\n"); return SDPtr->Status; }
00202
00203 Microsd_FlushRxFifo(SDPtr);
00204
00205
00206 Response = Microsd_SendCmd(SDPtr, SET_BLOCKLEN, len);
00207 if(Response != R1_READY_STATE)
00208 return Response;
00209
00210 Response = Microsd_SendCmd(SDPtr, READ_SINGLE_BLOCK, addr);
00211 if(Response != R1_READY_STATE)
00212 return Response;
00213
00214
00215 Response = Microsd_GetRespToken(SDPtr, data, len);
00216 if(Response != START_TOKEN)
00217 {
00218 xil_printf("Start Token seems wrong.\r\n");
00219 return Response;
00220 }
00221
00222
00223 Microsd_SpiTransfer(SDPtr, &IdleBuff, &Response, 1);
00224 crc = Response;
00225 Microsd_SpiTransfer(SDPtr, &IdleBuff, &Response, 1);
00226 crc = ( crc << 8 ) | Response;
00227
00228 if( crc != Microsd_crc16(data, len) ) {
00229 xil_printf("ReadBlock(): CRC error, data dumped.\r\n");
00230 return 0x00;
00231 }
00232
00233 return 0xFF;
00234 }
00235
00236
00249 Xuint8 Microsd_SendCmd(Microsd *SDPtr, Xuint8 cmd_idx, Xuint32 arg)
00250 {
00251 int i = 0;
00252 Xuint8 MessBuff[6], RecvBuff[6];
00253
00254 Microsd_FlushRxFifo(SDPtr);
00255
00256
00257
00258 MessBuff[0] = (cmd_idx & 0x3F) | 0x40;
00259 MessBuff[1] = (Xuint8) ((arg >> 24) & 0x000000FF);
00260 MessBuff[2] = (Xuint8) ((arg >> 16) & 0x000000FF);
00261 MessBuff[3] = (Xuint8) ((arg >> 8) & 0x000000FF);
00262 MessBuff[4] = (Xuint8) ( arg & 0x000000FF);
00263 MessBuff[5] = ( Microsd_crc7(MessBuff) | 0x01 );
00264
00265 Microsd_SpiTransfer(SDPtr, MessBuff, RecvBuff, 6);
00266
00267 return Microsd_GetResponse(SDPtr);
00268 }
00269
00270
00284 Xuint8 Microsd_SetSpiMode(Microsd *SDPtr)
00285 {
00286
00287 int i;
00288 Xuint8 RecvBuff[32];
00289
00290
00291 Xuint8 CMD0[6] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95},
00292 CMD8[6] = {0x48, 0x00, 0x00, 0x01, 0x69, 0xFB},
00293 CMD41[6] = {0x69, 0x00, 0x00, 0x00, 0x00, 0xE5},
00294 CMD55[6] = {0x77, 0x00, 0x00, 0x00, 0x00, 0x65},
00295 CMD58[6] = {0x7A, 0x00, 0x00, 0x00, 0x00, 0xFD};
00296
00297 Microsd_FlushRxFifo(SDPtr);
00298
00299 if(SDPtr->Status & SD_STATUS_READY_MASK) {
00300 xil_printf("Card is already in SPI Mode.\r\n"); return SDPtr->Status; }
00301
00302
00303 Microsd_SpiTransfer(SDPtr, CMD0, RecvBuff, 6);
00304
00305
00306 for(i = 0; Microsd_GetResponse(SDPtr) != R1_IDLE_STATE; i++)
00307 if(i == 10) {
00308 xil_printf("Setup ended early. Possibly Card not present.\r\n");
00309 return SDPtr->Status;
00310 }
00311
00312 #ifdef __CRC_ON__
00313
00314
00315 Xuint8 CMD59[6] = {0x7B, 0x00, 0x00, 0x00, 0x01, 0x83};
00316 Microsd_SpiTransfer(SDPtr, CMD59, RecvBuff, 6);
00317
00318 Microsd_GetResponse(SDPtr);
00319
00320 #endif
00321
00322
00323 Microsd_SpiTransfer(SDPtr, CMD8, RecvBuff, 6);
00324
00325 Xuint8 CorrectResp[4] = {0x00, 0x00, 0x01, 0x69};
00326
00327 if(Microsd_GetRespToken(SDPtr, RecvBuff, R7_RESPONSE_SIZE) != R1_IDLE_STATE)
00328 xil_printf("Card gave a bad response to CMD8.\r\n");
00329
00330 for(i = 0; i < R7_RESPONSE_SIZE-1; i++)
00331 if( RecvBuff[i] != CorrectResp[i]) {
00332 xil_printf("ERROR: Retry CMD8.\r\n");
00333 return (SDPtr->Status |= SD_STATUS_LEGACY_MASK);
00334 }
00335
00336
00337
00338
00339 do
00340 {
00341 Microsd_SpiTransfer(SDPtr, CMD55, RecvBuff, 6);
00342
00343 if( Microsd_GetResponse(SDPtr) != R1_IDLE_STATE ) {
00344 xil_printf("Bad response from CMD55.\r\n"); return SDPtr->Status; }
00345
00346 Microsd_SpiTransfer(SDPtr, CMD41, RecvBuff, 6);
00347
00348 } while( Microsd_GetResponse(SDPtr) != R1_READY_STATE );
00349
00350
00351 Microsd_SpiTransfer(SDPtr, CMD58, RecvBuff, 6);
00352 Microsd_GetRespToken(SDPtr, RecvBuff, R3_RESPONSE_SIZE);
00353
00354 if(RecvBuff[0] & 0x40)
00355 return (SDPtr->Status |= SD_STATUS_HIGHCAP_MASK);
00356
00357 return (SDPtr->Status |= SD_STATUS_READY_MASK);
00358 }
00359
00360
00372 void Microsd_SpiTransfer(Microsd *SDPtr, Xuint8 SendBuff[], Xuint8 RecvBuff[],
00373 unsigned int NumBytes)
00374 {
00375 int i;
00376 Xuint32 BaseAddr = SDPtr->SpiBaseAddr;
00377
00378 for(i = 0; i < NumBytes; i++)
00379 XSpi_mSendByte(BaseAddr, SendBuff[i]);
00380
00381 XSpi_mEnable(BaseAddr);
00382
00383 while( !(XSpi_mGetStatusReg(BaseAddr) & XSP_SR_TX_EMPTY_MASK) );
00384
00385 for(i = 0; !(XSpi_mGetStatusReg(BaseAddr) & XSP_SR_RX_EMPTY_MASK); i++)
00386 RecvBuff[i] = XSpi_mRecvByte(BaseAddr);
00387
00388 XSpi_mDisable(BaseAddr);
00389 }
00390
00391
00405 Xuint8 Microsd_WriteBlock(Microsd *SDPtr, Xuint32 address,
00406 Xuint8 data[], int len)
00407 {
00408 int i;
00409 Xuint8 Response;
00410 Xuint8 IdleBuff = 0xFF, StartToken = START_TOKEN;
00411 Xuint16 WriteCRC;
00412
00413 Microsd_FlushRxFifo(SDPtr);
00414
00415
00416 Response = Microsd_SendCmd(SDPtr, SET_BLOCKLEN, len);
00417 if(Response != R1_READY_STATE)
00418 return Response;
00419
00420 Response = Microsd_SendCmd(SDPtr, WRITE_BLOCK, address);
00421 if(Response != R1_READY_STATE)
00422 {
00423 xil_printf("WRITE_BLOCK was not accepted. Response: 0x%X\r\n", Response);
00424 return Response;
00425 }
00426
00427
00428 Microsd_SpiTransfer(SDPtr, &IdleBuff, &Response, 1);
00429 Microsd_SpiTransfer(SDPtr, &IdleBuff, &Response, 1);
00430
00431
00432 Microsd_SpiTransfer(SDPtr, &StartToken, &Response, 1);
00433
00434
00435 for(i = 0; i < len; i++)
00436 {
00437 Microsd_SpiTransfer(SDPtr, &data[i], &Response, 1);
00438 while(!(XSpi_mGetStatusReg(SDPtr->SpiBaseAddr) & XSP_SR_TX_EMPTY_MASK));
00439 }
00440
00441
00442 WriteCRC = Microsd_crc16(data, len);
00443 Response = (Xuint8) (WriteCRC >> 8);
00444 Microsd_SpiTransfer(SDPtr, &Response, &Response, 1);
00445 Response = (Xuint8) (0x00FF & WriteCRC);
00446 Microsd_SpiTransfer(SDPtr, &Response, &Response, 1);
00447
00448
00449 Response = Microsd_GetResponse(SDPtr);
00450
00451 if((Response & 0x0F) == 0x05)
00452 xil_printf("WriteBlock(): Data excepted.\r\n");
00453 else if ((Response & 0x0F) == 0x0B)
00454 xil_printf("WriteBlock(): Data rejected due to CRC error.\r\n");
00455 else if ((Response & 0x0F) == 0x0B)
00456 xil_printf("WriteBlock(): Data rejected due to Write Error.\r\n");
00457 else
00458 xil_printf("WriteBlock(): Unknown response - %02X.\r\n", Response);
00459
00460
00461 do {
00462 Microsd_SpiTransfer(SDPtr, &IdleBuff, &Response, 1);
00463 } while( Response == 0x00 );
00464
00465 return 0x00;
00466 }