Backported SD library from 1.5.x

This commit is contained in:
Cristian Maglie 2014-10-15 11:53:19 +02:00
parent b9b0fcdadc
commit 37115d03ef
15 changed files with 212 additions and 107 deletions

View File

@ -550,9 +550,9 @@ boolean SDClass::mkdir(char *filepath) {
boolean SDClass::rmdir(char *filepath) { boolean SDClass::rmdir(char *filepath) {
/* /*
Makes a single directory or a heirarchy of directories. Remove a single directory or a heirarchy of directories.
A rough equivalent to `mkdir -p`. A rough equivalent to `rm -rf`.
*/ */
return walkPath(filepath, root, callback_rmdir); return walkPath(filepath, root, callback_rmdir);

View File

@ -1,25 +1,26 @@
/* /*
SD card test SD card test
This example shows how use the utility libraries on which the' This example shows how use the utility libraries on which the'
SD library is based in order to get info about your SD card. SD library is based in order to get info about your SD card.
Very useful for testing a card when you're not sure whether its working or not. Very useful for testing a card when you're not sure whether its working or not.
The circuit: The circuit:
* SD card attached to SPI bus as follows: * SD card attached to SPI bus as follows:
** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
** CS - depends on your SD card shield or module. ** CS - depends on your SD card shield or module.
Pin 4 used here for consistency with other Arduino examples Pin 4 used here for consistency with other Arduino examples
created 28 Mar 2011 created 28 Mar 2011
by Limor Fried by Limor Fried
modified 9 Apr 2012 modified 9 Apr 2012
by Tom Igoe by Tom Igoe
*/ */
// include the SD library: // include the SD library:
#include <SPI.h>
#include <SD.h> #include <SD.h>
// set up variables using the SD utility library functions: // set up variables using the SD utility library functions:
@ -31,22 +32,22 @@ SdFile root;
// Arduino Ethernet shield: pin 4 // Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10 // Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8 // Sparkfun SD shield: pin 8
const int chipSelect = 4; const int chipSelect = 4;
void setup() void setup()
{ {
// Open serial communications and wait for port to open: // Open serial communications and wait for port to open:
Serial.begin(9600); Serial.begin(9600);
while (!Serial) { while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only ; // wait for serial port to connect. Needed for Leonardo only
} }
Serial.print("\nInitializing SD card..."); Serial.print("\nInitializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default. // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin // Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output // (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work. // or the SD library functions will not work.
pinMode(10, OUTPUT); // change this to 53 on a mega pinMode(10, OUTPUT); // change this to 53 on a mega
@ -59,12 +60,12 @@ void setup()
Serial.println("* did you change the chipSelect pin to match your shield or module?"); Serial.println("* did you change the chipSelect pin to match your shield or module?");
return; return;
} else { } else {
Serial.println("Wiring is correct and a card is present."); Serial.println("Wiring is correct and a card is present.");
} }
// print the type of card // print the type of card
Serial.print("\nCard type: "); Serial.print("\nCard type: ");
switch(card.type()) { switch (card.type()) {
case SD_CARD_TYPE_SD1: case SD_CARD_TYPE_SD1:
Serial.println("SD1"); Serial.println("SD1");
break; break;
@ -90,7 +91,7 @@ void setup()
Serial.print("\nVolume type is FAT"); Serial.print("\nVolume type is FAT");
Serial.println(volume.fatType(), DEC); Serial.println(volume.fatType(), DEC);
Serial.println(); Serial.println();
volumesize = volume.blocksPerCluster(); // clusters are collections of blocks volumesize = volume.blocksPerCluster(); // clusters are collections of blocks
volumesize *= volume.clusterCount(); // we'll have a lot of clusters volumesize *= volume.clusterCount(); // we'll have a lot of clusters
volumesize *= 512; // SD card blocks are always 512 bytes volumesize *= 512; // SD card blocks are always 512 bytes
@ -103,15 +104,15 @@ void setup()
volumesize /= 1024; volumesize /= 1024;
Serial.println(volumesize); Serial.println(volumesize);
Serial.println("\nFiles found on the card (name, date and size in bytes): "); Serial.println("\nFiles found on the card (name, date and size in bytes): ");
root.openRoot(volume); root.openRoot(volume);
// list all files in the card with date and size // list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE); root.ls(LS_R | LS_DATE | LS_SIZE);
} }
void loop(void) { void loop(void) {
} }

View File

@ -1,9 +1,9 @@
/* /*
SD card datalogger SD card datalogger
This example shows how to log data from three analog sensors This example shows how to log data from three analog sensors
to an SD card using the SD library. to an SD card using the SD library.
The circuit: The circuit:
* analog sensors on analog ins 0, 1, and 2 * analog sensors on analog ins 0, 1, and 2
* SD card attached to SPI bus as follows: * SD card attached to SPI bus as follows:
@ -11,15 +11,16 @@
** MISO - pin 12 ** MISO - pin 12
** CLK - pin 13 ** CLK - pin 13
** CS - pin 4 ** CS - pin 4
created 24 Nov 2010 created 24 Nov 2010
modified 9 Apr 2012 modified 9 Apr 2012
by Tom Igoe by Tom Igoe
This example code is in the public domain. This example code is in the public domain.
*/ */
#include <SPI.h>
#include <SD.h> #include <SD.h>
// On the Ethernet Shield, CS is pin 4. Note that even if it's not // On the Ethernet Shield, CS is pin 4. Note that even if it's not
@ -30,9 +31,9 @@ const int chipSelect = 4;
void setup() void setup()
{ {
// Open serial communications and wait for port to open: // Open serial communications and wait for port to open:
Serial.begin(9600); Serial.begin(9600);
while (!Serial) { while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only ; // wait for serial port to connect. Needed for Leonardo only
} }
@ -41,7 +42,7 @@ void setup()
// make sure that the default chip select pin is set to // make sure that the default chip select pin is set to
// output, even if you don't use it: // output, even if you don't use it:
pinMode(10, OUTPUT); pinMode(10, OUTPUT);
// see if the card is present and can be initialized: // see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) { if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present"); Serial.println("Card failed, or not present");
@ -61,7 +62,7 @@ void loop()
int sensor = analogRead(analogPin); int sensor = analogRead(analogPin);
dataString += String(sensor); dataString += String(sensor);
if (analogPin < 2) { if (analogPin < 2) {
dataString += ","; dataString += ",";
} }
} }
@ -75,11 +76,11 @@ void loop()
dataFile.close(); dataFile.close();
// print to the serial port too: // print to the serial port too:
Serial.println(dataString); Serial.println(dataString);
} }
// if the file isn't open, pop up an error: // if the file isn't open, pop up an error:
else { else {
Serial.println("error opening datalog.txt"); Serial.println("error opening datalog.txt");
} }
} }

