diff --git a/readme.txt b/readme.txt index fb2c3b8..b1ad39b 100644 --- a/readme.txt +++ b/readme.txt @@ -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 diff --git a/software/SCSI2SD/SCSI2SD.cydsn/disk.c b/software/SCSI2SD/SCSI2SD.cydsn/disk.c index a3ef45b..5f7be40 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/disk.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/disk.c @@ -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(); diff --git a/software/SCSI2SD/SCSI2SD.cydsn/sd.c b/software/SCSI2SD/SCSI2SD.cydsn/sd.c index e66af34..7affe5b 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/sd.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/sd.c @@ -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; diff --git a/software/SCSI2SD/SCSI2SD.cydsn/sd.h b/software/SCSI2SD/SCSI2SD.cydsn/sd.h index 53e4079..5fa61c0 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/sd.h +++ b/software/SCSI2SD/SCSI2SD.cydsn/sd.h @@ -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