Moved the SD initialization to a common function

This commit is contained in:
Michael Chisholm 2006-08-07 11:54:04 +00:00
parent 8ceb43c66c
commit 7b4d9b8d0a
5 changed files with 174 additions and 203 deletions

View File

@ -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) {

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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