View File

@ -1,25 +1,26 @@
/* /*
SD card file dump SD card file dump
This example shows how to read a file from the SD card using the This example shows how to read a file from the SD card using the
SD library and send it over the serial port. SD library and send it over the serial port.
The circuit: The circuit:
* SD card attached to SPI bus as follows: * SD card attached to SPI bus as follows:
** MOSI - pin 11 ** MOSI - pin 11
** MISO - pin 12 ** MISO - pin 12
** CLK - pin 13 ** CLK - pin 13
** CS - pin 4 ** CS - pin 4
created 22 December 2010 created 22 December 2010
by Limor Fried by Limor Fried
modified 9 Apr 2012 modified 9 Apr 2012
by Tom Igoe by Tom Igoe
This example code is in the public domain. This example code is in the public domain.
*/ */
#include <SPI.h>
#include <SD.h> #include <SD.h>
// On the Ethernet Shield, CS is pin 4. Note that even if it's not // On the Ethernet Shield, CS is pin 4. Note that even if it's not
@ -30,9 +31,9 @@ const int chipSelect = 4;
void setup() void setup()
{ {
// Open serial communications and wait for port to open: // Open serial communications and wait for port to open:
Serial.begin(9600); Serial.begin(9600);
while (!Serial) { while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only ; // wait for serial port to connect. Needed for Leonardo only
} }
@ -41,7 +42,7 @@ void setup()
// make sure that the default chip select pin is set to // make sure that the default chip select pin is set to
// output, even if you don't use it: // output, even if you don't use it:
pinMode(10, OUTPUT); pinMode(10, OUTPUT);
// see if the card is present and can be initialized: // see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) { if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present"); Serial.println("Card failed, or not present");
@ -49,7 +50,7 @@ void setup()
return; return;
} }
Serial.println("card initialized."); Serial.println("card initialized.");
// open the file. note that only one file can be open at a time, // open the file. note that only one file can be open at a time,
// so you have to close this one before opening another. // so you have to close this one before opening another.
File dataFile = SD.open("datalog.txt"); File dataFile = SD.open("datalog.txt");
@ -60,11 +61,11 @@ void setup()
Serial.write(dataFile.read()); Serial.write(dataFile.read());
} }
dataFile.close(); dataFile.close();
} }
// if the file isn't open, pop up an error: // if the file isn't open, pop up an error:
else { else {
Serial.println("error opening datalog.txt"); Serial.println("error opening datalog.txt");
} }
} }
void loop() void loop()

