SdFat and 20MHz clock

Hi All...

I am running SdFat on my 1284P clocked at 20MHz and most of the time, all works fine. Not all of the time though. The SD card is interfaced with a STMicroelectronics 74AC125MTR and is driven by a 3V regulator good to 400mA, so I think the hardware is fine.

If I set it to SPI_HALF_SPEED it is reliable, and it is reliable at full speed on my 16MHz board. I can hack the library so that "SPI_FULL_SPEED" is based upon 16,000,000 instead of 20,000,000 and I expect that will solve the issue, but before I go down that route I thought I would solicit other ideas.


SdFat does not check the clock speed. The only assumption is that millis() works correctly.

SPI_FULL_SPEED sets the SPI clock divider to 1/2 so the SPI clock speed in your case is F_CPU/2 or 10 MHz.

You can't hack software to get the equivalent of a 16 MHz board since the the hardware SPI clock divisors are powers of two.



How does it fail?

If it fails in the init() call try changing SPI_SD_INIT_RATE to 6 in SdFatConfig.h

 * SPI init rate for SD initialization commands. Must be 5 (F_CPU/64)
 * or 6 (F_CPU/128).
#define SPI_SD_INIT_RATE 5

fat16lib: SdFat does not check the clock speed. The only assumption is that millis() works correctly.

millis() will not quite work at 20 MHz. Microseconds per timer0 overflow (819.2) is not divisible by 8 so it's going to count 816 microseconds for each overflow. The timer will be slow almost 4 milliseconds every second.

micros() will be off by more because 64 is not evenly divisible by 20. I think it will be slow by 66 milliseconds per second.

delay() uses micros() so it will be off the same amount.

(See: wiring.h and wiring.c in the Arduino core)

Slow will be fine.

I use millis() to avoid a hang for some operations.

I add a generous amount to the timeout spec so even a bit fast should be O.K.

Actually I don't think my problems are related to SdFat now that I have done more testing. I'm not sure what is going on. Basically, I can, most of the time, run the bench sample sketch and I even see a nice performance boost over my 16 MHz board. Sometimes, though, the constructor fails to initialize and gives the standard error about not finding a card or whatever.

Yes, millis and delay don't work correctly on my 20MHz board. I expected that and coded around it. I also changed HardwareSerial.cpp to handle baud rate calculation correctly for the two onboard UARTs.

There may be a hardware problem with this board. It worked fine at 16MHz but perhaps when I changed the crystal I screwed something up.

Overall I have had so many problems with 20MHz that I am thinking its just not worth the effort. A shame really, a 20% performance would be nice to have. Maybe over the winter I'll rewrite me app in AVR Studio, but then I lose quite a bit of library support.

My thanks to everyone who replied!

You should try setting SPI_SD_INIT_RATE to 6.

SD cards initialize at a very slow speed, in the range 100 - 400 kHz.

At F_CPU = 20 MHz and a divider of 64 the SPI clock is 312.5 kHz so it should be O.K. but some cards are fussy.

Try the slower init rate.

SPI_SD_INIT_RATE = 6 will initialize at 156.25 kHz.

The clock rate is set to high speed if initialization is successful.

Oh okay, thanks! I’ll try that.