Write performance improvements. Doubled performance to 900kb/sec.
authorMichael McMaster <michael@codesrc.com>
Mon, 23 Dec 2013 11:51:23 +0000 (21:51 +1000)
committerMichael McMaster <michael@codesrc.com>
Mon, 23 Dec 2013 11:51:23 +0000 (21:51 +1000)
readme.txt
software/SCSI2SD/SCSI2SD.cydsn/disk.c
software/SCSI2SD/SCSI2SD.cydsn/sd.c

index 8236382..0931201 100644 (file)
@@ -43,7 +43,7 @@ Performance
 
 As currently implemented:
 
-Sequential read: 930kb/sec Sequential write: 414kb/sec
+Sequential read: 930kb/sec Sequential write: 900kb/sec
 
 Tested with a 16GB class 10 SD card, via the commands:
 
index 427112c..20de53b 100755 (executable)
@@ -117,7 +117,7 @@ static void doWrite(uint32 lba, uint32 blocks)
                transfer.currentBlock = 0;\r
                scsiDev.phase = DATA_OUT;\r
                scsiDev.dataLen = SCSI_BLOCK_SIZE;\r
-\r
+               scsiDev.dataPtr = SCSI_BLOCK_SIZE; // TODO FIX scsiDiskPoll()\r
                sdPrepareWrite();\r
        }\r
 }\r
@@ -370,21 +370,19 @@ void scsiDiskPoll()
        else if (scsiDev.phase == DATA_OUT &&\r
                transfer.currentBlock != transfer.blocks)\r
        {\r
-               if (scsiDev.dataPtr == SCSI_BLOCK_SIZE)\r
+               int writeOk = sdWriteSector();\r
+               // TODO FIX scsiDiskPoll() scsiDev.dataPtr = 0;\r
+               transfer.currentBlock++;\r
+               if (transfer.currentBlock >= transfer.blocks)\r
                {\r
-                       int writeOk = sdWriteSector();\r
+                       scsiDev.dataLen = 0;\r
                        scsiDev.dataPtr = 0;\r
-                       transfer.currentBlock++;\r
-                       if (transfer.currentBlock >= transfer.blocks)\r
-                       {\r
-                               scsiDev.dataLen = 0;\r
-                               scsiDev.phase = STATUS;\r
-                               scsiDiskReset();\r
+                       scsiDev.phase = STATUS;\r
+                       scsiDiskReset();\r
 \r
-                               if (writeOk)\r
-                               {\r
-                                       sdCompleteWrite();\r
-                               }\r
+                       if (writeOk)\r
+                       {\r
+                               sdCompleteWrite();\r
                        }\r
                }\r
        }\r
index 21a8ecc..a35ea6e 100755 (executable)
@@ -284,22 +284,61 @@ static void sdWaitWriteBusy()
 \r
 int sdWriteSector()\r
 {\r
-       int result, i, maxWait;\r
+       int prep, i, guard;     \r
+       int result, maxWait;\r
        uint8 dataToken;\r
+\r
+       // Don't do a bus settle delay if we're already in the correct phase.\r
+       if (transfer.currentBlock == 0)\r
+       {\r
+               scsiEnterPhase(DATA_OUT);\r
+       }\r
        \r
        // Wait for a previously-written sector to complete.\r
        sdWaitWriteBusy();\r
-\r
        sdSpiByte(0xFC); // MULTIPLE byte start token\r
-       for (i = 0; i < SCSI_BLOCK_SIZE; i++)\r
+       \r
+       prep = 0;\r
+       i = 0;\r
+       guard = 0;\r
+\r
+       // This loop is critically important for performance.\r
+       // We stream data straight from the SCSI fifos into the SPIM component\r
+       // FIFO's. If the loop isn't fast enough, the transmit FIFO's will empty,\r
+       // and performance will suffer. Every clock cycle counts.       \r
+       while (i < SCSI_BLOCK_SIZE)\r
        {\r
-               while(!(SDCard_ReadTxStatus() & SDCard_STS_TX_FIFO_NOT_FULL))\r
-               {}\r
-               SDCard_WriteTxData(scsiDev.data[i]);\r
-       }\r
-       while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE)) {}\r
-       SDCard_ClearFIFO();\r
+               uint8_t sdRxStatus = CY_GET_REG8(SDCard_RX_STATUS_PTR);\r
+               uint8_t scsiStatus = CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG);\r
+\r
+               // Read from the SCSI fifo if there is room to stream the byte to the\r
+               // SPIM fifos\r
+               // See sdReadSector for comment on guard (FIFO size is really 5)\r
+               if((guard - i < 4) &&\r
+                       (scsiStatus & 2)) // SCSI RX FIFO NOT EMPTY\r
+               {\r
+                       uint8_t val = CY_GET_REG8(scsiTarget_datapath__F1_REG);\r
+                       CY_SET_REG8(SDCard_TXDATA_PTR, val);\r
+                       guard++;\r
+               }\r
+       \r
+               // Byte has been sent out the SPIM interface.\r
+               if (sdRxStatus & SDCard_STS_RX_FIFO_NOT_EMPTY)\r
+               {\r
+                        CY_GET_REG8(SDCard_RXDATA_PTR);\r
+                       ++i;\r
+               }\r
 \r
+               if (prep < SCSI_BLOCK_SIZE &&\r
+                       (scsiStatus & 1) // SCSI TX FIFO NOT FULL\r
+                       )\r
+               {\r
+                       // Trigger the SCSI component to read a byte\r
+                       CY_SET_REG8(scsiTarget_datapath__F0_REG, 0xFF);\r
+                       prep++;\r
+               }                       \r
+       }\r
+       \r
        sdSpiByte(0x00); // CRC\r
        sdSpiByte(0x00); // CRC\r
 \r