From: Michael McMaster Date: Mon, 9 Dec 2013 12:00:49 +0000 (+1000) Subject: Reliability improvements for SD init and reads. X-Git-Tag: v3.0.1^0 X-Git-Url: http://git.codesrc.com/gitweb.cgi?a=commitdiff_plain;h=b50aad09c8cea3074cafffd2b88883cf253ef386;p=SCSI2SD-V6.git Reliability improvements for SD init and reads. --- diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice.h b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice.h index 8263e30a..5f1b198d 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice.h +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice.h @@ -1,7 +1,7 @@ /******************************************************************************* * FILENAME: cydevice.h * OBSOLETE: Do not use this file. Use the _trm version instead. -* PSoC Creator 3.0 +* PSoC Creator 3.0 Component Pack 7 * * DESCRIPTION: * This file provides all of the address values for the entire PSoC device. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice_trm.h b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice_trm.h index 08d77aa1..e2c0687f 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice_trm.h +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice_trm.h @@ -1,7 +1,7 @@ /******************************************************************************* * FILENAME: cydevice_trm.h * -* PSoC Creator 3.0 +* PSoC Creator 3.0 Component Pack 7 * * DESCRIPTION: * This file provides all of the address values for the entire PSoC device. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu.inc b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu.inc index 833c2b6f..1776ef90 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu.inc +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu.inc @@ -1,7 +1,7 @@ /******************************************************************************* * FILENAME: cydevicegnu.inc * OBSOLETE: Do not use this file. Use the _trm version instead. -* PSoC Creator 3.0 +* PSoC Creator 3.0 Component Pack 7 * * DESCRIPTION: * This file provides all of the address values for the entire PSoC device. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu_trm.inc b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu_trm.inc index ffbe68b0..3c24869c 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu_trm.inc +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu_trm.inc @@ -1,7 +1,7 @@ /******************************************************************************* * FILENAME: cydevicegnu_trm.inc * -* PSoC Creator 3.0 +* PSoC Creator 3.0 Component Pack 7 * * DESCRIPTION: * This file provides all of the address values for the entire PSoC device. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar.inc b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar.inc index 8556d0a3..e4f1a443 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar.inc +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar.inc @@ -1,7 +1,7 @@ ; ; FILENAME: cydeviceiar.inc ; OBSOLETE: Do not use this file. Use the _trm version instead. -; PSoC Creator 3.0 +; PSoC Creator 3.0 Component Pack 7 ; ; DESCRIPTION: ; This file provides all of the address values for the entire PSoC device. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar_trm.inc b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar_trm.inc index ea4e01d4..ebd1b1dc 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar_trm.inc +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar_trm.inc @@ -1,7 +1,7 @@ ; ; FILENAME: cydeviceiar_trm.inc ; -; PSoC Creator 3.0 +; PSoC Creator 3.0 Component Pack 7 ; ; DESCRIPTION: ; This file provides all of the address values for the entire PSoC device. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv.inc b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv.inc index 4c8a5376..4ed74edd 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv.inc +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv.inc @@ -1,7 +1,7 @@ ; ; FILENAME: cydevicerv.inc ; OBSOLETE: Do not use this file. Use the _trm version instead. -; PSoC Creator 3.0 +; PSoC Creator 3.0 Component Pack 7 ; ; DESCRIPTION: ; This file provides all of the address values for the entire PSoC device. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv_trm.inc b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv_trm.inc index 232c2fc0..d4d800c6 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv_trm.inc +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv_trm.inc @@ -1,7 +1,7 @@ ; ; FILENAME: cydevicerv_trm.inc ; -; PSoC Creator 3.0 +; PSoC Creator 3.0 Component Pack 7 ; ; DESCRIPTION: ; This file provides all of the address values for the entire PSoC device. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.c b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.c index 200bad6b..6c7544ec 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.c @@ -1,6 +1,6 @@ /******************************************************************************* * FILENAME: cyfitter_cfg.c -* PSoC Creator 3.0 +* PSoC Creator 3.0 Component Pack 7 * * Description: * This file is automatically generated by PSoC Creator with device diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.h b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.h old mode 100644 new mode 100755 index 02880d0e..9481fd38 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.h +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.h @@ -1,6 +1,6 @@ /******************************************************************************* * FILENAME: cyfitter_cfg.h -* PSoC Creator 3.0 +* PSoC Creator 3.0 Component Pack 7 * * Description: * This file is automatically generated by PSoC Creator. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c index 74983918..c2a969d2 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c @@ -1,7 +1,7 @@ /******************************************************************************* * FILENAME: cymetadata.c * -* PSoC Creator 3.0 +* PSoC Creator 3.0 Component Pack 7 * * DESCRIPTION: * This file defines all extra memory spaces that need to be included. diff --git a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/project.h b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/project.h index 4f8d256f..3b9f84bb 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/project.h +++ b/software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/project.h @@ -1,6 +1,6 @@ /******************************************************************************* * File Name: project.h - * PSoC Creator 3.0 + * PSoC Creator 3.0 Component Pack 7 * * Description: * This file is automatically generated by PSoC Creator and should not diff --git a/software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyfit b/software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyfit index 9cb0e8a8..2ffb942d 100755 Binary files a/software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyfit and b/software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyfit differ diff --git a/software/SCSI2SD/SCSI2SD.cydsn/disk.c b/software/SCSI2SD/SCSI2SD.cydsn/disk.c index ed76e879..b5b3fd80 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/disk.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/disk.c @@ -418,7 +418,7 @@ void scsiDiskInit() } #endif - //if (SD_CD_Read() == 0) + if (SD_CD_Read() == 1) { blockDev.state = blockDev.state | DISK_PRESENT; diff --git a/software/SCSI2SD/SCSI2SD.cydsn/scsi.c b/software/SCSI2SD/SCSI2SD.cydsn/scsi.c index 60ea9b3a..8b69da0a 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/scsi.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/scsi.c @@ -73,16 +73,10 @@ static void process_MessageIn() // back to MESSAGE_OUT first, get out parity error message, then come // back here. } - else if (scsiDev.msgIn == MSG_COMMAND_COMPLETE) + else /*if (scsiDev.msgIn == MSG_COMMAND_COMPLETE)*/ { enter_BusFree(); } - else - { - // MESSAGE_REJECT. Go back to command phase - // TODO MESSAGE_REJECT moved to messageReject method. - scsiDev.phase = COMMAND; - } } static void messageReject() @@ -361,8 +355,12 @@ static void enter_SelectionPhase() scsiDev.parityError = 0; scsiDev.dataPtr = 0; scsiDev.savedDataPtr = 0; + scsiDev.dataLen = 0; scsiDev.status = GOOD; scsiDev.phase = SELECTION; + + transfer.blocks = 0; + transfer.currentBlock = 0; } static void process_SelectionPhase() @@ -507,7 +505,7 @@ static void process_MessageOut() (scsiDev.msgOut & 0x7) // We only support LUN 0! ) { - enter_MessageIn(MSG_REJECT); + messageReject(); } } else if (scsiDev.msgOut >= 0x20 && scsiDev.msgOut <= 0x2F) diff --git a/software/SCSI2SD/SCSI2SD.cydsn/sd.c b/software/SCSI2SD/SCSI2SD.cydsn/sd.c index 1d239ba9..2d312949 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/sd.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/sd.c @@ -20,6 +20,7 @@ #include "config.h" #include "disk.h" #include "sd.h" +#include "led.h" #include @@ -47,9 +48,7 @@ static uint8 sdCrc7(uint8* chr, uint8 cnt, uint8 crc) static uint8 sdSpiByte(uint8 value) { SDCard_WriteTxData(value); - while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE)) - {} - while (!SDCard_GetRxBufferSize()) {} + while (!(SDCard_ReadRxStatus() & SDCard_STS_RX_FIFO_NOT_EMPTY)) {} return SDCard_ReadRxData(); } @@ -88,7 +87,7 @@ static void sdSendCommand(uint8 cmd, uint32 param) sdSpiByte(send[cmd]); } // Allow command to process before reading result code. - sdSpiByte(0xFF); + sdSpiByte(0xFF); } static uint8 sdReadResp() @@ -98,25 +97,12 @@ static uint8 sdReadResp() do { v = sdSpiByte(0xFF); - } while(i-- && (v == 0xFF)); - return v; -} - -static uint8 sdWaitResp() -{ - uint8 v; - uint8 i = 255; - do - { - v = sdSpiByte(0xFF); - } while(i-- && (v != 0xFE)); + } while(i-- && (v & 0x80)); return v; } - static uint8 sdCommandAndResponse(uint8 cmd, uint32 param) { - SDCard_ClearRxBuffer(); sdSpiByte(0xFF); sdSendCommand(cmd, param); return sdReadResp(); @@ -124,12 +110,19 @@ static uint8 sdCommandAndResponse(uint8 cmd, uint32 param) static uint8 sdCRCCommandAndResponse(uint8 cmd, uint32 param) { - SDCard_ClearRxBuffer(); sdSpiByte(0xFF); sdSendCRCCommand(cmd, param); return sdReadResp(); } +// Clear the sticky status bits on error. +static void sdClearStatus() +{ + uint8 r2hi = sdCRCCommandAndResponse(SD_SEND_STATUS, 0); + uint8 r2lo = sdSpiByte(0xFF); + (void) r2hi; (void) r2lo; +} + void sdPrepareRead() { @@ -142,6 +135,7 @@ void sdPrepareRead() if (v) { scsiDiskReset(); + sdClearStatus(); scsiDev.status = CHECK_CONDITION; scsiDev.sense.code = HARDWARE_ERROR; @@ -200,20 +194,31 @@ void sdReadSector() void sdCompleteRead() { - int counter = 512; - uint8 r1b; - do - { - r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0); - } while (r1b && (counter-- > 0)); + // We cannot send even a single "padding" byte, as we normally would when + // sending a command. If we've just finished reading the very last block + // on the card, then reading an additional dummy byte will just trigger + // an error condition as we're trying to read past-the-end of the storage + // device. + // ie. do not use sdCommandAndResponse here. + sdSendCommand(SD_STOP_TRANSMISSION, 0); + uint8 r1b = sdReadResp(); + if (r1b) { + // Try very hard to make sure the transmission stops + int retries = 255; + while (r1b && retries) + { + r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0); + retries--; + } + 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 @@ -237,68 +242,62 @@ int sdWriteSector() // Wait for a previously-written sector to complete. sdWaitWriteBusy(); - sdSpiByte(0xFC); // MULTIPLE byte start token - int i; - for (i = 0; i < SCSI_BLOCK_SIZE; i++) - { - while(!(SDCard_ReadTxStatus() & SDCard_STS_TX_FIFO_NOT_FULL)) - {} - SDCard_WriteTxData(scsiDev.data[i]); - } - while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE)) + sdSpiByte(0xFC); // MULTIPLE byte start token + int i; + for (i = 0; i < SCSI_BLOCK_SIZE; i++) + { + while(!(SDCard_ReadTxStatus() & SDCard_STS_TX_FIFO_NOT_FULL)) {} - SDCard_ReadRxData(); - SDCard_ReadRxData(); - SDCard_ReadRxData(); - SDCard_ReadRxData(); - SDCard_ReadRxData(); - - sdSpiByte(0x00); // CRC - sdSpiByte(0x00); // CRC - - // Don't wait more than 1000ms. - // My 2g Kingston micro-sd card doesn't respond immediately. - // My 16Gb card does. - int maxWait = 1000; - uint8 dataToken = sdSpiByte(0xFF); // Response - while (dataToken == 0xFF && maxWait-- > 0) - { - CyDelay(1); // 1ms. - dataToken = sdSpiByte(0xFF); - } - if (((dataToken & 0x1F) >> 1) != 0x2) // Accepted. - { - sdWaitWriteBusy(); - - int counter = 512; - uint8 r1b; - do - { - r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0); - } while (r1b && (counter-- > 0)); - // R1b has an optional trailing "busy" signal. - uint8 busy; - do - { - busy = sdSpiByte(0xFF); - } while (busy == 0); - - // Wait for the card to come out of busy. - sdWaitWriteBusy(); - - scsiDiskReset(); + SDCard_WriteTxData(scsiDev.data[i]); + } + while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE)) {} + SDCard_ClearFIFO(); + + sdSpiByte(0x00); // CRC + sdSpiByte(0x00); // CRC + + // Don't wait more than 1000ms. + // My 2g Kingston micro-sd card doesn't respond immediately. + // My 16Gb card does. + int maxWait = 1000; + uint8 dataToken = sdSpiByte(0xFF); // Response + while (dataToken == 0xFF && maxWait-- > 0) + { + CyDelay(1); // 1ms. + dataToken = sdSpiByte(0xFF); + } + if (((dataToken & 0x1F) >> 1) != 0x2) // Accepted. + { + sdWaitWriteBusy(); - scsiDev.status = CHECK_CONDITION; - scsiDev.sense.code = HARDWARE_ERROR; - scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE; - scsiDev.phase = STATUS; - result = 0; - } - else + uint8 r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0); + (void) r1b; + sdSpiByte(0xFF); + + // R1b has an optional trailing "busy" signal. + uint8 busy; + do { - // The card is probably in the busy state. - // Don't wait, as we could read the SCSI interface instead. - result = 1; + busy = sdSpiByte(0xFF); + } while (busy == 0); + + // Wait for the card to come out of busy. + sdWaitWriteBusy(); + + scsiDiskReset(); + sdClearStatus(); + + scsiDev.status = CHECK_CONDITION; + scsiDev.sense.code = HARDWARE_ERROR; + scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE; + scsiDev.phase = STATUS; + result = 0; + } + else + { + // The card is probably in the busy state. + // Don't wait, as we could read the SCSI interface instead. + result = 1; } return result; @@ -312,11 +311,12 @@ void sdCompleteWrite() sdSpiByte(0xFD); // STOP TOKEN // Wait for the card to come out of busy. sdWaitWriteBusy(); - + uint8 r1 = sdCommandAndResponse(13, 0); // send status uint8 r2 = sdSpiByte(0xFF); if (r1 || r2) { + sdClearStatus(); scsiDev.status = CHECK_CONDITION; scsiDev.sense.code = HARDWARE_ERROR; scsiDev.sense.asc = WRITE_ERROR_AUTO_REALLOCATION_FAILED; @@ -350,8 +350,11 @@ static int sendIfCond() { // Version 1 card. sdDev.version = 1; + sdClearStatus(); break; } + + sdClearStatus(); } while (--retries > 0); return retries > 0; @@ -369,6 +372,8 @@ static int sdOpCond() sdCRCCommandAndResponse(SD_APP_CMD, 0); // Host Capacity Support = 1 (SDHC/SDXC supported) status = sdCRCCommandAndResponse(SD_APP_SEND_OP_COND, 0x40000000); + + sdClearStatus(); } while ((status != 0) && (--retries > 0)); return retries > 0; @@ -397,8 +402,14 @@ static int sdReadCSD() { uint8 status = sdCRCCommandAndResponse(SD_SEND_CSD, 0); if(status){goto bad;} - status = sdWaitResp(); - if (status != 0xFE) { goto bad; } + + uint8 startToken; + int maxWait = 1023; + do + { + startToken = sdSpiByte(0xFF); + } while(maxWait-- && (startToken != 0xFE)); + if (startToken != 0xFE) { goto bad; } uint8 buf[16]; int i; @@ -440,7 +451,7 @@ bad: } int sdInit() -{ +{ sdDev.version = 0; sdDev.ccs = 0; sdDev.capacity = 0; @@ -464,6 +475,7 @@ int sdInit() uint8 v = sdCRCCommandAndResponse(SD_GO_IDLE_STATE, 0); if(v != 1){goto bad;} + ledOn(); if (!sendIfCond()) goto bad; // Sets V1 or V2 flag if (!sdOpCond()) goto bad; if (!sdReadOCR()) goto bad; @@ -476,9 +488,25 @@ int sdInit() if(v){goto bad;} // now set the sd card up for full speed + // The SD Card spec says we can run SPI @ 25MHz + // But the PSoC 5LP SPIM datasheet says the most we can do is 18MHz. + // I've confirmed that no data is ever put into the RX FIFO when run at + // 20MHz or 25MHz. + // ... and then we get timing analysis failures if the BUS_CLK is over 62MHz. + // So we run the MASTER_CLK and BUS_CLK at 60MHz, and run the SPI clock at 30MHz + // (15MHz SPI transfer clock). + SDCard_Stop(); SD_Data_Clk_Start(); // Turn on the fast clock SD_Clk_Ctl_Write(1); // Select the fast clock source. SD_Init_Clk_Stop(); // Stop the slow clock. + CyDelayUs(1); + SDCard_Start(); + + // Clear out rubbish data through clock change + CyDelayUs(1); + SDCard_ReadRxStatus(); + SDCard_ReadTxStatus(); + SDCard_ClearFIFO(); if (!sdReadCSD()) goto bad; @@ -489,6 +517,8 @@ bad: sdDev.capacity = 0; out: + sdClearStatus(); + ledOff(); return result; } @@ -512,7 +542,7 @@ void sdPrepareWrite() if (v) { scsiDiskReset(); - + sdClearStatus(); scsiDev.status = CHECK_CONDITION; scsiDev.sense.code = HARDWARE_ERROR; scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE; diff --git a/software/SCSI2SD/SCSI2SD.cydsn/sd.h b/software/SCSI2SD/SCSI2SD.cydsn/sd.h index 5fa61c04..b8e3c31d 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/sd.h +++ b/software/SCSI2SD/SCSI2SD.cydsn/sd.h @@ -24,6 +24,7 @@ typedef enum SD_SEND_IF_COND = 8, // SD V2 SD_SEND_CSD = 9, SD_STOP_TRANSMISSION = 12, + SD_SEND_STATUS = 13, SD_SET_BLOCKLEN = 16, SD_READ_MULTIPLE_BLOCK = 18, SD_APP_SET_WR_BLK_ERASE_COUNT = 23,