Reliability improvements for SD init and reads. v3.0.1
authorMichael McMaster <michael@codesrc.com>
Mon, 9 Dec 2013 12:00:49 +0000 (22:00 +1000)
committerMichael McMaster <michael@codesrc.com>
Mon, 9 Dec 2013 12:00:49 +0000 (22:00 +1000)
17 files changed:
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice.h
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevice_trm.h
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu.inc
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicegnu_trm.inc
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar.inc
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydeviceiar_trm.inc
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv.inc
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cydevicerv_trm.inc
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.c
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.h [changed mode: 0644->0755]
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/project.h
software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyfit
software/SCSI2SD/SCSI2SD.cydsn/disk.c
software/SCSI2SD/SCSI2SD.cydsn/scsi.c
software/SCSI2SD/SCSI2SD.cydsn/sd.c
software/SCSI2SD/SCSI2SD.cydsn/sd.h

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