Implemented multi-sector SD read command.

This commit is contained in:
Michael McMaster 2013-10-20 19:50:47 +10:00
parent b9ed365266
commit ad91a39f77
4 changed files with 42 additions and 41 deletions

View File

@ -43,7 +43,7 @@ Performance
As currently implemented:
Sequential read: 250kb/sec Sequential write: 240kb/sec
Sequential read: 424kb/sec Sequential write: 414kb/sec
Tested with a 16GB class 10 SD card, via the commands:
@ -53,7 +53,7 @@ Tested with a 16GB class 10 SD card, via the commands:
# READ TEST
sudo dd bs=8192 count=100 if=/dev/sdX of=/dev/null
I am working on updating the slow polling SD card communication to use DMA. I expect the performance to reach 1Mb/sec.
I am working on updating the SD card communication to use DMA, to allow simultaneous use of the SD and SCSI interfaces. I expect the performance to reach 1Mb/sec.
Compatibility

View File

@ -140,7 +140,7 @@ static void doRead(uint32 lba, uint32 blocks)
transfer.currentBlock = 0;
scsiDev.phase = DATA_IN;
scsiDev.dataLen = 0; // No data yet
sdPrepareRead(0);
sdPrepareRead();
}
}
@ -352,15 +352,7 @@ void scsiDiskPoll()
{
if (scsiDev.dataLen == 0)
{
if (sdIsReadReady())
{
sdReadSector();
if ((transfer.currentBlock + 1) < transfer.blocks)
{
sdPrepareRead(1); // Tell SD card to grab data while we send
// buffer to SCSI.
}
}
sdReadSector();
}
else if (scsiDev.dataPtr == scsiDev.dataLen)
{
@ -371,6 +363,7 @@ void scsiDiskPoll()
{
scsiDev.phase = STATUS;
scsiDiskReset();
sdCompleteRead();
}
}
}
@ -383,12 +376,11 @@ void scsiDiskPoll()
scsiDev.dataPtr = 0;
transfer.currentBlock++;
if (transfer.currentBlock >= transfer.blocks)
{
scsiDev.dataLen = 0;
scsiDev.phase = STATUS;
scsiDiskReset();
if (writeOk)
{
sdCompleteWrite();

View File

@ -127,14 +127,14 @@ static uint8 sdCRCCommandAndResponse(uint8 cmd, uint32 param)
}
void sdPrepareRead(int nextBlockOffset)
void sdPrepareRead()
{
uint32 len = (transfer.lba + transfer.currentBlock + nextBlockOffset);
uint32 len = (transfer.lba + transfer.currentBlock);
if (!sdDev.ccs)
{
len = len * SCSI_BLOCK_SIZE;
}
uint8 v = sdCommandAndResponse(17, len);
uint8 v = sdCommandAndResponse(SD_READ_MULTIPLE_BLOCK, len);
if (v)
{
scsiDiskReset();
@ -146,30 +146,15 @@ void sdPrepareRead(int nextBlockOffset)
}
}
int sdIsReadReady()
{
uint8 v = sdWaitResp();
if (v == 0xFF)
{
return 0;
}
else if (v == 0xFE)
{
return 1;
}
else
{
scsiDiskReset();
scsiDev.status = CHECK_CONDITION;
scsiDev.sense.code = HARDWARE_ERROR;
scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
scsiDev.phase = STATUS;
return 0;
}
}
void sdReadSector()
{
// Wait for a start-block token.
uint8 token;
do
{
token = sdSpiByte(0xFF);
} while(token != 0xFE); // TODO don't loop forever here in case of error!
int prep = 0;
int i = 0;
while (i < SCSI_BLOCK_SIZE)
@ -194,6 +179,28 @@ void sdReadSector()
scsiDev.dataPtr = 0;
}
void sdCompleteRead()
{
//uint8 r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0);
sdSendCommand(SD_STOP_TRANSMISSION, 0);
sdSpiByte(0xFF); // NEED STUFF BYTE for cmd12
uint8 r1b = sdReadResp();
if (r1b)
{
scsiDev.status = CHECK_CONDITION;
scsiDev.sense.code = HARDWARE_ERROR;
scsiDev.sense.asc = UNRECOVERED_READ_ERROR;
scsiDev.phase = STATUS;
}
// R1b has an optional trailing "busy" signal.
uint8 busy;
do
{
busy = sdSpiByte(0xFF);
} while (busy == 0);
}
static void sdWaitWriteBusy()
{
uint8 val;

View File

@ -23,7 +23,9 @@ typedef enum
SD_SEND_OP_COND = 1,
SD_SEND_IF_COND = 8, // SD V2
SD_SEND_CSD = 9,
SD_STOP_TRANSMISSION = 12,
SD_SET_BLOCKLEN = 16,
SD_READ_MULTIPLE_BLOCK = 18,
SD_APP_SET_WR_BLK_ERASE_COUNT = 23,
SD_APP_SEND_OP_COND = 41,
SD_APP_CMD = 55,
@ -56,8 +58,8 @@ void sdPrepareWrite();
int sdWriteSector();
void sdCompleteWrite();
void sdPrepareRead(int nextBlockOffset);
int sdIsReadReady();
void sdPrepareRead();
void sdReadSector();
void sdCompleteRead();
#endif