When I issue cmd17 with address (0x00000000) to my card from PIC-18F4520 on SPI bus, I get a correct return R1 token from the command issue. Then, after a few loops checking, I get a 0xFE marker returned from my issuing SPI_Put_Char(0xFF). Data should then start so I read 512 bytes into my IO_Buffer array. As I scan the returns, I got many 0x00 bytes. Oddly, and repeatedly, at about pos 448 in sector 0, some data comes over - a few bytes here and there - then the the final 32 bytes (I can only view 32 at a time on my LCD screen) are all zeroes followed by the 0x55AA marker expected at the end of the boot sector.
The odd thing, is that using disk investigator reveals the SD card has the proper sector zero information - MSDOS message, EB jump code, all sorts of stuff. My read command gives all that back as zeroes. I just don't get what's happening.
Other information: I boot with the cmd0, cmd8, cmd58 and OCR reads fine. Then acmd41 (looping cmd55 followed by APP_SEND_OP_COND). All seem to respond and give expected marker. Finally, I even use SEND_CID to get the card information. that returns MID=3 OID=SD and a verion SD017 followed by other information - seems all to be correct.
I have tried adding pull up and pull down resistors on DOUT from card but doesn't affect any results.
I am desperate for ideas to try to get this card to read correctly. I have (BTW) tried two other cards. They give different specific results, but qualitatively the same - initialization, OCR, and CID read all work okay. Data read gives mostly zeroes followed by some reproducible but sparse bytes, and a 0xAA55 marker!?!
My SanDisk 1GB SD card is running at 3.296 volts which seems stable during card reading.
Here's some code:
bit MMC_Command(unsigned char cmd, unsigned short AdrH, unsigned short AdrL, unsigned char *response)
{
unsigned char response_length;
unsigned char MMC_Counter_Byte = 255;
unsigned char current_response;
switch (cmd)
{
case MMC_SEND_IF_COND:
case MMC_READ_OCR:
response_length = 5;
break;
case MMC_SEND_STATUS:
response_length = 2;
break;
default:
response_length = 1;
};
DEV_xSELECT = DEV_MMC;
SPI_Put_Char(cmd);
SPI_Put_Char(AdrH >> 8);
SPI_Put_Char(AdrH & 0x00FFU);
SPI_Put_Char(AdrL >> 8);
SPI_Put_Char(AdrL & 0x00FFU);
SPI_Put_Char(0x95U); //CRC = 0x95 to get to SPI, then value not important, so always use this for convenience
do
{
response[0] = SPI_Put_Char(0xFF);
} while ((response[0] & 0x80) && --MMC_Counter_Byte);
if (!MMC_Counter_Byte)
{
//SPI_Put_Char(0xFF); //some say is necessary
DEV_xSELECT = DEV_NONE;
return FALSE;
};
for (current_response = 1; current_response < response_length; current_response++)
{
response[current_response] = SPI_Put_Char(0xFF);
};
SPI_Put_Char(0xFF); //some say is necessary
DEV_xSELECT = DEV_NONE;
return TRUE;
};
unsigned char MMC_Init_SD(void)
{
unsigned long MMC_Counter_Word;
unsigned char response[5];
DEV_xSELECT = DEV_MMC;
for (MMC_Counter_Word = 0; MMC_Counter_Word < 20; MMC_Counter_Word++)
{
SPI_Put_Char(0xFFU);
};
DEV_xSELECT = DEV_NONE;
for (MMC_Counter_Word = 0; MMC_Counter_Word < 10; MMC_Counter_Word++)
{
SPI_Put_Char(0xFFU);
};
MMC_Counter_Word = 255;
do
{
MMC_Command(MMC_GO_IDLE_STATE, 0x0000, 0x0000, response); //cmd0
} while (--MMC_Counter_Word && (response[0] != 0x01));
if (!MMC_Counter_Word) //if counter timed out, error
{
return FALSE;
};
MMC_Command(MMC_SEND_IF_COND, 0x0000, 0x01AA, response); //cmd8
if (response[0] != 0x05)
{
return FALSE; //other card type
};
MMC_Command(MMC_READ_OCR, 0x0000, 0x0000, response); //cmd58
MMC_Counter_Word = 0xFFFFU;
do
{
if (MMC_Command(MMC_APP_CMD, 0x0000, 0x0000, response)) //cmd55
{
MMC_Command(MMC_APP_SEND_OP_COND, 0x4001, 0x0000, response); //acmd41
SPI_Put_Char(0xFF);
}
else
{
return FALSE;
};
} while (--MMC_Counter_Word && ((response[0] & 1) == 1));
if (!MMC_Counter_Word)
{
return FALSE;
};
if (MMC_Command(MMC_SEND_CID, 0x0000, 0x0000, response)) //cmd10
{
DEV_xSELECT = DEV_MMC;
MMC_Counter_Word = 255;
while (--MMC_Counter_Word && (SPI_Put_Char(0xFF) != 0xFE));
if (!MMC_Counter_Word)
{
DEV_xSELECT = DEV_NONE;
return FALSE;
};
//code for reading 16 byte OCR goes here
SPI_Put_Char(0xFFU);
SPI_Put_Char(0xFFU); //cycle through 16-bit CRC
SPI_Put_Char(0xFFU); //1GB Sandisk SD seems to require another dummy
DEV_xSELECT = DEV_NONE;
Delay_Sec(2);
LCD_CLS();
}
else
{
return FALSE;
};
return TRUE;
};
bit MMC_Fill_IO_Buffer(unsigned long sector)
{
unsigned short MMC_Fill_Index_Byte;
unsigned char MMC_Counter_Byte = 255;
unsigned char response[1];
if (MMC_Command(MMC_READ_SINGLE_BLOCK, 0x0000, 0x0000, response)) //cmd10
{
DEV_xSELECT = DEV_MMC;
MMC_Counter_Byte = 255;
while (--MMC_Counter_Byte && (SPI_Put_Char(0xFF) != 0xFE));
if (!MMC_Counter_Byte)
{
DEV_xSELECT = DEV_NONE;
return FALSE;
};
}
else
{
return FALSE;
};
for (MMC_Fill_Index_Byte = 0; MMC_Fill_Index_Byte < 512 ; MMC_Fill_Index_Byte++)
{
IO_Buffer[MMC_Fill_Index_Byte] = SPI_Put_Char(0xFF);
};
SPI_Put_Char(0xFFU);
SPI_Put_Char(0xFFU); //cycle through 16-bit CRC
SPI_Put_Char(0xFFU); //1GB Sandisk SD seems to require another dummy
DEV_xSELECT = DEV_NONE;
//following is IO_Buffer displaying code.
//LCD_CLS();
//for (MMC_Counter_Byte = 0; MMC_Counter_Byte < 42; MMC_Counter_Byte++)
//{
// LCD_Draw_Byte_Hex(IO_Buffer[MMC_Counter_Byte + 448]);
//};
//while (1);
return TRUE;
};
Thanks ahead of time!