I'm working on an SPI SD driver for an LPC4088 microcontroller. However, when I send CMD8
(after CMD0
) to detect if I'm working with a V2 or high capacity card, I get a weird response. Instead of getting a correct response( 0x01
for highest bits, 0x1AA
for the lower 12) or an error I get 0x00 00 00 02 1F
, which doesn't make any sense to me at all.
Code I use for initialization:
bool initialize () {
//0. Initialize SPI
SPI::init();
//1. Set clock to 400kHz
SPI::set_clock(400000);
//2. Assert CS signal (=0)
assert_cs();
// 3. Delay at least 74 clocks
delay8(10);
// 4. Deassert CS signal
deassert_cs();
// 5. Delay at least 16 clocks
delay8(2);
uint8_t argument[4];
reset_argument(argument);
// 6. Send CMD0 (reset, go to idle)
if (!send_command(CMD::GO_IDLE_STATE, CMD_RESPONSE_SIZE::GO_IDLE_STATE, response, argument)) {
return false;
}
// 7. Send CMD8
bool version2;
reset_argument(argument);
pack_argument(argument, 0x1AA);
if (!send_command(CMD::SEND_IF_COND, CMD_RESPONSE_SIZE::SEND_IF_COND, response, argument)) {
return false;
}
if ((response[0] & 0xFE) == 0x04) {
//unknown command. This means we have version1
version2 = false;
} else if (response[0] & 0xFE) {
//other error, let's bail
return false;
} else {
//Response, we're version2
version2 = true;
if (response[4] != 0xAA) {
return false;
}
}
//....
}
send_command code:
bool send_command(CMD::value cmd, uint8_t response_size, uint8_t *response, uint8_t *argument) {
assert_cs();
Crc7_SD crc;
crc += cmd | 0x40;
crc += argument[3] & 0xFF;
crc += argument[2] & 0xFF;
crc += argument[1] & 0xFF;
crc += argument[0] & 0xFF;
SPI::send(cmd | 0x40);
SPI::send(argument[3] & 0xFF);
SPI::send(argument[2] & 0xFF);
SPI::send(argument[1] & 0xFF);
SPI::send(argument[0] & 0xFF);
SPI::send((crc << 1) | 1);
volatile uint8_t data;
{
unsigned int timeout = SD_CMD_TIMEOUT;
do {
data = SPI::receive();
--timeout;
} while(timeout && (data & 0x80));
if (timeout == 0) {
deassert_cs();
return false;
}
}
for (int i = 0; i < response_size; i++) {
//First byte is already read above
if (response) {
response[i] = data;
}
data = SPI::receive();
}
deassert_cs();
return true;
}
To make sure that I didn't had an error in the SPI protocol I've verified the input and output with a logic analyzer. Result: CMD0 followed by CMD8. It seems that I'm sending the correct commands, but still I get this weird response.
Additional info about the setup:
Microcontroller is an LPC4088
Microcontroller is connected with this OEM board
The SD card module is connected to the serial expansion connector of the OEM board
The logic analyzer is connected to the SD card module
I've used 2 different versions of both the microcontroller and the OEM board to rule out that there is a hardware error in one of those. Unfortunately I don't have a second SD controller available.
I've used a SanDisk Ultra SDHC 4GB Class 6 SD card and a Transcend SDHC 4GB Class 4 SD card, both gave exactly the same result.
And last but not least, I have very little experience with embedded software, so it might just be some small stupid error.