From 7b4d9b8d0ad0e0bea8c8c2e696342aa63dfb4d79 Mon Sep 17 00:00:00 2001 From: Michael Chisholm Date: Mon, 7 Aug 2006 11:54:04 +0000 Subject: [PATCH] Moved the SD initialization to a common function --- source/disc_io/io_m3sd.c | 89 +++++++--------------------- source/disc_io/io_njsd.c | 86 ++++++++------------------- source/disc_io/io_scsd.c | 106 +++++++++++----------------------- source/disc_io/io_sd_common.c | 79 +++++++++++++++++++++++++ source/disc_io/io_sd_common.h | 17 +++++- 5 files changed, 174 insertions(+), 203 deletions(-) diff --git a/source/disc_io/io_m3sd.c b/source/disc_io/io_m3sd.c index d4151db..322ad00 100644 --- a/source/disc_io/io_m3sd.c +++ b/source/disc_io/io_m3sd.c @@ -38,6 +38,9 @@ 2006-08-05 - Chishm * Tries multiple times to get a Relative Card Address at startup + + 2006-08-07 - Chishm + * Moved the SD initialization to a common function */ #include "io_m3sd.h" @@ -56,11 +59,10 @@ //--------------------------------------------------------------- // Send / receive timeouts, to stop infinite wait loops -#define MAX_STARTUP_TRIES 20 // Arbitrary value, check if the card is ready 20 times before giving up #define NUM_STARTUP_CLOCKS 100 // Number of empty (0xFF when sending) bytes to send/receive to/from the card -#define TRANSMIT_TIMEOUT 2000 // Time to wait for the M3 to respond to transmit or receive requests +#define TRANSMIT_TIMEOUT 20000 // Time to wait for the M3 to respond to transmit or receive requests #define RESPONSE_TIMEOUT 256 // Number of clocks sent to the SD card before giving up -#define WRITE_TIMEOUT 300 // Time to wait for the card to finish writing +#define WRITE_TIMEOUT 3000 // Time to wait for the card to finish writing //--------------------------------------------------------------- // Variables required for tracking SD state @@ -236,10 +238,17 @@ static void _M3SD_getClocks (u32 numClocks) { } } +bool _M3SD_cmd_6byte_response (u8* responseBuffer, u8 command, u32 data) { + _M3SD_sendCommand (command, data); + return _M3SD_getResponse (responseBuffer, 6); +} + +bool _M3SD_cmd_17byte_response (u8* responseBuffer, u8 command, u32 data) { + _M3SD_sendCommand (command, data); + return _M3SD_getResponse (responseBuffer, 17); +} + static bool _M3SD_initCard (void) { - int i; - u8 responseBuffer[17]; // sizeof 17 to hold the maximum response size possible - // Give the card time to stabilise _M3SD_sendClocks (NUM_STARTUP_CLOCKS); @@ -252,70 +261,12 @@ static bool _M3SD_initCard (void) { // Card is now reset, including it's address _M3SD_relativeCardAddress = 0; - - for (i = 0; i < MAX_STARTUP_TRIES ; i++) { - _M3SD_sendCommand (APP_CMD, 0); - if (!_M3SD_getResponse_R1 (responseBuffer)) { - return false; - } - _M3SD_sendCommand (SD_APP_OP_COND, SD_OCR_VALUE); - if ((_M3SD_getResponse_R3 (responseBuffer)) && ((responseBuffer[1] & 0x80) != 0)) { - // Card is ready to receive commands now - break; - } - } - - if (i == MAX_STARTUP_TRIES) { - return false; - } - - // The card's name, as assigned by the manufacturer - _M3SD_sendCommand (ALL_SEND_CID, 0); - _M3SD_getResponse_R2 (responseBuffer); - - // Get a new address - for (i = 0; i < MAX_STARTUP_TRIES ; i++) { - _M3SD_sendCommand (SEND_RELATIVE_ADDR, 0); - _M3SD_getResponse_R6 (responseBuffer); - _M3SD_relativeCardAddress = (responseBuffer[1] << 24) | (responseBuffer[2] << 16); - if ((responseBuffer[3] & 0x1e) != (SD_STATE_STBY << 1)) { - break; - } - } - if (i >= MAX_STARTUP_TRIES) { - return false; - } - - // Some cards won't go to higher speeds unless they think you checked their capabilities - _M3SD_sendCommand (SEND_CSD, _M3SD_relativeCardAddress); - _M3SD_getResponse_R2 (responseBuffer); - - // Only this card should respond to all future commands - _M3SD_sendCommand (SELECT_CARD, _M3SD_relativeCardAddress); - _M3SD_getResponse_R1 (responseBuffer); - - // Set a 4 bit data bus - _M3SD_sendCommand (APP_CMD, _M3SD_relativeCardAddress); - _M3SD_getResponse_R1 (responseBuffer); - - _M3SD_sendCommand (SET_BUS_WIDTH, 2); - _M3SD_getResponse_R1 (responseBuffer); - - // Use 512 byte blocks - _M3SD_sendCommand (SET_BLOCKLEN, BYTES_PER_READ); - _M3SD_getResponse_R1 (responseBuffer); - - // Wait until card is ready for data - i = 0; - do { - if (i >= RESPONSE_TIMEOUT) { - return false; - } - i++; - _M3SD_sendCommand (SEND_STATUS, _M3SD_relativeCardAddress); - } while ((!_M3SD_getResponse_R1 (responseBuffer)) && ((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA))); - return true; + // Init the card + return _SD_InitCard (_M3SD_cmd_6byte_response, + _M3SD_cmd_17byte_response, + true, + &_M3SD_relativeCardAddress); } static bool _M3SD_readData (void* buffer) { diff --git a/source/disc_io/io_njsd.c b/source/disc_io/io_njsd.c index 7d3ba83..de369ad 100644 --- a/source/disc_io/io_njsd.c +++ b/source/disc_io/io_njsd.c @@ -35,6 +35,9 @@ 2006-08-06 - Chishm * Removed unneeded _NJSD_writeRAM function * Removed casts for calls to cardWriteCommand + + 2006-08-07 - Chishm + * Moved the SD initialization to a common function */ #include "io_njsd.h" @@ -46,7 +49,6 @@ #include "io_sd_common.h" #define _NJSD_SYNC -// #define _NJSD_DEBUG //--------------------------------------------------------------- // Card communication speeds @@ -64,11 +66,10 @@ //--------------------------------------------------------------- // Send / receive timeouts, to stop infinite wait loops -#define IRQ_TIMEOUT 100000 -#define RESET_TIMEOUT 1000 -#define COMMAND_TIMEOUT 10000 -#define MAX_STARTUP_TRIES 20 // Arbitrary value, check if the card is ready 20 times before giving up -#define WRITE_TIMEOUT 300 // Time to wait for the card to finish writing +#define IRQ_TIMEOUT 1000000 +#define RESET_TIMEOUT 10000 +#define COMMAND_TIMEOUT 100000 +#define WRITE_TIMEOUT 3000 // Time to wait for the card to finish writing static const u8 _NJSD_read_cmd[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40}; @@ -191,13 +192,6 @@ static bool _NJSD_sendCMDR (int speed, u8 *rsp_buf, int type, u8 cmd, u32 param) i++; } } while (CARD_CR2 & CARD_BUSY); - -#ifdef _NJSD_DEBUG - iprintf ("r: "); - for (i = 0; i < 6; i++) - iprintf ("%02X ", rsp_buf[i]); - iprintf ("\n"); -#endif } else { CARD_CR2 = _NJSD_cardFlags; while (CARD_CR2 & CARD_BUSY); @@ -390,62 +384,32 @@ static bool _NJSD_sendCMDN (int speed, u8 cmd, u32 param) { return true; } +bool _NJSD_cmd_6byte_response (u8* responseBuffer, u8 command, u32 data) { + return _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, command, data); +} + +bool _NJSD_cmd_17byte_response (u8* responseBuffer, u8 command, u32 data) { + return _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_136, command, data); +} + static bool _NJSD_cardInit (void) { - u8 responseBuffer[17]; - int i; - // If the commands succeed the first time, assume they'll always succeed - if (! _NJSD_sendCLK (SD_CLK_167KHz, 256) ) return false; - if (! _NJSD_sendCMDN (SD_CLK_167KHz, GO_IDLE_STATE, 0) ) return false; + if (! _NJSD_sendCLK (SD_CLK_167KHz, 256) ) { + return false; + } + if (! _NJSD_sendCMDN (SD_CLK_167KHz, GO_IDLE_STATE, 0) ) { + return false; + } _NJSD_sendCLK (SD_CLK_167KHz, 8); _NJSD_sendCLK (SD_CLK_167KHz, 256); _NJSD_sendCMDN (SD_CLK_167KHz, GO_IDLE_STATE, 0); _NJSD_sendCLK (SD_CLK_167KHz, 8); - for (i = 0; i < MAX_STARTUP_TRIES ; i++) { - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, APP_CMD, 0); - if ( - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, SD_APP_OP_COND, SD_OCR_VALUE) && - ((responseBuffer[1] & 0x80) != 0)) - { - // Card is ready to receive commands now - break; - } - } - if (i >= MAX_STARTUP_TRIES) { - return false; - } - - // The card's name, as assigned by the manufacturer - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_136, ALL_SEND_CID, 0); - - // Get a new address - for (i = 0; i < MAX_STARTUP_TRIES ; i++) { - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, SEND_RELATIVE_ADDR, 0); - _NJSD_relativeCardAddress = (responseBuffer[1] << 24) | (responseBuffer[2] << 16); - if ((responseBuffer[3] & 0x1e) != (SD_STATE_STBY << 1)) { - break; - } - } - if (i >= MAX_STARTUP_TRIES) { - return false; - } - - // Some cards won't go to higher speeds unless they think you checked their capabilities - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_136, SEND_CSD, _NJSD_relativeCardAddress); - - // Only this card should respond to all future commands - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, SELECT_CARD, _NJSD_relativeCardAddress); - - // Set a 4 bit data bus - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, APP_CMD, _NJSD_relativeCardAddress); - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, SET_BUS_WIDTH, 2); // 4-bit mode. - - // Use 512 byte blocks - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, SET_BLOCKLEN, 512); // 512 byte blocks - - return true; + return _SD_InitCard (_NJSD_cmd_6byte_response, + _NJSD_cmd_17byte_response, + true, + &_NJSD_relativeCardAddress); } diff --git a/source/disc_io/io_scsd.c b/source/disc_io/io_scsd.c index 7358deb..9a024d0 100644 --- a/source/disc_io/io_scsd.c +++ b/source/disc_io/io_scsd.c @@ -39,6 +39,9 @@ 2006-08-05 - Chishm * Tries multiple times to get a Relative Card Address at startup + + 2006-08-07 - Chishm + * Moved the SD initialization to a common function */ #include "io_scsd.h" @@ -66,12 +69,11 @@ //--------------------------------------------------------------- // Send / receive timeouts, to stop infinite wait loops -#define MAX_STARTUP_TRIES 20 // Arbitrary value, check if the card is ready 20 times before giving up #define NUM_STARTUP_CLOCKS 100 // Number of empty (0xFF when sending) bytes to send/receive to/from the card -#define TRANSMIT_TIMEOUT 10000 // Time to wait for the SC to respond to transmit or receive requests +#define TRANSMIT_TIMEOUT 100000 // Time to wait for the SC to respond to transmit or receive requests #define RESPONSE_TIMEOUT 256 // Number of clocks sent to the SD card before giving up #define BUSY_WAIT_TIMEOUT 500000 -#define WRITE_TIMEOUT 300 // Time to wait for the card to finish writing +#define WRITE_TIMEOUT 3000 // Time to wait for the card to finish writing //--------------------------------------------------------------- // Variables required for tracking SD state static u32 _SCSD_relativeCardAddress = 0; // Preshifted Relative Card Address @@ -81,8 +83,17 @@ static u32 _SCSD_relativeCardAddress = 0; // Preshifted Relative Card Address extern bool _SCSD_writeData_s (u8 *data, u16* crc); -static inline void _SCSD_unlock (void) { +static bool _SCSD_unlock (void) { + //see if we can write to SCSD RAM + vu32 *ramPointer = (u32*)0x08000000; + _SC_changeMode (SC_MODE_RAM); + *ramPointer = 0x5555aaaa; + *ramPointer = ~*ramPointer; + if(*ramPointer != 0xaaaa5555) { + return false; + } _SC_changeMode (SC_MODE_MEDIA); + return true; } static bool _SCSD_sendCommand (u8 command, u32 argument) { @@ -188,10 +199,18 @@ static void _SCSD_sendClocks (u32 numClocks) { } while (numClocks--); } +bool _SCSD_cmd_6byte_response (u8* responseBuffer, u8 command, u32 data) { + _SCSD_sendCommand (command, data); + return _SCSD_getResponse (responseBuffer, 6); +} + +bool _SCSD_cmd_17byte_response (u8* responseBuffer, u8 command, u32 data) { + _SCSD_sendCommand (command, data); + return _SCSD_getResponse (responseBuffer, 17); +} + + static bool _SCSD_initCard (void) { - int i; - u8 responseBuffer[17] = {0}; // sizeof 17 to hold the maximum response size possible - // Give the card time to stabilise _SCSD_sendClocks (NUM_STARTUP_CLOCKS); @@ -205,70 +224,11 @@ static bool _SCSD_initCard (void) { // Card is now reset, including it's address _SCSD_relativeCardAddress = 0; - for (i = 0; i < MAX_STARTUP_TRIES ; i++) { - _SCSD_sendCommand (APP_CMD, 0); - if (!_SCSD_getResponse_R1 (responseBuffer)) { - return false; - } - - _SCSD_sendCommand (SD_APP_OP_COND, SD_OCR_VALUE); - if ((_SCSD_getResponse_R3 (responseBuffer)) && ((responseBuffer[1] & 0x80) != 0)) { - // Card is ready to receive commands now - break; - } - } - - if (i >= MAX_STARTUP_TRIES) { - return false; - } - - // The card's name, as assigned by the manufacturer - _SCSD_sendCommand (ALL_SEND_CID, 0); - _SCSD_getResponse_R2 (responseBuffer); - - // Get a new address - for (i = 0; i < MAX_STARTUP_TRIES ; i++) { - _SCSD_sendCommand (SEND_RELATIVE_ADDR, 0); - _SCSD_getResponse_R6 (responseBuffer); - _SCSD_relativeCardAddress = (responseBuffer[1] << 24) | (responseBuffer[2] << 16); - if ((responseBuffer[3] & 0x1e) != (SD_STATE_STBY << 1)) { - break; - } - } - if (i >= MAX_STARTUP_TRIES) { - return false; - } - - // Some cards won't go to higher speeds unless they think you checked their capabilities - _SCSD_sendCommand (SEND_CSD, _SCSD_relativeCardAddress); - _SCSD_getResponse_R2 (responseBuffer); - - // Only this card should respond to all future commands - _SCSD_sendCommand (SELECT_CARD, _SCSD_relativeCardAddress); - _SCSD_getResponse_R1 (responseBuffer); - - // Set a 4 bit data bus - _SCSD_sendCommand (APP_CMD, _SCSD_relativeCardAddress); - _SCSD_getResponse_R1 (responseBuffer); - - _SCSD_sendCommand (SET_BUS_WIDTH, 2); - _SCSD_getResponse_R1 (responseBuffer); - - // Use 512 byte blocks - _SCSD_sendCommand (SET_BLOCKLEN, BYTES_PER_READ); - _SCSD_getResponse_R1 (responseBuffer); - - // Wait until card is ready for data - i = 0; - do { - if (i >= RESPONSE_TIMEOUT) { - return false; - } - i++; - _SCSD_sendCommand (SEND_STATUS, _SCSD_relativeCardAddress); - } while ((!_SCSD_getResponse_R1 (responseBuffer)) && ((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA))); - - return true; + // Init the card + return _SD_InitCard (_SCSD_cmd_6byte_response, + _SCSD_cmd_17byte_response, + true, + &_SCSD_relativeCardAddress); } static bool _SCSD_readData (void* buffer) { @@ -313,7 +273,9 @@ static bool _SCSD_readData (void* buffer) { // Functions needed for the external interface bool _SCSD_startUp (void) { - _SCSD_unlock(); + if (!_SCSD_unlock()) { + return false; + } return _SCSD_initCard(); } diff --git a/source/disc_io/io_sd_common.c b/source/disc_io/io_sd_common.c index a67eb9f..0a38e62 100644 --- a/source/disc_io/io_sd_common.c +++ b/source/disc_io/io_sd_common.c @@ -29,10 +29,17 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-08-07 - Chishm + * Moved the SD initialization to a common function + * Increased timeouts for slower cards */ #include "io_sd_common.h" +#define MAX_STARTUP_TRIES 1000 // Arbitrary value, check if the card is ready 20 times before giving up +#define RESPONSE_TIMEOUT 256 // Number of clocks sent to the SD card before giving up + /* Improved CRC7 function provided by cory1492 Calculates the CRC of an SD command, and includes the end bit in the byte @@ -122,3 +129,75 @@ void _SD_CRC16 (u8* buff, int buffLength, u8* crc16buff) { return; } +/* +Initialise the SD card, after it has been sent into an Idle state +cmd_6byte_response: a pointer to a function that sends the SD card a command and gets a 6 byte response +cmd_17byte_response: a pointer to a function that sends the SD card a command and gets a 17 byte response +use4bitBus: initialise card to use a 4 bit data bus when communicating with the card +RCA: a pointer to the location to store the card's Relative Card Address, preshifted up by 16 bits. +*/ +bool _SD_InitCard (_SD_FN_CMD_6BYTE_RESPONSE cmd_6byte_response, + _SD_FN_CMD_17BYTE_RESPONSE cmd_17byte_response, + bool use4bitBus, + u32 *RCA) +{ + u8 responseBuffer[17] = {0}; + int i; + + for (i = 0; i < MAX_STARTUP_TRIES ; i++) { + cmd_6byte_response (responseBuffer, APP_CMD, 0); + if ( + cmd_6byte_response (responseBuffer, SD_APP_OP_COND, SD_OCR_VALUE) && + ((responseBuffer[1] & 0x80) != 0)) + { + // Card is ready to receive commands now + break; + } + } + if (i >= MAX_STARTUP_TRIES) { + return false; + } + + // The card's name, as assigned by the manufacturer + cmd_17byte_response (responseBuffer, ALL_SEND_CID, 0); + + // Get a new address + for (i = 0; i < MAX_STARTUP_TRIES ; i++) { + cmd_6byte_response (responseBuffer, SEND_RELATIVE_ADDR, 0); + *RCA = (responseBuffer[1] << 24) | (responseBuffer[2] << 16); + if ((responseBuffer[3] & 0x1e) != (SD_STATE_STBY << 1)) { + break; + } + } + if (i >= MAX_STARTUP_TRIES) { + return false; + } + + // Some cards won't go to higher speeds unless they think you checked their capabilities + cmd_17byte_response (responseBuffer, SEND_CSD, *RCA); + + // Only this card should respond to all future commands + cmd_6byte_response (responseBuffer, SELECT_CARD, *RCA); + + if (use4bitBus) { + // Set a 4 bit data bus + cmd_6byte_response (responseBuffer, APP_CMD, *RCA); + cmd_6byte_response (responseBuffer, SET_BUS_WIDTH, 2); // 4-bit mode. + } + + // Use 512 byte blocks + cmd_6byte_response (responseBuffer, SET_BLOCKLEN, 512); // 512 byte blocks + + // Wait until card is ready for data + i = 0; + do { + if (i >= RESPONSE_TIMEOUT) { + return false; + } + i++; + } while (!cmd_6byte_response (responseBuffer, SEND_STATUS, *RCA) && ((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA))); + + return true; +} + + diff --git a/source/disc_io/io_sd_common.h b/source/disc_io/io_sd_common.h index 3ed5afb..09abffa 100644 --- a/source/disc_io/io_sd_common.h +++ b/source/disc_io/io_sd_common.h @@ -64,7 +64,8 @@ /* OCR (Operating Conditions Register) send value */ //#define SD_OCR_VALUE 0x00030000 /* 2.8V to 3.0V */ -#define SD_OCR_VALUE 0x003F8000 /* 2.7V to 3.4V */ +//#define SD_OCR_VALUE 0x003F8000 /* 2.7V to 3.4V */ +#define SD_OCR_VALUE 0x00FC0000 /* SD Data repsonses */ #define SD_CARD_BUSY 0xff @@ -95,5 +96,19 @@ four data lines at once */ extern void _SD_CRC16 (u8* buff, int buffLength, u8* crc16buff); +typedef bool (*_SD_FN_CMD_6BYTE_RESPONSE) (u8* responseBuffer, u8 command, u32 data); +typedef bool (*_SD_FN_CMD_17BYTE_RESPONSE) (u8* responseBuffer, u8 command, u32 data); + +/* +Initialise the SD card, after it has been sent into an Idle state +cmd_6byte_response: a pointer to a function that sends the SD card a command and gets a 6 byte response +cmd_17byte_response: a pointer to a function that sends the SD card a command and gets a 17 byte response +use4bitBus: initialise card to use a 4 bit data bus when communicating with the card +RCA: a pointer to the location to store the card's Relative Card Address, preshifted up by 16 bits. +*/ +extern bool _SD_InitCard (_SD_FN_CMD_6BYTE_RESPONSE cmd_6byte_response, + _SD_FN_CMD_17BYTE_RESPONSE cmd_17byte_response, + bool use4bitBus, + u32 *RCA); #endif // define IO_SD_COMMON_H