SD SPI max speed

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

Hi everybody,

I'm having an issue when connecting to an SD card.
Everything works alright when SPI clock is 1MHz (core is ATMega644, system clock=16MHz).

But when I turn to SPI clock = 2MHz or higher the SD card won't even initialize, it won't pass even the first step in initialization.
Here I attach the code related to the SD card, it's compiled with WINAVR.

void	SPI_init()
{
	SPCR0 = 0;	//reseteamos por las dudas
	SPSR0 = 0;

	SPI_DDR |= (1<<SPI_MOSI_BIT) | (1<<SPI_SCK_BIT) | (1<<SPI_SS_BIT);	//mosi & sck outs, tb ss!
	
	clrbit( SPI_DDR, SPI_MISO_BIT);	//por las dudas IN
	
	clrbit( SPI_PORT, SPI_MISO_BIT);	// no pullups
	
	
	SPCR0 = (1<<SPE0) | (1<<MSTR0) | (1<<SPR00);
}

u08	SPI_tx( u08	data )
{
	SPDR0 = data;

	timer_t	tout = TIMER_get() + SPI_TIMEOUT_MS*TIMER_TICKSperms;

	while( !( SPSR0 & (1<<SPIF0)) )
	{
		if ( tout < TIMER_get() )
			return 0xff;	//error!
	}
	//esperamos
	
	return SPDR0;	//leemos
}

u08	SD_txCmd( u08 cmd, u32 arg )
{

	cmd |= 0x40;
	
	u08 crc = 0;
	crc = mmc_crc7(cmd, crc);
	crc = mmc_crc7( *(((u08*)&(arg))+3), crc);
	crc = mmc_crc7( *(((u08*)&(arg))+2), crc);
	crc = mmc_crc7( *(((u08*)&(arg))+1), crc);
	crc = mmc_crc7( *(((u08*)&(arg))+0), crc);
	
	crc = (crc<<1)|0x01;	//desplazar!

	SD_CS_OFF();
		SPI_tx(0xFF);
	SD_CS_ON();
	
 	SPI_tx( cmd );
	SPI_tx( arg >> 24);
	SPI_tx( arg >> 16);
	SPI_tx( arg >> 8);
	SPI_tx( arg );
	
	SPI_tx(  crc );	//solo para CMD =0!		OJO!!
	
	u08 retr = 100, rx;
	
	while ( (rx = SPI_tx( 0xFF )) == 0XFF )	//nada?
		if ( retr-- == 0)	break;
	
//	SD_CS_OFF();
	
	return	rx;
}

s08	SD_init()
{
	setbit( SD_CS_DDR, SD_CS_BIT );	//out
	
	u08 rx;
	
	SD_CS_OFF();
	
	u08	retries;
	
	retries = 10;
	do
	{
		DBGHERE("a");
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );		
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		SPI_tx( 0xFF );
		
		rx = SD_txCmd( MMC_GO_IDLE_STATE, 0 );
		//rx = SD_txCmd( MMC_GO_IDLE_STATE,MMC_SEND_OP_COND);
		DBGHERE("0");
		
		retries--;
		
	} while ( (rx != 0x01) && (retries > 0) );
	
	DBGHERE("1");
	
	if ( rx != 0x01 )
	{
		DISPLAY_int( (int) rx );
		return SD_ERROR_NOT_FOUND;	//err
	}
	
	DBGHERE("2");
	
	retries = 100;
	
	do
	{
		rx = SD_txCmd( MMC_SEND_OP_COND, 0);
		
		if ( retries-- == 0)
			return SD_ERROR_INIT;	//err
	} while( rx );
	DBGHERE("3");
	
	//block length = 512 bytes
	rx = SD_txCmd(MMC_SET_BLOCKLEN, 512);
	if ( rx == 0xFF )
		return SD_ERROR_BLOCKLEN;
	DBGHERE("4");

	#ifdef	SD_IGNORE_CSUM
		rx = SD_txCmd(MMC_CRC_ON_OFF, 0);	//off
	#else
		rx = SD_txCmd(MMC_CRC_ON_OFF, 1);		//turn ON CRC 
	#endif
	
	if ( rx == 0xFF )
		return SD_ERROR_OTHER;
	DBGHERE("5");
	SD_CS_OFF();	//chau

	return 1;
}

The TIMER_get() function is just an interrupt-driven counter, which ticks every 1msec.. so I use it for timeouts and avoid hanging the atmega.

When at SPI clk=1MHz the card will initialize fine.
When at higher clock rates, I could see it gets inside the IF just after DBGHERE("1");