View File

@ -1,40 +1,41 @@
/* /*
SD card basic file example SD card basic file example
This example shows how to create and destroy an SD card file This example shows how to create and destroy an SD card file
The circuit: The circuit:
* SD card attached to SPI bus as follows: * SD card attached to SPI bus as follows:
** MOSI - pin 11 ** MOSI - pin 11
** MISO - pin 12 ** MISO - pin 12
** CLK - pin 13 ** CLK - pin 13
** CS - pin 4 ** CS - pin 4
created Nov 2010 created Nov 2010
by David A. Mellis by David A. Mellis
modified 9 Apr 2012 modified 9 Apr 2012
by Tom Igoe by Tom Igoe
This example code is in the public domain. This example code is in the public domain.
*/ */
#include <SPI.h>
#include <SD.h> #include <SD.h>
File myFile; File myFile;
void setup() void setup()
{ {
// Open serial communications and wait for port to open: // Open serial communications and wait for port to open:
Serial.begin(9600); Serial.begin(9600);
while (!Serial) { while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only ; // wait for serial port to connect. Needed for Leonardo only
} }
Serial.print("Initializing SD card..."); Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default. // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin // Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output // (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work. // or the SD library functions will not work.
pinMode(10, OUTPUT); pinMode(10, OUTPUT);
if (!SD.begin(4)) { if (!SD.begin(4)) {
@ -55,23 +56,23 @@ void setup()
myFile = SD.open("example.txt", FILE_WRITE); myFile = SD.open("example.txt", FILE_WRITE);
myFile.close(); myFile.close();
// Check to see if the file exists: // Check to see if the file exists:
if (SD.exists("example.txt")) { if (SD.exists("example.txt")) {
Serial.println("example.txt exists."); Serial.println("example.txt exists.");
} }
else { else {
Serial.println("example.txt doesn't exist."); Serial.println("example.txt doesn't exist.");
} }
// delete the file: // delete the file:
Serial.println("Removing example.txt..."); Serial.println("Removing example.txt...");
SD.remove("example.txt"); SD.remove("example.txt");
if (SD.exists("example.txt")){ if (SD.exists("example.txt")) {
Serial.println("example.txt exists."); Serial.println("example.txt exists.");
} }
else { else {
Serial.println("example.txt doesn't exist."); Serial.println("example.txt doesn't exist.");
} }
} }

View File

@ -1,85 +1,86 @@
/* /*
SD card read/write SD card read/write
This example shows how to read and write data to and from an SD card file This example shows how to read and write data to and from an SD card file
The circuit: The circuit:
* SD card attached to SPI bus as follows: * SD card attached to SPI bus as follows:
** MOSI - pin 11 ** MOSI - pin 11
** MISO - pin 12 ** MISO - pin 12
** CLK - pin 13 ** CLK - pin 13
** CS - pin 4 ** CS - pin 4
created Nov 2010 created Nov 2010
by David A. Mellis by David A. Mellis
modified 9 Apr 2012 modified 9 Apr 2012
by Tom Igoe by Tom Igoe
This example code is in the public domain. This example code is in the public domain.
*/ */
#include <SPI.h>
#include <SD.h> #include <SD.h>
File myFile; File myFile;
void setup() void setup()
{ {
// Open serial communications and wait for port to open: // Open serial communications and wait for port to open:
Serial.begin(9600); Serial.begin(9600);
while (!Serial) { while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only ; // wait for serial port to connect. Needed for Leonardo only
} }
Serial.print("Initializing SD card..."); Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default. // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin // Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output // (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work. // or the SD library functions will not work.
pinMode(10, OUTPUT); pinMode(10, OUTPUT);
if (!SD.begin(4)) { if (!SD.begin(4)) {
Serial.println("initialization failed!"); Serial.println("initialization failed!");
return; return;
} }
Serial.println("initialization done."); Serial.println("initialization done.");
// open the file. note that only one file can be open at a time, // open the file. note that only one file can be open at a time,
// so you have to close this one before opening another. // so you have to close this one before opening another.
myFile = SD.open("test.txt", FILE_WRITE); myFile = SD.open("test.txt", FILE_WRITE);
// if the file opened okay, write to it: // if the file opened okay, write to it:
if (myFile) { if (myFile) {
Serial.print("Writing to test.txt..."); Serial.print("Writing to test.txt...");
myFile.println("testing 1, 2, 3."); myFile.println("testing 1, 2, 3.");
// close the file: // close the file:
myFile.close(); myFile.close();
Serial.println("done."); Serial.println("done.");
} else { } else {
// if the file didn't open, print an error: // if the file didn't open, print an error:
Serial.println("error opening test.txt"); Serial.println("error opening test.txt");
} }
// re-open the file for reading: // re-open the file for reading:
myFile = SD.open("test.txt"); myFile = SD.open("test.txt");
if (myFile) { if (myFile) {
Serial.println("test.txt:"); Serial.println("test.txt:");
// read from the file until there's nothing else in it: // read from the file until there's nothing else in it:
while (myFile.available()) { while (myFile.available()) {
Serial.write(myFile.read()); Serial.write(myFile.read());
} }
// close the file: // close the file:
myFile.close(); myFile.close();
} else { } else {
// if the file didn't open, print an error: // if the file didn't open, print an error:
Serial.println("error opening test.txt"); Serial.println("error opening test.txt");
} }
} }
void loop() void loop()
{ {
// nothing happens after setup // nothing happens after setup
} }

