Implemented multi-sector SD read command.
authorMichael McMaster <michael@codesrc.com>
Sun, 20 Oct 2013 09:50:47 +0000 (19:50 +1000)
committerMichael McMaster <michael@codesrc.com>
Sun, 20 Oct 2013 09:50:47 +0000 (19:50 +1000)
readme.txt
software/SCSI2SD/SCSI2SD.cydsn/disk.c
software/SCSI2SD/SCSI2SD.cydsn/sd.c
software/SCSI2SD/SCSI2SD.cydsn/sd.h

index fb2c3b8..b1ad39b 100644 (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
index a3ef45b..5f7be40 100755 (executable)
@@ -140,7 +140,7 @@ static void doRead(uint32 lba, uint32 blocks)
                transfer.currentBlock = 0;\r
                scsiDev.phase = DATA_IN;\r
                scsiDev.dataLen = 0; // No data yet\r
-               sdPrepareRead(0);\r
+               sdPrepareRead();\r
        }\r
 }\r
 \r
@@ -352,15 +352,7 @@ void scsiDiskPoll()
        {\r
                if (scsiDev.dataLen == 0)\r
                {\r
-                       if (sdIsReadReady())\r
-                       {\r
-                               sdReadSector();\r
-                               if ((transfer.currentBlock + 1) < transfer.blocks)\r
-                               {\r
-                                       sdPrepareRead(1); // Tell SD card to grab data while we send\r
-                                                                       // buffer to SCSI.\r
-                               }\r
-                       }\r
+                       sdReadSector();\r
                }\r
                else if (scsiDev.dataPtr == scsiDev.dataLen)\r
                {\r
@@ -371,6 +363,7 @@ void scsiDiskPoll()
                        {\r
                                scsiDev.phase = STATUS;\r
                                scsiDiskReset();\r
+                               sdCompleteRead();\r
                        }\r
                }\r
        }\r
@@ -383,12 +376,11 @@ void scsiDiskPoll()
                        scsiDev.dataPtr = 0;\r
                        transfer.currentBlock++;\r
                        if (transfer.currentBlock >= transfer.blocks)\r
-                               \r
                        {\r
                                scsiDev.dataLen = 0;\r
                                scsiDev.phase = STATUS;\r
                                scsiDiskReset();\r
-                               \r
+\r
                                if (writeOk)\r
                                {\r
                                        sdCompleteWrite();\r
index e66af34..7affe5b 100755 (executable)
@@ -127,14 +127,14 @@ static uint8 sdCRCCommandAndResponse(uint8 cmd, uint32 param)
 }\r
 \r
 \r
-void sdPrepareRead(int nextBlockOffset)\r
+void sdPrepareRead()\r
 {\r
-       uint32 len = (transfer.lba + transfer.currentBlock + nextBlockOffset);\r
+       uint32 len = (transfer.lba + transfer.currentBlock);\r
        if (!sdDev.ccs)\r
        {\r
                len = len * SCSI_BLOCK_SIZE;\r
        }\r
-       uint8 v = sdCommandAndResponse(17, len);\r
+       uint8 v = sdCommandAndResponse(SD_READ_MULTIPLE_BLOCK, len);\r
        if (v)\r
        {\r
                scsiDiskReset();\r
@@ -146,30 +146,15 @@ void sdPrepareRead(int nextBlockOffset)
        }\r
 }\r
 \r
-int sdIsReadReady()\r
+void sdReadSector()\r
 {\r
-       uint8 v = sdWaitResp();\r
-       if (v == 0xFF)\r
-       {\r
-               return 0;\r
-       }\r
-       else if (v == 0xFE)\r
-       {\r
-               return 1;\r
-       }\r
-       else\r
+       // Wait for a start-block token.\r
+       uint8 token;\r
+       do\r
        {\r
-               scsiDiskReset();\r
-               scsiDev.status = CHECK_CONDITION;\r
-               scsiDev.sense.code = HARDWARE_ERROR;\r
-               scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
-               scsiDev.phase = STATUS;\r
-               return 0;\r
-       }\r
-}\r
+               token = sdSpiByte(0xFF);\r
+       } while(token != 0xFE); // TODO don't loop forever here in case of error!\r
 \r
-void sdReadSector()\r
-{\r
        int prep = 0;\r
        int i = 0;\r
        while (i < SCSI_BLOCK_SIZE)\r
@@ -194,6 +179,28 @@ void sdReadSector()
        scsiDev.dataPtr = 0;\r
 }\r
 \r
+void sdCompleteRead()\r
+{\r
+       //uint8 r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0);\r
+       sdSendCommand(SD_STOP_TRANSMISSION, 0);\r
+       sdSpiByte(0xFF); // NEED STUFF BYTE for cmd12\r
+       uint8 r1b = sdReadResp();\r
+       if (r1b)\r
+       {\r
+               scsiDev.status = CHECK_CONDITION;\r
+               scsiDev.sense.code = HARDWARE_ERROR;\r
+               scsiDev.sense.asc = UNRECOVERED_READ_ERROR;\r
+               scsiDev.phase = STATUS;\r
+       }\r
+       \r
+       // R1b has an optional trailing "busy" signal.\r
+       uint8 busy;\r
+       do\r
+       {\r
+               busy = sdSpiByte(0xFF);\r
+       } while (busy == 0);\r
+}\r
+\r
 static void sdWaitWriteBusy()\r
 {\r
        uint8 val;\r
index 53e4079..5fa61c0 100755 (executable)
@@ -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