SD CMD17 giving no R1 Response

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

I am currently working with an ATXMEGA256A3B trying to interface with a Micro-SDHC card (4GB). Firstly, it seems that everything is working fine for the most part, the card will initialize properly, will write to sectors without problem (even when pumped up to 16MHz clock) and will even properly return CSD when CMD9 is executed. However, for some reason when CMD17 is given there is simply no response, the card ignores the fact that any command was sent at all.

I have spent a decent time browsing the web attempting to identify this problem, however it seems most issues have been with the card not sending the start token (0xFE) and the following data. However I am not getting an initial R1 response when I send CMD17 rather the card is simply appearing to echo back my 0xFF (the end byte for my CMD17 check out code below).

I was wondering if anyone has any ideas on this problem, I am beginning to think that perhaps the card is simply damaged, and needs to be replaced.

Here is the code segments for different functional calls, the "USB_xxx" commands are just a utility to output stuff from the card to Realterm.

Read Block function:

uint8_t SD_read_block(uint32_t addr, uint8_t * buf, uint16_t size)
{	
	uint8_t response;
	uint16_t i;
	uint16_t crc;
	
	// CMD17 with no CRC required
	uint8_t CMD_17_READ_BLOCK[6] = {17, 0x00, 0x00, 0x00, 0x00, 0xFF};
	CMD_17_READ_BLOCK[1] = (addr >> 24);
	CMD_17_READ_BLOCK[2] = (addr >> 16) & 0xff;
	CMD_17_READ_BLOCK[3] = (addr >> 8) & 0xff;
	CMD_17_READ_BLOCK[4] = addr & 0xff;

	/* Outputting address for debugging */
	USB_put_array((uint8_t*)"ADDRESS: ", 9); 
	USB_write_ascii_byte((addr >> 24));
	USB_write_ascii_byte((addr >> 16) & 0xFF);
	USB_write_ascii_byte((addr >> 8) & 0xFF);
	USB_write_ascii_byte((addr) & 0xFF);
	USB_put_array((uint8_t*)"\r\n", 2);

	// Enable the card
	SD_ENABLE( );
	
	// Send the read command
	response = SD_send_command(CMD_17_READ_BLOCK);
	
	// If there are any problems, return an error
	if (response)
	{
		SD_DISABLE( );
		switch(response){
		case (1 << 0): USB_put_array((uint8_t*)"ERR: IN IDLE\r\n", 14); break;
		case (1 << 1): USB_put_array((uint8_t*)"ERR: ERASE RST\r\n", 15); break;
		case (1 << 2): USB_put_array((uint8_t*)"ERR: ILLEGAL\r\n", 14); break;
		case (1 << 3): USB_put_array((uint8_t*)"ERR: COM CRC\r\n", 14); break;
		case (1 << 4): USB_put_array((uint8_t*)"ERR: ERASE SEQ\r\n", 15); break;
		case (1 << 5): USB_put_array((uint8_t*)"ERR: ADDRESS\r\n", 14); break;
		case (1 << 6): USB_put_array((uint8_t*)"ERR: PARAMETER\r\n", 15); break;
		default: USB_write_ascii_byte(response);
		}
		return 2;
	}
	
	// Wait for the start token
	i = 0;
	do
	{
		response = SPI_MasterTransceiveByte(&spiMasterD, 0xFF);
		__no_operation( );
	} while (response != START_TOKEN && i++ < SD_MAX_TRIES);
	
	// If no start token was received by now, it probably won't be showing
	// up, so return an error.
	if (i >= SD_MAX_TRIES)
	{
		SD_DISABLE( );
		return 1;	
	}
	
	// Read the data from the card
	for (i = 0; i < SD_BLOCK_SIZE; ++i)
	{
		USB_put_array((uint8_t*)"RECEIVING...\r\n", 14);
		if (i < size)
		{
			buf[i] = SPI_MasterTransceiveByte(&spiMasterD, 0xFF);
		}
		else
		{
			SPI_MasterTransceiveByte(&spiMasterD, 0xFF);
		}
	}
	
	// Get the CRC
	crc = (SPI_MasterTransceiveByte(&spiMasterD, 0xFF) << 8);
	crc |= SPI_MasterTransceiveByte(&spiMasterD, 0xFF);
	
	// Give the card a few cycles to finish internal operations
	for (i = 0; i < 10; ++i)
	{
		SPI_MasterTransceiveByte(&spiMasterD, 0xFF);
	}
	
	// Disable the card
	SD_DISABLE( );
	
	// Return success
	return 0;
}

Send Command Function:

uint8_t SD_send_command(uint8_t cmd[])
{
	uint8_t i;
	uint8_t response;
	
	// Set framing bits
	cmd[0] = (cmd[0] & ~START_BIT) | TRAN_BIT;
	cmd[5] |= END_BIT;
	
	// Send the command
	for (i = 0; i < 6; ++i)
	{
		SPI_MasterTransceiveByte(&spiMasterD, cmd[i]);
	}
	
	// Get the response
	i = 0;
	while (1)
	{
		response = SPI_MasterTransceiveByte(&spiMasterD, 0xFF);
		
		// If the response has a 0 in the MSB, then this is a valid response
		if ((response & START_BIT) == 0)
		{
			return response;	
		}
		
		// Otherwise, increment the number of tries, i.  If too many failures
		// have occurred, then return the response, which will have the MSB
		// set to 1, indicating an invalid response
		else if (i++ > SD_MAX_TRIES)
		{
			return response;
		}
	}	
}

I have checked the addressing and it is working out just fine, the uint32_t is keeping the address values so they aren't getting corrupted.

If you would like me to post the get_CSD function or the write_block functions (both of which are working) I will, any information will be wonderfully helpful.

Thanks in advance,

Josh.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Google for FATFS and go to the site. Download latest ver. and setup using the tutorial for it avrfreaks tut. section. I've used it for my xmega16A4 mp3 pjt. It has a UART console app too, which is easy enough to take out. I suggest that since FATFS works, just use it .

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the reply,

Unfortunately for the project I am working on we are trying to avoid using a file-system, as the 16 MHz limit on data transfer is barely cutting it for us. The added overhead for FAT would most likely put us over. The code right now of course is for testing and isn't really cleaned up for speed.

- Josh

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think the point was that FATFS must still have SD card code to work, so you can use that part and forget the use of filesystem.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It might be worth it to compare FATFS implementation of cmd17 and see if there are differences.
Try a different card, maybe < 4GB ( if they use cmd17 ) . Did you double check that your coding of cmd17 is correct ?

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Alright will certainly check it out, thank you.

Although I have checked over the functionality of CMD17 with the physical layer documentation specs for Ver 2.00 which covers the SDHC cards. The main notable difference between HC/SC is the initialization protocol and indicating that the host knows that it is a high capacity card. That initialization works perfectly, its the read_block that seems to be behaving strangely.

I will take a look at the FATFS code and see if there is any notable differences with the read block functions they use.

- Josh

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

CMD17 appears to be correct, however even if it weren't I would expect an R1 response of "Illegal Command" etc, rather than just nothing at all.

Looking at the FATFS code for a PIC I do notice one difference, their function to read a block will first poll the SD to make sure it is echoing back their values to ensure the card is ready for command reception. I will try this out and see if it helps, although if I don't seem to need this wait before writing/reading registers etc I don't see why I would need it now, but who knows.

Hopefully this works out,

- Josh