View File

@ -10,7 +10,7 @@
** MISO - pin 12 ** MISO - pin 12
** CLK - pin 13 ** CLK - pin 13
** CS - pin 4 ** CS - pin 4
created Nov 2010 created Nov 2010
by David A. Mellis by David A. Mellis
modified 9 Apr 2012 modified 9 Apr 2012
@ -19,8 +19,9 @@
by Scott Fitzgerald by Scott Fitzgerald
This example code is in the public domain. This example code is in the public domain.
*/ */
#include <SPI.h>
#include <SD.h> #include <SD.h>
File root; File root;
@ -29,15 +30,15 @@ void setup()
{ {
// Open serial communications and wait for port to open: // Open serial communications and wait for port to open:
Serial.begin(9600); Serial.begin(9600);
while (!Serial) { while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only ; // wait for serial port to connect. Needed for Leonardo only
} }
Serial.print("Initializing SD card..."); Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default. // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin // Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output // (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work. // or the SD library functions will not work.
pinMode(10, OUTPUT); pinMode(10, OUTPUT);
if (!SD.begin(4)) { if (!SD.begin(4)) {
@ -47,9 +48,9 @@ void setup()
Serial.println("initialization done."); Serial.println("initialization done.");
root = SD.open("/"); root = SD.open("/");
printDirectory(root, 0); printDirectory(root, 0);
Serial.println("done!"); Serial.println("done!");
} }

View File

@ -90,7 +90,7 @@ struct partitionTable {
uint32_t firstSector; uint32_t firstSector;
/** Length of the partition, in blocks. */ /** Length of the partition, in blocks. */
uint32_t totalSectors; uint32_t totalSectors;
}; } __attribute__((packed));
/** Type name for partitionTable */ /** Type name for partitionTable */
typedef struct partitionTable part_t; typedef struct partitionTable part_t;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -114,7 +114,7 @@ struct masterBootRecord {
uint8_t mbrSig0; uint8_t mbrSig0;
/** Second MBR signature byte. Must be 0XAA */ /** Second MBR signature byte. Must be 0XAA */
uint8_t mbrSig1; uint8_t mbrSig1;
}; } __attribute__((packed));
/** Type name for masterBootRecord */ /** Type name for masterBootRecord */
typedef struct masterBootRecord mbr_t; typedef struct masterBootRecord mbr_t;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -236,7 +236,7 @@ struct biosParmBlock {
* should always set all of the bytes of this field to 0. * should always set all of the bytes of this field to 0.
*/ */
uint8_t fat32Reserved[12]; uint8_t fat32Reserved[12];
}; } __attribute__((packed));
/** Type name for biosParmBlock */ /** Type name for biosParmBlock */
typedef struct biosParmBlock bpb_t; typedef struct biosParmBlock bpb_t;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -271,7 +271,7 @@ struct fat32BootSector {
uint8_t bootSectorSig0; uint8_t bootSectorSig0;
/** must be 0XAA */ /** must be 0XAA */
uint8_t bootSectorSig1; uint8_t bootSectorSig1;
}; } __attribute__((packed));
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// End Of Chain values for FAT entries // End Of Chain values for FAT entries
/** FAT16 end of chain value used by Microsoft. */ /** FAT16 end of chain value used by Microsoft. */
@ -366,7 +366,7 @@ struct directoryEntry {
uint16_t firstClusterLow; uint16_t firstClusterLow;
/** 32-bit unsigned holding this file's size in bytes. */ /** 32-bit unsigned holding this file's size in bytes. */
uint32_t fileSize; uint32_t fileSize;
}; } __attribute__((packed));
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Definitions for directory entries // Definitions for directory entries
// //

