ソースを参照

Reliability improvements for SD init and reads.

Michael McMaster 12 年 前
コミット
92bf8843f7

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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 

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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.

+ 1 - 1
lib/SCSI2SD/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 

BIN
lib/SCSI2SD/software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyfit


+ 1 - 1
lib/SCSI2SD/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;
 

+ 6 - 8
lib/SCSI2SD/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)

+ 120 - 90
lib/SCSI2SD/software/SCSI2SD/SCSI2SD.cydsn/sd.c

@@ -20,6 +20,7 @@
 #include "config.h"
 #include "disk.h"
 #include "sd.h"
+#include "led.h"
 
 #include <string.h>
 
@@ -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;

+ 1 - 0
lib/SCSI2SD/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,