Using USE_SOFTWARE_SPI mode on SdFat

Hello,

I'm trying to use USE_SOFTWARE_SPI mode in the SdFat library. I had gotten the SD card to work just fine using the Arduino Due's SPI lines, but ran into some trouble running both the SD card and another device (FLASH memory) on the same SPI bus. I realize that SPI using digital pins will be slower, but I thought I'd give it a shot.

But... sadly it isn't working. I'm getting the error:

use software spi: 1
Can't access SD card. Do not reformat.
No card, wrong chip select pin, or SPI problem?
SD errorCode: 0X1,0XFF

I followed these instructions:

Define MEGA_SOFT_SPI to be non-zero in SdFatConfig.h to use software SPI
on Mega Arduinos. Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.

I've hooked up my SD card module as follows:

SD card => Arduino

CS => pin 10
DI => pin 11
DO => pin 12
CLK => pin 13

My code is a slightly modified version of the read/write sample code:

#include <SdFat.h>
SdFat sd;
SdFile myFile;

void setup() 
{
	pinMode(10, OUTPUT);
	pinMode(11, OUTPUT);
	pinMode(12, OUTPUT);
	pinMode(13, OUTPUT);

	Serial.begin(9600);
	//while (!Serial) {} // wait for Leonardo
	// Serial.println("Type any character to start");
	// while (Serial.read() <= 0) {}
	delay(400); // catch Due reset problem

	Serial.print("use software spi: ");
	Serial.println(USE_SOFTWARE_SPI);

	// Initialize SdFat or print a detailed error message and halt
	// Use half speed like the native library.
	// change to SPI_FULL_SPEED for more performance.
	if (!sd.begin(10, SPI_EIGHTH_SPEED)) sd.initErrorHalt();
	// open the file for write at end like the Native SD library
	if (!myFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END)) {
	sd.errorHalt("opening test.txt for write failed");
	}
	// if the file opened okay, write to it:
	Serial.print("Writing to test.txt...");
	myFile.println("testing 1, 2, 3.");
	// close the file:
	myFile.close();
	Serial.println("done.");

	// re-open the file for reading:
	if (!myFile.open("test.txt", O_READ)) 
	{
		sd.errorHalt("opening test.txt for read failed");
	}
	Serial.println("test.txt:");
	
	// read from the file until there's nothing else in it:
	int data;
	while ((data = myFile.read()) >= 0) Serial.write(data);

	// close the file:
	myFile.close();
}
void loop() {
// nothing happens after setup
}

Any suggestions?

Thanks,
Bret

By the way, I removed the following lines, but still no luck:

pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);

Any assistance would be much appreciated.

Bret

Quote
Define MEGA_SOFT_SPI to be non-zero in SdFatConfig.h to use software SPI
on Mega Arduinos. Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.

This only works on a Mega board, not a Due.

There is a beta version of SdFat that supports software SPI on Due GitHub - greiman/SdFat-beta: Beta SdFat for test of new features.

Note that software SPI ignores the SPI_EIGHTH_SPEED parameter in begin() since software SPI is at a slow fixed rate.
if (!sd.begin(10, SPI_EIGHTH_SPEED)) sd.initErrorHalt();

Edit SdFatConfig.h at about line 160 and change the value of DUE_SOFT_SPI.

//------------------------------------------------------------------------------
/**
 * Define DUE_SOFT_SPI nonzero to use software SPI on Due Arduinos.
 */
#define DUE_SOFT_SPI 0

Here is a comparison of hardware SPI and software SPI on Due. This is the bench example on a high end microSDHC card with 100 byte reads and writes.

Hardware SPI:

File size 5 MB
Buffer size 100 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
444.64,7128,6,223

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
1469.29,606,6,66

Software SPI

File size 5 MB
Buffer size 100 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
203.67,13384,6,489

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
404.69,2437,5,245

Note that the Due has more hardware SPI channels by using the USART in SPI mode. I believe it can be configured with up to a 14 MHz clock. Looks rather easy to setup and use ... its unfortunate there isn't many (if any) examples using this. Probably because the code would not be portable (would only work on the Due), but its a bit of a shame to see the unused features of the USART sit there dormant.

Table 36-1. SPI Operating Mode

PIN   USART  SPI Slave  SPI Master
RXD   RXD    MOSI       MISO
TXD   TXD    MISO       MOSI
RTS   RTS    –          CS
CTS   CTS    CS         –

Using a USART in SPI mode can be useful for small transfers to a device like an DAC, ADC or a SPI sensor. I have used the serial ports on AVR boards to avoid conflicts with the single SPI controller when I need SPI in an interrupt routine.

I don't plan on supporting SPI mode USARTs in SdFat. I use DMA SPI or the standard SPI library on Due.

Another shame is that a powerful chip like the SAM3X8E has only one SPI controller. I use a lot of other Cortex M chips and most have several SPI controllers. STM32 chips have up to four SPI controllers in 100 pin packages.

fat16lib:
I don't plan on supporting SPI mode USARTs in SdFat. I use DMA SPI or the standard SPI library on Due.

I haven't tried your library as yet but I do follow anything SPI related with interest. Your work and test results with DMA SPI is quite interesting. I've noticed that Arduino 1.58 BETA has added transaction API (Paul Stoffregen). I think if used, this could resolve some problems when multiple devices are using the same SPI controller.

I've noticed that Arduino 1.58 BETA has added transaction API (Paul Stoffregen). I think if used, this could resolve some problems when multiple devices are using the same SPI controller.

I added support for Paul's SPI transactions to SdFat. I personally don't like SPI transactions. You can't reliably breakup the 512 byte transfer for an SD card. This means you get huge latency in an ISR that needs SPI. The idea just isn't general enough and is poorly implemented.

If Due had allowed use of the SDIO controller, SD would not be a problem. I have a more advanced FAT library running on STM32. I can get SD read/write rates over 30 MB/sec with 4-bit SDIO on STM32.

I added software SPI to SdFat for Due and Teensy users who couldn't use Paul's SPI transactions to solve their SPI sharing problems.