mirror of
https://github.com/fhgwright/SCSI2SD.git
synced 2024-06-11 05:29:27 +00:00
Reliability improvements for SD init and reads.
This commit is contained in:
parent
a835e7a1d3
commit
b50aad09c8
|
@ -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,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,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,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,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,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,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,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,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
|
||||
|
|
2
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.h
Normal file → Executable file
2
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.h
Normal file → Executable file
|
@ -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,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,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
|
||||
|
|
Binary file not shown.
|
@ -418,7 +418,7 @@ void scsiDiskInit()
|
|||
}
|
||||
#endif
|
||||
|
||||
//if (SD_CD_Read() == 0)
|
||||
if (SD_CD_Read() == 1)
|
||||
{
|
||||
blockDev.state = blockDev.state | DISK_PRESENT;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
} while(i-- && (v & 0x80));
|
||||
return v;
|
||||
}
|
||||
|
||||
static uint8 sdWaitResp()
|
||||
{
|
||||
uint8 v;
|
||||
uint8 i = 255;
|
||||
do
|
||||
{
|
||||
v = sdSpiByte(0xFF);
|
||||
} while(i-- && (v != 0xFE));
|
||||
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();
|
||||
SDCard_WriteTxData(scsiDev.data[i]);
|
||||
}
|
||||
while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE)) {}
|
||||
SDCard_ClearFIFO();
|
||||
|
||||
sdSpiByte(0x00); // CRC
|
||||
sdSpiByte(0x00); // CRC
|
||||
|
||||
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)
|
||||
// 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();
|
||||
|
||||
uint8 r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0);
|
||||
(void) r1b;
|
||||
sdSpiByte(0xFF);
|
||||
|
||||
// R1b has an optional trailing "busy" signal.
|
||||
uint8 busy;
|
||||
do
|
||||
{
|
||||
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);
|
||||
busy = sdSpiByte(0xFF);
|
||||
} while (busy == 0);
|
||||
|
||||
// Wait for the card to come out of busy.
|
||||
sdWaitWriteBusy();
|
||||
// Wait for the card to come out of busy.
|
||||
sdWaitWriteBusy();
|
||||
|
||||
scsiDiskReset();
|
||||
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;
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue
Block a user