View File

@ -17,20 +17,34 @@
* along with the Arduino Sd2Card Library. If not, see * along with the Arduino Sd2Card Library. If not, see
* <http://www.gnu.org/licenses/>. * <http://www.gnu.org/licenses/>.
*/ */
#define USE_SPI_LIB
#include <Arduino.h> #include <Arduino.h>
#include "Sd2Card.h" #include "Sd2Card.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifndef SOFTWARE_SPI #ifndef SOFTWARE_SPI
#ifdef USE_SPI_LIB
#include <SPI.h>
static SPISettings settings;
#endif
// functions for hardware SPI // functions for hardware SPI
/** Send a byte to the card */ /** Send a byte to the card */
static void spiSend(uint8_t b) { static void spiSend(uint8_t b) {
#ifndef USE_SPI_LIB
SPDR = b; SPDR = b;
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)))
;
#else
SPI.transfer(b);
#endif
} }
/** Receive a byte from the card */ /** Receive a byte from the card */
static uint8_t spiRec(void) { static uint8_t spiRec(void) {
#ifndef USE_SPI_LIB
spiSend(0XFF); spiSend(0XFF);
return SPDR; return SPDR;
#else
return SPI.transfer(0xFF);
#endif
} }
#else // SOFTWARE_SPI #else // SOFTWARE_SPI
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -112,7 +126,8 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
spiSend(crc); spiSend(crc);
// wait for response // wait for response
for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++)
;
return status_; return status_;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -144,9 +159,15 @@ uint32_t Sd2Card::cardSize(void) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Sd2Card::chipSelectHigh(void) { void Sd2Card::chipSelectHigh(void) {
digitalWrite(chipSelectPin_, HIGH); digitalWrite(chipSelectPin_, HIGH);
#ifdef USE_SPI_LIB
SPI.endTransaction();
#endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Sd2Card::chipSelectLow(void) { void Sd2Card::chipSelectLow(void) {
#ifdef USE_SPI_LIB
SPI.beginTransaction(settings);
#endif
digitalWrite(chipSelectPin_, LOW); digitalWrite(chipSelectPin_, LOW);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -219,12 +240,15 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
// set pin modes // set pin modes
pinMode(chipSelectPin_, OUTPUT); pinMode(chipSelectPin_, OUTPUT);
chipSelectHigh(); digitalWrite(chipSelectPin_, HIGH);
#ifndef USE_SPI_LIB
pinMode(SPI_MISO_PIN, INPUT); pinMode(SPI_MISO_PIN, INPUT);
pinMode(SPI_MOSI_PIN, OUTPUT); pinMode(SPI_MOSI_PIN, OUTPUT);
pinMode(SPI_SCK_PIN, OUTPUT); pinMode(SPI_SCK_PIN, OUTPUT);
#endif
#ifndef SOFTWARE_SPI #ifndef SOFTWARE_SPI
#ifndef USE_SPI_LIB
// SS must be in output mode even it is not chip select // SS must be in output mode even it is not chip select
pinMode(SS_PIN, OUTPUT); pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
@ -232,10 +256,20 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
// clear double speed // clear double speed
SPSR &= ~(1 << SPI2X); SPSR &= ~(1 << SPI2X);
#endif // SOFTWARE_SPI #else // USE_SPI_LIB
SPI.begin();
settings = SPISettings(250000, MSBFIRST, SPI_MODE0);
#endif // USE_SPI_LIB
#endif // SOFTWARE_SPI
// must supply min of 74 clock cycles with CS high. // must supply min of 74 clock cycles with CS high.
#ifdef USE_SPI_LIB
SPI.beginTransaction(settings);
#endif
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
#ifdef USE_SPI_LIB
SPI.endTransaction();
#endif
chipSelectLow(); chipSelectLow();
@ -360,18 +394,21 @@ uint8_t Sd2Card::readData(uint32_t block,
// skip data before offset // skip data before offset
for (;offset_ < offset; offset_++) { for (;offset_ < offset; offset_++) {
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)))
;
SPDR = 0XFF; SPDR = 0XFF;
} }
// transfer data // transfer data
n = count - 1; n = count - 1;
for (uint16_t i = 0; i < n; i++) { for (uint16_t i = 0; i < n; i++) {
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)))
;
dst[i] = SPDR; dst[i] = SPDR;
SPDR = 0XFF; SPDR = 0XFF;
} }
// wait for last byte // wait for last byte
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)))
;
dst[n] = SPDR; dst[n] = SPDR;
#else // OPTIMIZE_HARDWARE_SPI #else // OPTIMIZE_HARDWARE_SPI
@ -406,11 +443,13 @@ void Sd2Card::readEnd(void) {
// optimize skip for hardware // optimize skip for hardware
SPDR = 0XFF; SPDR = 0XFF;
while (offset_++ < 513) { while (offset_++ < 513) {
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)))
;
SPDR = 0XFF; SPDR = 0XFF;
} }
// wait for last crc byte // wait for last crc byte
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)))
;
#else // OPTIMIZE_HARDWARE_SPI #else // OPTIMIZE_HARDWARE_SPI
while (offset_++ < 514) spiRec(); while (offset_++ < 514) spiRec();
#endif // OPTIMIZE_HARDWARE_SPI #endif // OPTIMIZE_HARDWARE_SPI
@ -456,6 +495,7 @@ uint8_t Sd2Card::setSckRate(uint8_t sckRateID) {
error(SD_CARD_ERROR_SCK_RATE); error(SD_CARD_ERROR_SCK_RATE);
return false; return false;
} }
#ifndef USE_SPI_LIB
// see avr processor datasheet for SPI register bit definitions // see avr processor datasheet for SPI register bit definitions
if ((sckRateID & 1) || sckRateID == 6) { if ((sckRateID & 1) || sckRateID == 6) {
SPSR &= ~(1 << SPI2X); SPSR &= ~(1 << SPI2X);
@ -465,6 +505,17 @@ uint8_t Sd2Card::setSckRate(uint8_t sckRateID) {
SPCR &= ~((1 <<SPR1) | (1 << SPR0)); SPCR &= ~((1 <<SPR1) | (1 << SPR0));
SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0) SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0)
| (sckRateID & 2 ? (1 << SPR0) : 0); | (sckRateID & 2 ? (1 << SPR0) : 0);
#else // USE_SPI_LIB
switch (sckRateID) {
case 0: settings = SPISettings(25000000, MSBFIRST, SPI_MODE0); break;
case 1: settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); break;
case 2: settings = SPISettings(2000000, MSBFIRST, SPI_MODE0); break;
case 3: settings = SPISettings(1000000, MSBFIRST, SPI_MODE0); break;
case 4: settings = SPISettings(500000, MSBFIRST, SPI_MODE0); break;
case 5: settings = SPISettings(250000, MSBFIRST, SPI_MODE0); break;
default: settings = SPISettings(125000, MSBFIRST, SPI_MODE0);
}
#endif // USE_SPI_LIB
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -561,14 +612,17 @@ uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {
// send two byte per iteration // send two byte per iteration
for (uint16_t i = 0; i < 512; i += 2) { for (uint16_t i = 0; i < 512; i += 2) {
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)))
;
SPDR = src[i]; SPDR = src[i];
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)))
;
SPDR = src[i+1]; SPDR = src[i+1];
} }
// wait for last data byte // wait for last data byte
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)))
;
#else // OPTIMIZE_HARDWARE_SPI #else // OPTIMIZE_HARDWARE_SPI
spiSend(token); spiSend(token);

