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

This commit is contained in:
Michael McMaster 2013-12-23 21:51:23 +10:00
parent 3e22ca4e6f
commit 0629f76919
3 changed files with 61 additions and 24 deletions

View File

@ -43,7 +43,7 @@ Performance
As currently implemented: 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: Tested with a 16GB class 10 SD card, via the commands:

View File

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

View File

@ -284,22 +284,61 @@ static void sdWaitWriteBusy()
int sdWriteSector() int sdWriteSector()
{ {
int result, i, maxWait; int prep, i, guard;
int result, maxWait;
uint8 dataToken; 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. // Wait for a previously-written sector to complete.
sdWaitWriteBusy(); sdWaitWriteBusy();
sdSpiByte(0xFC); // MULTIPLE byte start token sdSpiByte(0xFC); // MULTIPLE byte start token
for (i = 0; i < SCSI_BLOCK_SIZE; i++)
{ prep = 0;
while(!(SDCard_ReadTxStatus() & SDCard_STS_TX_FIFO_NOT_FULL)) i = 0;
{} guard = 0;
SDCard_WriteTxData(scsiDev.data[i]);
}
while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE)) {}
SDCard_ClearFIFO();
// 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)
{
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
sdSpiByte(0x00); // CRC sdSpiByte(0x00); // CRC