Any help is appreciated..
I read that some SD cards support 400Khz and some others up to 20MHz clock, but I saw a lot of people using high clock rates (like 2MHz) with apparently no problem.

Thanks all,

Carlos

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

I'm not as familiar with SPI mode as regular mode, but in non-spi mode, the initialization phase must be done at <= 400kHz. After reading the CSD and determining that it's a high-speed card, only then can the frequency be upped to whatever maximum the card supports. The CSD block should contain a few bits that tell you how fast you can clock it.

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

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

What have you read about the SPI speed of the SD card you are actually using?

Clocked devices that are more complex than a simple hardware shift register may have issues with input metastability circuits limiting the maximum SPI speed in relation to the device clock. If it is internally sampling the SPI input with a clocked line, it will also have SPI speed limitations. The SD data sheet should answer your questions.

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

According to the CSD info, TRAN_SPEED is 50 decimal, which means that max clock speed is 10Mbit (taken from documentation).

I tried to switch to higher speeds after initializing and reading CSD, but still the same problem: it looks as if the SD is not responding.

any ideas?

Thanks

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

Can you provide a link to your SD card data sheet?

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

I used the one available at avrfreaks.net
http://www.cs.ucr.edu/~amitra/sd...

on page 3-15 it talks about TRAN_SPEED

thanks

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

50 decimal corresponds to 26MHz, but again, that's the data transfer speed in regular mode. Not sure if that's also the speed in SPI mode.

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

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

Oh yes, I forgot to multiply by 2.5

I don't know where to find the other limitation. The only thing I can think of is something wrong in the code, but it works for 1MHz with no trouble at all.

Well, I'll keep investigating..

thanks,

carlos

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

Can't seem to see from specs why it wouldn't work at 2MHz except that maybe it's expecting the init part to be at <=400kHz and is using some relaxed bus timing that still works at 1MHz but not at 2. Can you try running the bus at 400KHz (or at least <1MHz) through the init until you get right before a data transfer and then increase to 2MHz and see if you can still do the reads correctly?

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

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

That's what I did an hour ago.
After initializing at 1MHz (the SD works as spected) and asking for CSD, I change to 2MHz and try to do a sector read.. but that doesn't succeed. It does if I keep it at 1MHz all the time.

I don't know what else to try.

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

Hmm... short of putting a scope on it and looking at the signals, I'm not sure why it's not working.

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

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

To change to 2MHz, you're just setting the SPI2X bit in SPSR, right?

Have you tried other frequencies? 4MHz for example. Just to see if it's something problematic with 2MHz.

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

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

I tried with 2, 4 and 8MHz, the same behaviour.
I tried setting the SPI2X bit and also setting different prescaling bits, and still the same.

Unfortunately I don't have an oscilloscope nor a logic analyzer to test it :(

Thanks again,

carlos

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

I'm confused. When asked about running 400 KHz or slower initialization you said you did, but went on to describe initializing at 1 MHz. You would have to initialize with a divide by 64 (250 KHz clock) which is as close to 400 KHz as you can get. After the initialization is when you turn SCK back up. Anyway, you only need to do this if you also want to use Multimedia Cards.

It is a complex interface and you appear to not be following all the rules. I gave up trying to decode the data sheet interface specification because it just keeps getting deeper and deeper. I see where it appears you shut off the chip select and send 8 clocks before turning on the chip select and sending the command. Are you sure you want to wait to do it just before sending a new command (or is this a safety feature)? Those last 8 clock cycles are for the last operation to complete. Are you ever checking for a busy SD card? As far as I can tell you never read the OCR bits or the CSD register TAAC, NSAC and R2W_factor or do anything about the timeout values. Admittedly, you are not using allot of the general purpose SD card compatibility, so you can get away with a selective interface. Still, some of the missing stuff might be causing trouble. Someone that knows this interface better than I do will have to figure that out.

I found this AVR SD card library link with Google:
http://hubbard.engr.scu.edu/avr/...
There must be more AVR SD card software in the 250000 Google hits.

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

take a look at:
http://www.embedded-os.de/index.html?pcfat_port.htm

This code describes the setup of the SPI-speed after reading the CID & CSD from the MMC/SD-cards for some boards.

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

thanks to everyone. I'll see all the links, if I get something working I will post it here

thanks again!

Carlos

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

I'm only a newbie and don't even fully understand AVR assembler but according to http://elm-chan.org/docs/mmc/mmc... MMC cards (which SD cards are very similar to) have to be given at least a millisecond to power on before you even start the SPI clock. They then need to be given at least 74 clock pulses before they become active.