View File

@ -31,6 +31,11 @@ uint8_t const SPI_FULL_SPEED = 0;
uint8_t const SPI_HALF_SPEED = 1; uint8_t const SPI_HALF_SPEED = 1;
/** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */ /** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */
uint8_t const SPI_QUARTER_SPEED = 2; uint8_t const SPI_QUARTER_SPEED = 2;
/**
* USE_SPI_LIB: if set, use the SPI library bundled with Arduino IDE, otherwise
* run with a standalone driver for AVR.
*/
#define USE_SPI_LIB
/** /**
* Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos. * Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos.
* Pins used are SS 10, MOSI 11, MISO 12, and SCK 13. * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.
@ -66,7 +71,9 @@ uint8_t const SPI_MISO_PIN = MISO_PIN;
/** SPI Clock pin */ /** SPI Clock pin */
uint8_t const SPI_SCK_PIN = SCK_PIN; uint8_t const SPI_SCK_PIN = SCK_PIN;
/** optimize loops for hardware SPI */ /** optimize loops for hardware SPI */
#ifndef USE_SPI_LIB
#define OPTIMIZE_HARDWARE_SPI #define OPTIMIZE_HARDWARE_SPI
#endif
#else // SOFTWARE_SPI #else // SOFTWARE_SPI
// define software SPI pins so Mega can use unmodified GPS Shield // define software SPI pins so Mega can use unmodified GPS Shield

