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

@ -20,6 +20,7 @@
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:

View File

@ -20,6 +20,7 @@
*/ */
#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

View File

@ -20,6 +20,7 @@
*/ */
#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

View File

@ -17,6 +17,7 @@
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;

View File

@ -18,6 +18,7 @@
*/ */
#include <SPI.h>
#include <SD.h> #include <SD.h>
File myFile; File myFile;

View File

@ -21,6 +21,7 @@
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;

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);
#else // USE_SPI_LIB
SPI.begin();
settings = SPISettings(250000, MSBFIRST, SPI_MODE0);
#endif // USE_SPI_LIB
#endif // SOFTWARE_SPI #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