It could be possible at 1MHz you retry for a long enough period for one to succeed but not at 2MHz. Again, I know little about this but this problem would make sense if there are some required delays you're not implementing.

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

I'm leaving about 100ms for card to start up.

I'm still looking for the problem. It's not a critical issue, since I can live with 1MHz, but I would like to make it faster in case I need it for other applications.

Thanks once again,

carlos

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

I am still confused if you are trying to initialize card at 1MHz or less than 400kHz.

I mean, you really should initialize the card with less than 400kHz, if you are not doing that already.

- Jani

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

I'm initializing the card at 250kHz now,
and then, if I switch to 1Mhz, everything works fine.
When switching to 2Mhz or higher, card doesn't respond to commands.

Even sending several 0xFF after speed switching and after and before chip select enable, this

rx = SD_txCmd(MMC_READ_SINGLE_BLOCK, sector<<9);

would return 0xFF all the time.. as If the card isn't getting the command.
Again, it does work with 1Mhz.

here is txCmd:

u08	SD_txCmd( u08 cmd, u32 arg )
{
	unsigned char i;
	
	cmd |= 0x40;
	
	u08 crc = 0;
	crc = mmc_crc7(cmd, crc);
	crc = mmc_crc7( *(((u08*)&(arg))+3), crc);
	crc = mmc_crc7( *(((u08*)&(arg))+2), crc);
	crc = mmc_crc7( *(((u08*)&(arg))+1), crc);
	crc = mmc_crc7( *(((u08*)&(arg))+0), crc);
	
	crc = (crc<<1)|0x01;	//desplazar!

	SD_CS_OFF();
		for (i=0; i < 100; i++)
			SPI_tx(0xFF);
	SD_CS_ON();
		for (i=0; i < 100; i++)
				SPI_tx(0xFF);
		
		
	
 	SPI_tx( cmd );
	SPI_tx( arg >> 24);
	SPI_tx( arg >> 16);
	SPI_tx( arg >> 8);
	SPI_tx( arg );
	
	SPI_tx(  crc );	//solo para CMD =0!		OJO!!
	
	u08 retr = 100, rx;
	
	while ( (rx = SPI_tx( 0xFF )) == 0XFF )	//nada?
		if ( retr-- == 0)	break;
	
	
//	SD_CS_OFF();
	
	return	rx;
}

Again, I'm confused.

Thanks again to everyone for the interest in solving this!

Carlos

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

Is it possible that because you're going at double the speed, it's taking less time to transfer the command, the card has less time to respond and it's using up the 100 retry times just before getting a response? Looks like the timeout is based on transmission speed, as it's just 100 cycles.

Can you up that retr=100 to retr=1000 or something much larger and see if you get a response if you haven't already?

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

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

After leaving the project away for some time, I returned today trying to make it work again..
well, the problem is still there.. even with really big timeouts (8 seconds for instance!) it won't work.

It's still quite confusing... if I happen to find something new I'll let you know.

thanks to all,

Carlos

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

How is the card connected? 16 MHz AVR suggest it being at 5 volt. If you are using a resistive divider to interface with the card it is possible the lowpass filtering of the R with any stray/input capacitance might case it to fail at higher speeds.

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

CountZero,
yes, I'm powering the uP with 5V and using a R/R divisor to adapt voltages.
I thought of the stray capacitance problem, but since it was working alright at 1MHz I thought 2MHz wouldn't be such a problem then.. but who knows, I don't have experience on this.. so it could be that.

Maybe I should try adding some buffers. Any suggestions?

thanks!

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

Without a scope you're basically working in the dark. What resistor values did you use?

I would use buffers that translate 5V to 3V3. Like a few 74LVC08 gates that have 5V tolerant inputs. The AVR sees 3V as high, so that shouldn't be a problem; depending on the minimum spec of the minimun high voltage of the SD card maybe you should insert a buffer for that signal too.

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

I will try that IC, and get a scope soon!! I hope that solves the matter.

thanks!

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

If there is no possibility to use the AVR at the same voltage as the SD card runs (2.7 to 3.6 volts, and therefore you would propably need the L version of the AVR and then the maximum AVR frequency would be 8MHz), and you really put some level translators there for converting 5V to 3.3, you might want to get for example 74HCT08 to buffer the 3.3V signals to 5V signals for the AVR.

Although AVR at 5V supply will understand 3.3V as logic 1, but still this is not nice.

- Jani

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

quote from datasheet:
• A command/response sequence. Eight clocks after the card response end bit. The
CS signal can be asserted or de-asserted during these eight clocks.
• A read data transaction; eight clocks after the end bit of the last data block.
• A write data transaction; eight clocks after the CRC status token.