View File

@ -17,6 +17,22 @@
* along with the Arduino SdFat Library. If not, see * along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>. * <http://www.gnu.org/licenses/>.
*/ */
#if defined(__arm__) // Arduino Due Board follows
#ifndef Sd2PinMap_h
#define Sd2PinMap_h
#include <Arduino.h>
uint8_t const SS_PIN = SS;
uint8_t const MOSI_PIN = MOSI;
uint8_t const MISO_PIN = MISO;
uint8_t const SCK_PIN = SCK;
#endif // Sd2PinMap_h
#elif defined(__AVR__) // Other AVR based Boards follows
// Warning this file was generated by a program. // Warning this file was generated by a program.
#ifndef Sd2PinMap_h #ifndef Sd2PinMap_h
#define Sd2PinMap_h #define Sd2PinMap_h
@ -350,3 +366,7 @@ static inline __attribute__((always_inline))
} }
} }
#endif // Sd2PinMap_h #endif // Sd2PinMap_h
#else
#error Architecture or board not supported.
#endif

View File

@ -23,7 +23,9 @@
* \file * \file
* SdFile and SdVolume classes * SdFile and SdVolume classes
*/ */
#ifdef __AVR__
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#endif
#include "Sd2Card.h" #include "Sd2Card.h"
#include "FatStructs.h" #include "FatStructs.h"
#include "Print.h" #include "Print.h"
@ -286,8 +288,10 @@ class SdFile : public Print {
size_t write(uint8_t b); size_t write(uint8_t b);
size_t write(const void* buf, uint16_t nbyte); size_t write(const void* buf, uint16_t nbyte);
size_t write(const char* str); size_t write(const char* str);
#ifdef __AVR__
void write_P(PGM_P str); void write_P(PGM_P str);
void writeln_P(PGM_P str); void writeln_P(PGM_P str);
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if ALLOW_DEPRECATED_FUNCTIONS #if ALLOW_DEPRECATED_FUNCTIONS
// Deprecated functions - suppress cpplint warnings with NOLINT comment // Deprecated functions - suppress cpplint warnings with NOLINT comment

View File

@ -24,12 +24,14 @@
* Useful utility functions. * Useful utility functions.
*/ */
#include <Arduino.h> #include <Arduino.h>
#ifdef __AVR__
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
/** Store and print a string in flash memory.*/ /** Store and print a string in flash memory.*/
#define PgmPrint(x) SerialPrint_P(PSTR(x)) #define PgmPrint(x) SerialPrint_P(PSTR(x))
/** Store and print a string in flash memory followed by a CR/LF.*/ /** Store and print a string in flash memory followed by a CR/LF.*/
#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) #define PgmPrintln(x) SerialPrintln_P(PSTR(x))
/** Defined so doxygen works for function definitions. */ /** Defined so doxygen works for function definitions. */
#endif
#define NOINLINE __attribute__((noinline,unused)) #define NOINLINE __attribute__((noinline,unused))
#define UNUSEDOK __attribute__((unused)) #define UNUSEDOK __attribute__((unused))
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -49,6 +51,7 @@ static UNUSEDOK int FreeRam(void) {
} }
return free_memory; return free_memory;
} }
#ifdef __AVR__
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
* %Print a string in flash memory to the serial port. * %Print a string in flash memory to the serial port.
@ -68,4 +71,5 @@ static NOINLINE void SerialPrintln_P(PGM_P str) {
SerialPrint_P(str); SerialPrint_P(str);
Serial.println(); Serial.println();
} }
#endif // __AVR__
#endif // #define SdFatUtil_h #endif // #define SdFatUtil_h

