byte = cmd | 0x40;
SD_Write(byte);
// send command packet (6 bytes)
byte = addr>>24;
SD_Write(byte);
// msb of the address
byte = addr>>16;
SD_Write(byte);
byte = addr>>8;
SD_Write(byte);
SD_Write( addr);
// lsb
SD_Write(CRC7);
// Not used unless CRC mode on
// now wait for a response (allow for up
// to 8 bytes delay)
n = 9;
do {
res = SD_Read();
// check if ready
if ( res != 0xFF)
break;
} while ( —n > 0);
return (res);
// return the result
}
void SD_InitSPI( void)
/**
* Configure the SD card SPI bus hardware
* settings and software. *
*** Using the SD SPI mode spec settings
* instead of the MCHP example.
*
*
*
*
*
*
*/
{
nMEM_CS = 1;
// De-select the SD card
PRECONDITION: none
INPUTS: none - The hardware is explicitly
set up
OUTPUTS: none
RETURNS: none.
if (sdcard.cardInit == 1) {
return;
}
// init spi module for a slow (init) clock
// speed, 8 bit byte mode
// Master, CKE=0; CKP=1, sample end,
// prescale 1:64 (250KHz)
SPI1STATbits.SPIEN = 0;
// disable SPI for configuration
SPI1CON1 = 0x027c;
SPI1CON2 = 0x0000;
// No buffer, no frame mode
SPI1STAT = 0x8000;
// enable
}
uint8_t SD_InitMedia( void)
/**
* Discover the type and version of the
* installed SD card. This routine will find
* any SD or SDHC card and properly set it up.
*
* PRECONDITION: none
* INPUTS: none
* OUTPUTS: none
* RETURNS: 0 if successful, some other
* error if not.
*/
{
uint16_t n;
uint8_t res = 0;
// // If we get that far...
uint32_t timer;
uint8_t cmd;
uint8_t db[16];
// when we get data back to look at
if (sdcard.cardInit == 1) {
return(0);
// done, don’t do it again.
}
// 1. start with the card not selected
SD_Disable();
// 2. send 80 clock cycles so card can
// init registers
for ( n=0; n<10; n++)
SD_Clock();
// 3. now select the card
SD_Enable();
// 4. send a reset command and look for
// “IDLE”
res = SD_SendCmd( RESET, 0); SD_Disable();
if ( res != 1) {
SD_Disable();
return(LOG_FAIL);
// card did not respond with “idle”
}
// 5. Check card voltage (type) for SD 1.0
// or SD 2.0
res = SD_SendCmd(SEND_IF_COND, 0x000001AA);
// didn’t respond or responded with an
// “illegal cmd”
if ( (res == 0xFF) || (res == 0x05)) {
sdcard.cardVer = 1;
// means it’s an SD 1.0 or MMC card
// 6. send INIT until receive a 0 or
// 300ms passes
timer = t_1ms + 300;
while(timer > t_1ms) {
res = SD_SendCmd(INIT,0);
SD_Disable();
// SendSDCmd() enables SD card
if (!res) {
break;
// The card is ready
}
}
if (res != 0) {
return(LOG_FAIL);
// failed to reset.
}
SD_Disable();
// remember to disable the card
}
else { // need to pick up 4 bytes for v2
card voltage description
sdcard.cardVer = 2;
// SD version 2.0 card
for (n=0; n<4; n++) {
db[n] = SD_Read();
}
// but we’ll ignore these bytes
SD_Disable();
// 6. send INIT or SEND_APP_OP
// repeatedly until receive a 0
cmd = SEND_APP_OP;
timer = t_1ms + 300;
// wait up to .3 seconds for life
// will still be in idle mode (0x01)
// after this
res = SD_SendCmd(APP_CMD, 0);
SD_Disable();
while (timer > t_1ms) {
res = SD_SendCmd(cmd, 0x40000000);
SD_Disable();
// ACMD41 not recognized, use CMD1 Cont.
SERVO 09.2011 17