Browse Source

Write performance improvements. Doubled performance to 900kb/sec.

Michael McMaster 12 years ago
parent
commit
4fb7f73a13

+ 1 - 1
lib/SCSI2SD/readme.txt

@@ -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:
 

+ 11 - 13
lib/SCSI2SD/software/SCSI2SD/SCSI2SD.cydsn/disk.c

@@ -117,7 +117,7 @@ static void doWrite(uint32 lba, uint32 blocks)
 		transfer.currentBlock = 0;
 		scsiDev.phase = DATA_OUT;
 		scsiDev.dataLen = SCSI_BLOCK_SIZE;
-
+		scsiDev.dataPtr = SCSI_BLOCK_SIZE; // TODO FIX scsiDiskPoll()
 		sdPrepareWrite();
 	}
 }
@@ -370,21 +370,19 @@ void scsiDiskPoll()
 	else if (scsiDev.phase == DATA_OUT &&
 		transfer.currentBlock != transfer.blocks)
 	{
-		if (scsiDev.dataPtr == SCSI_BLOCK_SIZE)
+		int writeOk = sdWriteSector();
+		// TODO FIX scsiDiskPoll() scsiDev.dataPtr = 0;
+		transfer.currentBlock++;
+		if (transfer.currentBlock >= transfer.blocks)
 		{
-			int writeOk = sdWriteSector();
+			scsiDev.dataLen = 0;
 			scsiDev.dataPtr = 0;
-			transfer.currentBlock++;
-			if (transfer.currentBlock >= transfer.blocks)
-			{
-				scsiDev.dataLen = 0;
-				scsiDev.phase = STATUS;
-				scsiDiskReset();
+			scsiDev.phase = STATUS;
+			scsiDiskReset();
 
-				if (writeOk)
-				{
-					sdCompleteWrite();
-				}
+			if (writeOk)
+			{
+				sdCompleteWrite();
 			}
 		}
 	}

+ 48 - 9
lib/SCSI2SD/software/SCSI2SD/SCSI2SD.cydsn/sd.c

@@ -284,22 +284,61 @@ static void sdWaitWriteBusy()
 
 int sdWriteSector()
 {
-	int result, i, maxWait;
+	int prep, i, guard;	
+	int result, maxWait;
 	uint8 dataToken;
+
+	// Don't do a bus settle delay if we're already in the correct phase.
+	if (transfer.currentBlock == 0)
+	{
+		scsiEnterPhase(DATA_OUT);
+	}
 	
 	// Wait for a previously-written sector to complete.
 	sdWaitWriteBusy();
-
 	sdSpiByte(0xFC); // MULTIPLE byte start token
-	for (i = 0; i < SCSI_BLOCK_SIZE; i++)
+	
+	prep = 0;
+	i = 0;
+	guard = 0;
+
+	// This loop is critically important for performance.
+	// We stream data straight from the SCSI fifos into the SPIM component
+	// FIFO's. If the loop isn't fast enough, the transmit FIFO's will empty,
+	// and performance will suffer. Every clock cycle counts.	
+	while (i < SCSI_BLOCK_SIZE)
 	{
-		while(!(SDCard_ReadTxStatus() & SDCard_STS_TX_FIFO_NOT_FULL))
-		{}
-		SDCard_WriteTxData(scsiDev.data[i]);
-	}
-	while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE)) {}
-	SDCard_ClearFIFO();
+		uint8_t sdRxStatus = CY_GET_REG8(SDCard_RX_STATUS_PTR);
+		uint8_t scsiStatus = CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG);
+
+		// Read from the SCSI fifo if there is room to stream the byte to the
+		// SPIM fifos
+		// See sdReadSector for comment on guard (FIFO size is really 5)
+		if((guard - i < 4) &&
+			(scsiStatus & 2)) // SCSI RX FIFO NOT EMPTY
+		{
+			uint8_t val = CY_GET_REG8(scsiTarget_datapath__F1_REG);
+			CY_SET_REG8(SDCard_TXDATA_PTR, val);
+			guard++;
+		}
+	
+		// Byte has been sent out the SPIM interface.
+		if (sdRxStatus & SDCard_STS_RX_FIFO_NOT_EMPTY)
+		{
+			 CY_GET_REG8(SDCard_RXDATA_PTR);
+			++i;
+		}
 
+		if (prep < SCSI_BLOCK_SIZE &&
+			(scsiStatus & 1) // SCSI TX FIFO NOT FULL
+			)
+		{
+			// Trigger the SCSI component to read a byte
+			CY_SET_REG8(scsiTarget_datapath__F0_REG, 0xFF);
+			prep++;
+		}			
+	}
+	
 	sdSpiByte(0x00); // CRC
 	sdSpiByte(0x00); // CRC