View File

@ -17,8 +17,10 @@
* along with the Arduino SdFat Library. If not, see * along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>. * <http://www.gnu.org/licenses/>.
*/ */
#include <SdFat.h> #include "SdFat.h"
#ifdef __AVR__
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#endif
#include <Arduino.h> #include <Arduino.h>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// callback function for date/time // callback function for date/time
@ -256,9 +258,15 @@ uint8_t SdFile::make83Name(const char* str, uint8_t* name) {
i = 8; // place for extension i = 8; // place for extension
} else { } else {
// illegal FAT characters // illegal FAT characters
PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
uint8_t b; uint8_t b;
#if defined(__AVR__)
PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
while ((b = pgm_read_byte(p++))) if (b == c) return false; while ((b = pgm_read_byte(p++))) if (b == c) return false;
#elif defined(__arm__)
const uint8_t valid[] = "|<>^+=?/[];,*\"\\";
const uint8_t *p = valid;
while ((b = *p++)) if (b == c) return false;
#endif
// check size and only allow ASCII printable characters // check size and only allow ASCII printable characters
if (i > n || c < 0X21 || c > 0X7E)return false; if (i > n || c < 0X21 || c > 0X7E)return false;
// only upper case allowed in 8.3 names - convert lower to upper // only upper case allowed in 8.3 names - convert lower to upper
@ -1232,6 +1240,7 @@ size_t SdFile::write(uint8_t b) {
size_t SdFile::write(const char* str) { size_t SdFile::write(const char* str) {
return write(str, strlen(str)); return write(str, strlen(str));
} }
#ifdef __AVR__
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
* Write a PROGMEM string to a file. * Write a PROGMEM string to a file.
@ -1251,3 +1260,4 @@ void SdFile::writeln_P(PGM_P str) {
write_P(str); write_P(str);
println(); println();
} }
#endif

View File

@ -17,7 +17,7 @@
* along with the Arduino SdFat Library. If not, see * along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>. * <http://www.gnu.org/licenses/>.
*/ */
#include <SdFat.h> #include "SdFat.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// raw block cache // raw block cache
// init cacheBlockNumber_to invalid SD block number // init cacheBlockNumber_to invalid SD block number