DRESULT disk_readp ( BYTE *buff, /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */ DWORD lba, /* Sector number (LBA) */ WORD ofs, /* Byte offset to read from (0..511) */ WORD cnt /* Number of bytes to read (ofs + cnt mus be <= 512) */ ) { DRESULT res; BYTE d; WORD bc, tmr; if (!(CardType & CT_BLOCK)) lba *= 512; /* Convert to byte address if needed */ res = RES_ERROR; if (send_cmd(CMD17, lba) == 0) { /* READ_SINGLE_BLOCK */ tmr = 1000; do { /* Wait for data packet in timeout of 100ms */ // DLY_US(100); mmc_spi_Wait100us(); d = rcvr_mmc(); } while (d == 0xFF && --tmr); if (d == 0xFE) { /* A data packet arrived */ bc = 514 - ofs - cnt; /* Skip leading bytes */ if (ofs) skip_mmc(ofs); /* Receive a part of the sector */ // if (buff) { /* Store data to the memory */ do *buff++ = rcvr_mmc(); while (--cnt); // } else { /* Forward data to the outgoing stream */ // do { // d = rcvr_mmc(); // FORWARD(d); // } while (--cnt); // } /* Skip trailing bytes and CRC */ skip_mmc(bc); res = RES_OK; } } release_spi(); return res; }
DSTATUS disk_initialize (void) { BYTE n, cmd, ty, buf[4]; UINT tmr; // INIT_PORT(); mmc_spi_InitSocket(); // CS_H(); mmc_spi_SetCardDeselect(); skip_mmc(10); /* Dummy clocks */ ty = 0; if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ for (n = 0; n < 4; n++) buf[n] = rcvr_mmc(); /* Get trailing return value of R7 resp */ if (buf[2] == 0x01 && buf[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (send_cmd(ACMD41, 1UL << 30) == 0) break; // DLY_US(1000); mmc_spi_SetTimer(1); while( mmc_spi_CheckTimer() ) {} } if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ for (n = 0; n < 4; n++) buf[n] = rcvr_mmc(); ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ } } } else { /* SDv1 or MMCv3 */ if (send_cmd(ACMD41, 0) <= 1) { ty = CT_SD1; cmd = ACMD41; /* SDv1 */ } else { ty = CT_MMC; cmd = CMD1; /* MMCv3 */ } for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state */ if (send_cmd(ACMD41, 0) == 0) break; // DLY_US(1000); mmc_spi_SetTimer(1); while( mmc_spi_CheckTimer() ) {} } if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ ty = 0; } } CardType = ty; release_spi(); // return ty ? 0 : STA_NOINIT; if ( !ty ) return STA_NOINIT; mmc_spi_SetTransClock(); return 0; }
DRESULT disk_readp ( BYTE *buff, /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */ DWORD sector, /* Sector number (LBA) */ UINT offset, /* Byte offset to read from (0..511) */ UINT count /* Number of bytes to read (ofs + cnt mus be <= 512) */ ) { BYTE *buff_sec = buffer; DRESULT res; BYTE d; UINT bc, tmr; if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */ // check if sector is already in sector buffer if(buffer_sector == sector) { buff_sec += offset; // skip to requested bytes while(count--) *buff++ = *buff_sec++; return RES_OK; } res = RES_ERROR; if (send_cmd(CMD17, sector) == 0) { /* READ_SINGLE_BLOCK */ tmr = 1000; do { /* Wait for data packet in timeout of 100ms */ DLY_US(100); d = rcvr_mmc(); } while (d == 0xFF && --tmr); if (d == 0xFE) { /* A data packet arrived */ bc = 512 - offset - count; /* Skip leading bytes (store in buffer only) */ while(offset--) *buff_sec++ = rcvr_mmc(); /* Receive a part of the sector */ if (buff) { /* Store data to the memory */ do *buff_sec++ = *buff++ = rcvr_mmc(); while (--count); } else { /* Forward data to the outgoing stream */ do { *buff_sec++ = d = rcvr_mmc(); FORWARD(d); } while (--count); } /* Skip trailing bytes (store in buffer only) */ while(bc--) *buff_sec++ = rcvr_mmc(); /* and skip crc */ skip_mmc(2); buffer_sector = sector; res = RES_OK; } } release_spi(); return res; }
DSTATUS disk_initialize (void) { BYTE n, cmd, ty, buf[4]; UINT tmr; #if AXI_SPI /* * Initialize the SPI driver so that it's ready to use, * specify the device ID that is generated in xparameters.h. */ XStatus Status = XSpi_Initialize(&Spi, XPAR_SDCARD_SPI_DEVICE_ID); if(Status != XST_SUCCESS) {\ xil_printf("Failure INIT\r\n"); return XST_FAILURE; } /* * Set the SPI device as a master and in manual slave select mode such * that the slave select signal does not toggle for every byte of a * transfer, this must be done before the slave select is set. */ Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION); if(Status != XST_SUCCESS) { xil_printf("Failure Options\r\n"); return XST_FAILURE; } Status = XSpi_SetSlaveSelect(&Spi, 1); if(Status != XST_SUCCESS) { xil_printf("Failure Slave Select\r\n"); return XST_FAILURE; } XSpi_Start(&Spi); XSpi_IntrGlobalDisable(&Spi); DLY_US(1); #else INIT_PORT(); CS_H(); #endif skip_mmc(10); /* Dummy clocks */ ty = 0; if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ for (n = 0; n < 4; n++) buf[n] = rcvr_mmc(); /* Get trailing return value of R7 resp */ if (buf[2] == 0x01 && buf[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (send_cmd(ACMD41, 1UL << 30) == 0) break; DLY_US(1000); } if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ for (n = 0; n < 4; n++) buf[n] = rcvr_mmc(); ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ } } } else { /* SDv1 or MMCv3 */ if (send_cmd(ACMD41, 0) <= 1) { ty = CT_SD1; cmd = ACMD41; /* SDv1 */ } else { ty = CT_MMC; cmd = CMD1; /* MMCv3 */ } for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state */ if (send_cmd(cmd, 0) == 0) break; DLY_US(1000); } if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ ty = 0; } } CardType = ty; release_spi(); return ty ? 0 : STA_NOINIT; }