Переглянути джерело

Bug fixes and new features

main
Bill Greiman 4 роки тому
джерело
коміт
56f3e4c857
20 змінених файлів з 321 додано та 324 видалено
  1. +1
    -1
      examples/ExFatUnicodeTest/ExFatUnicodeTest.ino
  2. +47
    -0
      examples/UserChipSelectFunction/UserChipSelectFunction.ino
  3. +78
    -0
      examples/UserSPIDriver/UserSPIDriver.ino
  4. +1
    -1
      examples/debug/TestMkdir/TestMkdir.ino
  5. +1
    -1
      examples/debug/TestRmdir/TestRmdir.ino
  6. +40
    -37
      extras/SdErrorCodes.txt
  7. +1
    -1
      library.properties
  8. +6
    -4
      src/ExFatLib/ExFatFile.cpp
  9. +8
    -12
      src/FatLib/FatFileLFN.cpp
  10. +2
    -1
      src/FsLib/FsFile.cpp
  11. +1
    -2
      src/SdCard/SdCard.h
  12. +12
    -6
      src/SdCard/SdSpiCard.cpp
  13. +46
    -16
      src/SdCard/SdSpiCard.h
  14. +6
    -6
      src/SdFatConfig.h
  15. +6
    -1
      src/SpiDriver/SdSpiArtemis.cpp
  16. +1
    -60
      src/SpiDriver/SdSpiBaseClass.h
  17. +1
    -1
      src/SpiDriver/SdSpiChipSelect.cpp
  18. +25
    -25
      src/SpiDriver/SdSpiDriver.h
  19. +0
    -90
      src/SpiDriver/SdSpiExternalDriver.h
  20. +38
    -59
      src/SpiDriver/SdSpiSoftDriver.h

+ 1
- 1
examples/ExFatUnicodeTest/ExFatUnicodeTest.ino Переглянути файл

@@ -13,7 +13,7 @@ const uint8_t SD_CS_PIN = SS;
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN

// Use SPI, SD_CS_PIN, SHARED_SPI, FULL_SPEED.
// Use SPI, SD_CS_PIN, SHARED_SPI, 50 MHz.
#define SD_CONFIG SdSpiConfig(SD_CS_PIN)

SdExFat sd;

+ 47
- 0
examples/UserChipSelectFunction/UserChipSelectFunction.ino Переглянути файл

@@ -0,0 +1,47 @@
// An example of an external chip select functions.
// Useful for port expanders or replacement of the standard GPIO functions.
//
#include "SdFat.h"

// SD_CHIP_SELECT_MODE must be set to one or two in SdFat/SdFatConfig.h.
// A value of one allows optional replacement and two requires replacement.
#if SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2

// SD chip select pin.
#define SD_CS_PIN SS

#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(50))

SdFat sd;

// Stats to verify function calls.
uint32_t initCalls = 0;
uint32_t writeCalls = 0;
//------------------------------------------------------------------------------
// Modify these functions for your port expander or custom GPIO library.
void sdCsInit(SdCsPin_t pin) {
initCalls++;
pinMode(pin, OUTPUT);
}
void sdCsWrite(SdCsPin_t pin, bool level) {
writeCalls++;
digitalWrite(pin, level);
}
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
sd.ls(&Serial, LS_SIZE);
Serial.print(F("sdCsInit calls: "));
Serial.println(initCalls);
Serial.print(F("sdCsWrite calls: "));
Serial.println(writeCalls);
}
//------------------------------------------------------------------------------
void loop() {}
#else // SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2
#error SD_CHIP_SELECT_MODE must be one or two in SdFat/SdFatConfig.h
#endif // SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2

+ 78
- 0
examples/UserSPIDriver/UserSPIDriver.ino Переглянути файл

@@ -0,0 +1,78 @@
// An example of an external SPI driver.
//
#include "SdFat.h"
#include "SPI.h" // Only required if you use features in the SPI library.

#if SPI_DRIVER_SELECT == 3 // Must be set in SdFat/SdFatConfig.h

// SD chip select pin.
#define SD_CS_PIN SS

// This is a simple driver based on the the standard SPI.h library.
// You can write a driver entirely independent of SPI.h.
// It can be optimized for your board or a different SPI port can be used.
// The driver must be derived from SdSpiBaseClass.
// See: SdFat/src/SpiDriver/SdSpiBaseClass.h
class MySpiClass : public SdSpiBaseClass {
public:
// Activate SPI hardware with correct speed and mode.
void activate() {
SPI.beginTransaction(m_spiSettings);
}
// Initialize the SPI bus.
void begin(SdSpiConfig config) {
(void)config;
SPI.begin();
}
// Deactivate SPI hardware.
void deactivate() {
SPI.endTransaction();
}
// Receive a byte.
uint8_t receive() {
return SPI.transfer(0XFF);
}
// Receive multiple bytes.
// Replace this function if your board has multiple byte receive.
uint8_t receive(uint8_t* buf, size_t count) {
for (size_t i = 0; i < count; i++) {
buf[i] = SPI.transfer(0XFF);
}
return 0;
}
// Send a byte.
void send(uint8_t data) {
SPI.transfer(data);
}
// Send multiple bytes.
// Replace this function if your board has multiple byte send.
void send(const uint8_t* buf, size_t count) {
for (size_t i = 0; i < count; i++) {
SPI.transfer(buf[i]);
}
}
// Save SPISettings for new max SCK frequency
void setSckSpeed(uint32_t maxSck) {
m_spiSettings = SPISettings(maxSck, MSBFIRST, SPI_MODE0);
}

private:
SPISettings m_spiSettings;
} mySpi;

#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(50), &mySpi)
SdFat sd;

//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
sd.ls(&Serial, LS_SIZE);
}
//------------------------------------------------------------------------------
void loop() {}
#else // SPI_DRIVER_SELECT
#error SPI_DRIVER_SELECT must be three in SdFat/SdFatConfig.h
#endif // SPI_DRIVER_SELECT

+ 1
- 1
examples/debug/TestMkdir/TestMkdir.ino Переглянути файл

@@ -109,7 +109,7 @@ void setup() {
delay(200); // Catch Due reset problem
// initialize the SD card at SPI_FULL_SPEED for best performance.
// try SPI_HALF_SPEED if bus errors occur.
// try lower speed if bus errors occur.
if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) {
sd.initErrorHalt(&Serial);
}

+ 1
- 1
examples/debug/TestRmdir/TestRmdir.ino Переглянути файл

@@ -62,7 +62,7 @@ void setup() {
delay(200); // Catch Due reset problem
// initialize the SD card at SPI_FULL_SPEED for best performance.
// try SPI_HALF_SPEED if bus errors occur.
// try lower speed if bus errors occur.
if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) {
sd.initErrorHalt(&Serial);
}

+ 40
- 37
extras/SdErrorCodes.txt Переглянути файл

@@ -1,47 +1,50 @@
2017-08-10
2019-12-10

Run the SdErrorCode example to produce an updated list.

C
Code,Symbol - failed operation
0X0,SD_CARD_ERROR_NONE - No error
0X1,SD_CARD_ERROR_CMD0 - Card reset failed
0X2,SD_CARD_ERROR_CMD2 - SDIO read CID
0X3,SD_CARD_ERROR_CMD3 - SDIO publish RCA
0X4,SD_CARD_ERROR_CMD6 - Switch card function
0X5,SD_CARD_ERROR_CMD7 - SDIO card select
0X6,SD_CARD_ERROR_CMD8 - Send and check interface settings
0X7,SD_CARD_ERROR_CMD9 - Read CSD data
0X8,SD_CARD_ERROR_CMD10 - Read CID data
0X9,SD_CARD_ERROR_CMD12 - Stop multiple block read
0XA,SD_CARD_ERROR_CMD13 - Read card status
0XB,SD_CARD_ERROR_CMD17 - Read single block
0XC,SD_CARD_ERROR_CMD18 - Read multiple blocks
0XD,SD_CARD_ERROR_CMD24 - Write single block
0XE,SD_CARD_ERROR_CMD25 - Write multiple blocks
0XF,SD_CARD_ERROR_CMD32 - Set first erase block
0X00,SD_CARD_ERROR_NONE - No error
0X01,SD_CARD_ERROR_CMD0 - Card reset failed
0X02,SD_CARD_ERROR_CMD2 - SDIO read CID
0X03,SD_CARD_ERROR_CMD3 - SDIO publish RCA
0X04,SD_CARD_ERROR_CMD6 - Switch card function
0X05,SD_CARD_ERROR_CMD7 - SDIO card select
0X06,SD_CARD_ERROR_CMD8 - Send and check interface settings
0X07,SD_CARD_ERROR_CMD9 - Read CSD data
0X08,SD_CARD_ERROR_CMD10 - Read CID data
0X09,SD_CARD_ERROR_CMD12 - Stop multiple block read
0X0A,SD_CARD_ERROR_CMD13 - Read card status
0X0B,SD_CARD_ERROR_CMD17 - Read single block
0X0C,SD_CARD_ERROR_CMD18 - Read multiple blocks
0X0D,SD_CARD_ERROR_CMD24 - Write single block
0X0E,SD_CARD_ERROR_CMD25 - Write multiple blocks
0X0F,SD_CARD_ERROR_CMD32 - Set first erase block
0X10,SD_CARD_ERROR_CMD33 - Set last erase block
0X11,SD_CARD_ERROR_CMD38 - Erase selected blocks
0X12,SD_CARD_ERROR_CMD58 - Read OCR register
0X13,SD_CARD_ERROR_CMD59 - Set CRC mode
0X14,SD_CARD_ERROR_ACMD6 - Set SDIO bus width
0X15,SD_CARD_ERROR_ACMD13 - Read extended status
0X16,SD_CARD_ERROR_ACMD41 - Activate card initialization
0X17,SD_CARD_ERROR_READ_TOKEN - Bad read data token
0X18,SD_CARD_ERROR_READ_CRC - Read CRC error
0X19,SD_CARD_ERROR_READ_FIFO - SDIO fifo read timeout
0X1A,SD_CARD_ERROR_READ_REG - Read CID or CSD failed.
0X1B,SD_CARD_ERROR_READ_START - Bad readStart argument
0X1C,SD_CARD_ERROR_READ_TIMEOUT - Read data timeout
0X1D,SD_CARD_ERROR_STOP_TRAN - Multiple block stop failed
0X1E,SD_CARD_ERROR_WRITE_DATA - Write data not accepted
0X1F,SD_CARD_ERROR_WRITE_FIFO - SDIO fifo write timeout
0X20,SD_CARD_ERROR_WRITE_START - Bad writeStart argument
0X21,SD_CARD_ERROR_WRITE_TIMEOUT - Flash programming timeout
0X22,SD_CARD_ERROR_DMA - DMA transfer failed
0X23,SD_CARD_ERROR_ERASE - Card did not accept erase commands
0X24,SD_CARD_ERROR_ERASE_SINGLE_SECTOR - Card does not support erase
0X25,SD_CARD_ERROR_ERASE_TIMEOUT - Erase command timeout
0X26,SD_CARD_ERROR_INIT_NOT_CALLED - Card has not been initialized
0X27,SD_CARD_ERROR_INVALID_CARD_CONFIG - Invalid card config
0X28,SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED - Unsupported SDIO command
0X29,SD_CARD_ERROR_UNKNOWN - Unknown error
0X16,SD_CARD_ERROR_ACMD23 - Set pre-erased count
0X17,SD_CARD_ERROR_ACMD41 - Activate card initialization
0X18,SD_CARD_ERROR_READ_TOKEN - Bad read data token
0X19,SD_CARD_ERROR_READ_CRC - Read CRC error
0X1A,SD_CARD_ERROR_READ_FIFO - SDIO fifo read timeout
0X1B,SD_CARD_ERROR_READ_REG - Read CID or CSD failed.
0X1C,SD_CARD_ERROR_READ_START - Bad readStart argument
0X1D,SD_CARD_ERROR_READ_TIMEOUT - Read data timeout
0X1E,SD_CARD_ERROR_STOP_TRAN - Multiple block stop failed
0X1F,SD_CARD_ERROR_WRITE_DATA - Write data not accepted
0X20,SD_CARD_ERROR_WRITE_FIFO - SDIO fifo write timeout
0X21,SD_CARD_ERROR_WRITE_START - Bad writeStart argument
0X22,SD_CARD_ERROR_WRITE_PROGRAMMING - Flash programming
0X23,SD_CARD_ERROR_WRITE_TIMEOUT - Write timeout
0X24,SD_CARD_ERROR_DMA - DMA transfer failed
0X25,SD_CARD_ERROR_ERASE - Card did not accept erase commands
0X26,SD_CARD_ERROR_ERASE_SINGLE_SECTOR - Card does not support erase
0X27,SD_CARD_ERROR_ERASE_TIMEOUT - Erase command timeout
0X28,SD_CARD_ERROR_INIT_NOT_CALLED - Card has not been initialized
0X29,SD_CARD_ERROR_INVALID_CARD_CONFIG - Invalid card config
0X2A,SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED - Unsupported SDIO command
0X2B,SD_CARD_ERROR_UNKNOWN - Unknown error

+ 1
- 1
library.properties Переглянути файл

@@ -1,5 +1,5 @@
name=SdFat
version=2.0.0-beta.7
version=2.0.0-beta.8
license=MIT
author=Bill Greiman <fat16lib@sbcglobal.net>
maintainer=Bill Greiman <fat16lib@sbcglobal.net>

+ 6
- 4
src/ExFatLib/ExFatFile.cpp Переглянути файл

@@ -508,6 +508,8 @@ size_t ExFatFile::printName(print_t* pr) {
DirName_t* dn;
DirPos_t pos = m_dirPos;
size_t n = 0;
uint8_t in;
uint8_t buf[15];
if (!isOpen()) {
DBG_FAIL_MACRO;
goto fail;
@@ -523,16 +525,16 @@ size_t ExFatFile::printName(print_t* pr) {
DBG_FAIL_MACRO;
goto fail;
}
for (uint8_t in = 0; in < 15; in++) {
for (in = 0; in < 15; in++) {
uint16_t c = getLe16(dn->unicode + 2*in);
if (!c) {
goto done;
break;;
}
pr->write(c < 0X7f ? c : '?');
buf[in] = c < 0X7f ? c : '?';
n++;
}
pr->write(buf, in);
}
done:
return n;

fail:

+ 8
- 12
src/FatLib/FatFileLFN.cpp Переглянути файл

@@ -506,9 +506,11 @@ fail:
//------------------------------------------------------------------------------
size_t FatFile::printName(print_t* pr) {
FatFile dirFile;
uint16_t u;
size_t n = 0;
DirLfn_t* ldir;
size_t n = 0;
uint16_t u;
uint8_t buf[13];
uint8_t i;

if (!isLFN()) {
return printSFN(pr);
@@ -532,24 +534,18 @@ size_t FatFile::printName(print_t* pr) {
DBG_FAIL_MACRO;
goto fail;
}
for (uint8_t i = 0; i < 13; i++) {
for (i = 0; i < 13; i++) {
u = lfnGetChar(ldir, i);
if (u == 0) {
// End of name.
break;
}
if (u > 0X7E) {
u = '?';
}
pr->write(static_cast<char>(u));
buf[i] = u < 0X7F ? u : '?';
n++;
}
if (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) {
return n;
}
pr->write(buf, i);
}
// Fall into fail;
DBG_FAIL_MACRO;
return n;

fail:
return 0;

+ 2
- 1
src/FsLib/FsFile.cpp Переглянути файл

@@ -25,7 +25,8 @@
#include "FsLib.h"
//------------------------------------------------------------------------------
FsBaseFile::FsBaseFile(const FsBaseFile& from) {
close();
m_fFile = nullptr;
m_xFile = nullptr;
if (from.m_fFile) {
m_fFile = new (m_fileMem) FatFile;
*m_fFile = *from.m_fFile;

+ 1
- 2
src/SdCard/SdCard.h Переглянути файл

@@ -55,7 +55,7 @@ class SdCardFactory {
* \return generic card pointer.
*/
SdCard* newCard(SdSpiConfig config) {
m_spiCard.begin(&m_spi, config);
m_spiCard.begin(config);
return &m_spiCard;
}
/** Initialize SDIO card.
@@ -78,6 +78,5 @@ class SdCardFactory {
SdioCard m_sdioCard;
#endif // HAS_SDIO_CLASS
SdSpiCard m_spiCard;
SdSpiDriver m_spi;
};
#endif // SdCard_h

+ 12
- 6
src/SdCard/SdSpiCard.cpp Переглянути файл

@@ -220,16 +220,22 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
//==============================================================================
// SdSpiCard member functions
//------------------------------------------------------------------------------
bool SdSpiCard::begin(SdSpiDriver* spi, SdSpiConfig spiConfig) {
bool SdSpiCard::begin(SdSpiConfig spiConfig) {
SdMillis_t t0 = SysCall::curTimeMS();
m_errorCode = SD_CARD_ERROR_NONE;
m_type = 0;
m_csPin = spiConfig.csPin;
#if SPI_DRIVER_SELECT >= 2
m_spiDriverPtr = spiConfig.spiPort;
if (!m_spiDriverPtr) {
error(SD_CARD_ERROR_INVALID_CARD_CONFIG);
goto fail;
}
#endif // SPI_DRIVER_SELECT
sdCsInit(m_csPin);
spiUnselect();
m_spiDriver = spi;
m_spiDriver->setSckSpeed(1000UL*SD_MAX_INIT_RATE_KHZ);
m_spiDriver->begin(spiConfig);
SdMillis_t t0 = SysCall::curTimeMS();
spiSetSckSpeed(1000UL*SD_MAX_INIT_RATE_KHZ);
spiBegin(spiConfig);
uint32_t arg;
#if ENABLE_DEDICATED_SPI
m_sharedSpi = !(spiConfig.options & DEDICATED_SPI);
@@ -317,7 +323,7 @@ bool SdSpiCard::begin(SdSpiDriver* spi, SdSpiConfig spiConfig) {
}
}
spiStop();
m_spiDriver->setSckSpeed(spiConfig.maxSck);
spiSetSckSpeed(spiConfig.maxSck);
return true;

fail:

+ 46
- 16
src/SdCard/SdSpiCard.h Переглянути файл

@@ -53,7 +53,7 @@ class SdSpiCard {
* \param[in] spiConfig SPI card configuration.
* \return true for success or false for failure.
*/
bool begin(SdSpiDriver* spi, SdSpiConfig spiConfig);
bool begin(SdSpiConfig spiConfig);
/** Clear debug stats. */
void dbgClearStats();
/** Print debug stats. */
@@ -285,40 +285,71 @@ class SdSpiCard {
bool isTimedOut(SdMillis_t startMS, SdMillis_t timeoutMS);
bool readData(uint8_t* dst, size_t count);
bool readRegister(uint8_t cmd, void* buf);

void spiSelect() {
sdCsWrite(m_csPin, false);
}
void type(uint8_t value) {
m_type = value;
}

void spiUnselect() {
sdCsWrite(m_csPin, true);
}
bool waitNotBusy(SdMillis_t timeoutMS);
bool writeData(uint8_t token, const uint8_t* src);

//---------------------------------------------------------------------------
// functions defined in SdSpiDriver.h
#if SPI_DRIVER_SELECT < 2
void spiActivate() {
m_spiDriver->activate();
m_spiDriver.activate();
}
void spiBegin(SdSpiConfig spiConfig) {
m_spiDriver.begin(spiConfig);
}
void spiDeactivate() {
m_spiDriver->deactivate();
m_spiDriver.deactivate();
}
uint8_t spiReceive() {
return m_spiDriver->receive();
return m_spiDriver.receive();
}
uint8_t spiReceive(uint8_t* buf, size_t n) {
return m_spiDriver->receive(buf, n);
return m_spiDriver.receive(buf, n);
}
void spiSend(uint8_t data) {
m_spiDriver->send(data);
m_spiDriver.send(data);
}
void spiSend(const uint8_t* buf, size_t n) {
m_spiDriver->send(buf, n);
m_spiDriver.send(buf, n);
}
void spiSelect() {
sdCsWrite(m_csPin, false);
void spiSetSckSpeed(uint32_t maxSck) {
m_spiDriver.setSckSpeed(maxSck);
}
void spiUnselect() {
sdCsWrite(m_csPin, true);
SdSpiDriver m_spiDriver;
#else // SPI_DRIVER_SELECT < 2
void spiActivate() {
m_spiDriverPtr->activate();
}
void spiBegin(SdSpiConfig spiConfig) {
m_spiDriverPtr->begin(spiConfig);
}
void spiDeactivate() {
m_spiDriverPtr->deactivate();
}
uint8_t spiReceive() {
return m_spiDriverPtr->receive();
}
uint8_t spiReceive(uint8_t* buf, size_t n) {
return m_spiDriverPtr->receive(buf, n);
}
void spiSend(uint8_t data) {
m_spiDriverPtr->send(data);
}
void spiSend(const uint8_t* buf, size_t n) {
m_spiDriverPtr->send(buf, n);
}
void spiSetSckSpeed(uint32_t maxSck) {
m_spiDriverPtr->setSckSpeed(maxSck);
}
SdSpiDriver* m_spiDriverPtr;
#endif // SPI_DRIVER_SELECT < 2
#if ENABLE_DEDICATED_SPI
static const uint8_t IDLE_STATE = 0;
static const uint8_t READ_STATE = 1;
@@ -327,7 +358,6 @@ class SdSpiCard {
uint8_t m_curState;
bool m_sharedSpi;
#endif // ENABLE_DEDICATED_SPI
SdSpiDriver *m_spiDriver;
SdCsPin_t m_csPin;
uint8_t m_errorCode;
bool m_spiActive;

+ 6
- 6
src/SdFatConfig.h Переглянути файл

@@ -38,13 +38,13 @@
#define ENABLE_ARDUINO_SERIAL 1
/** For Debug - must be one */
#define ENABLE_ARDUINO_STRING 1
/** Set USE_BLOCK_DEVICE_INTERFACE nonzero to use generic of block device */
/** Set USE_BLOCK_DEVICE_INTERFACE nonzero to use generic block device */
#define USE_BLOCK_DEVICE_INTERFACE 0
//------------------------------------------------------------------------------
#if ENABLE_ARDUINO_FEATURES
#include "Arduino.h"
#ifdef PLATFORM_ID
// Only defined if a Particle device
// Only defined if a Particle device.
#include "application.h"
#endif // PLATFORM_ID
#endif // ENABLE_ARDUINO_FEATURES
@@ -56,8 +56,8 @@
#define INCLUDE_SDIOS 0
//------------------------------------------------------------------------------
/**
* Optimize access to contiguous files.
* Experimental - set nonzero to enable.
* Set USE_FAT_FILE_FLAG_CONTIGUOUS nonzero to optimize access to
* contiguous files.
*/
#define USE_FAT_FILE_FLAG_CONTIGUOUS 1
//------------------------------------------------------------------------------
@@ -101,9 +101,9 @@
*
* 1 - The standard library driver is always used.
*
* 2 - The software SPI driver is always used.
* 2 - An external SPI driver of SoftSpiDriver template class is always used.
*
* 3 - Experimental external SPI driver hook.
* 3 - An external SPI driver derived from SdSpiBaseClass is always used.
*/
#define SPI_DRIVER_SELECT 0
//------------------------------------------------------------------------------

+ 6
- 1
src/SpiDriver/SdSpiArtemis.cpp Переглянути файл

@@ -56,7 +56,12 @@ void SdSpiArduinoDriver::send(uint8_t data) {
}
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::send(const uint8_t *buf, size_t count) {
// Convert byte array to 4 byte array
// If not a multiple of four. Command with CRC used six byte send.
while (count%4) {
send(*buf++);
count--;
}
// Convert byte array to 4 byte array.
uint32_t myArray[count/4]; // NOLINT
for (int x = 0; x < count/4; x++) {
myArray[x] = ((uint32_t)buf[(x * 4) + 3] << (8 * 3)) |

+ 1
- 60
src/SpiDriver/SdSpiBaseClass.h Переглянути файл

@@ -37,7 +37,7 @@ class SdSpiBaseClass {
/** Activate SPI hardware. */
virtual void activate() {}
/** Initialize the SPI bus. */
virtual void begin() = 0;
virtual void begin(SdSpiConfig config) = 0;
/** Deactivate SPI hardware. */
virtual void deactivate() {}
/** Receive a byte.
@@ -70,63 +70,4 @@ class SdSpiBaseClass {
*/
virtual void setSckSpeed(uint32_t maxSck) {(void)maxSck;}
};
#include "SPI.h"
/**
* \class MySpiClass
* \brief Sample external SPI class.
*/
class MySpiClass : public SdSpiBaseClass {
public:
/** Activate SPI hardware. */
void activate() {
SPI.beginTransaction(m_spiSettings);
}
/** Initialize the SPI bus. */
void begin() {SPI.begin();}
/** Deactivate SPI hardware. */
void deactivate() {SPI.endTransaction();}
/** Receive a byte.
*
* \return The byte.
*/
uint8_t receive() {return SPI.transfer(0XFF);}
/** Receive multiple bytes.
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
uint8_t receive(uint8_t* buf, size_t count) {
for (size_t i = 0; i < count; i++) {
buf[i] = SPI.transfer(0XFF);
}
return 0;
}
/** Send a byte.
*
* \param[in] data Byte to send
*/
void send(uint8_t data) {SPI.transfer(data);}
/** Send multiple bytes.
*
* \param[in] buf Buffer for data to be sent.
* \param[in] count Number of bytes to send.
*/
void send(const uint8_t* buf, size_t count) {
for (size_t i = 0; i < count; i++) {
SPI.transfer(buf[i]);
}
}
/** Save high speed SPISettings after SD initialization.
*
* \param[in] maxSck Maximum SCK frequency.
*/
void setSckSpeed(uint32_t maxSck) {
m_spiSettings = SPISettings(maxSck, MSBFIRST, SPI_MODE0);
}

private:
SPISettings m_spiSettings;
};
#endif // SdSpiBaseClass_h

+ 1
- 1
src/SpiDriver/SdSpiChipSelect.cpp Переглянути файл

@@ -33,8 +33,8 @@ void sdCsInit(SdCsPin_t pin) {
void sdCsWrite(SdCsPin_t pin, bool level) {
digitalWrite(pin, level);
}
//------------------------------------------------------------------------------
#elif SD_CHIP_SELECT_MODE == 1
//------------------------------------------------------------------------------
__attribute__((weak))
void sdCsInit(SdCsPin_t pin) {
pinMode(pin, OUTPUT);

+ 25
- 25
src/SpiDriver/SdSpiDriver.h Переглянути файл

@@ -47,21 +47,21 @@ void sdCsWrite(SdCsPin_t pin, bool level);
#define SD_SCK_HZ(maxSpeed) (maxSpeed)
/** SPISettings for SCK frequency in MHz. */
#define SD_SCK_MHZ(maxMhz) (1000000UL*(maxMhz))
// SPI divisor constants
// SPI divisor constants - obsolete.
/** Set SCK to max rate. */
#define SPI_FULL_SPEED SD_SCK_MHZ(50)
/** Set SCK rate to F_CPU/3 for Due */
#define SPI_DIV3_SPEED SD_SCK_HZ(F_CPU/3)
/** Set SCK rate to F_CPU/4. */
#define SPI_HALF_SPEED SD_SCK_HZ(F_CPU/4)
/** Set SCK rate to F_CPU/6 for Due */
#define SPI_DIV6_SPEED SD_SCK_HZ(F_CPU/6)
/** Set SCK rate to F_CPU/8. */
#define SPI_QUARTER_SPEED SD_SCK_HZ(F_CPU/8)
/** Set SCK rate to F_CPU/16. */
#define SPI_EIGHTH_SPEED SD_SCK_HZ(F_CPU/16)
/** Set SCK rate to F_CPU/32. */
#define SPI_SIXTEENTH_SPEED SD_SCK_HZ(F_CPU/32)
/** Set SCK rate to 16 MHz for Due */
#define SPI_DIV3_SPEED SD_SCK_MHZ(16)
/** Set SCK rate to 4 MHz for AVR. */
#define SPI_HALF_SPEED SD_SCK_MHZ(4)
/** Set SCK rate to 8 MHz for Due */
#define SPI_DIV6_SPEED SD_SCK_MHZ(8)
/** Set SCK rate to 2 MHz for AVR. */
#define SPI_QUARTER_SPEED SD_SCK_MHZ(2)
/** Set SCK rate to 1 MHz for AVR. */
#define SPI_EIGHTH_SPEED SD_SCK_MHZ(1)
/** Set SCK rate to 500 kHz for AVR. */
#define SPI_SIXTEENTH_SPEED SD_SCK_HZ(500000)
//------------------------------------------------------------------------------
/** The SD is the only device on the SPI bus. */
#define DEDICATED_SPI 0X80
@@ -69,15 +69,18 @@ void sdCsWrite(SdCsPin_t pin, bool level);
#define SHARED_SPI 0
#if SPI_DRIVER_SELECT < 2
#include "SPI.h"
/** Port type for SPI hardware driver. */
/** Port type for Arduino SPI hardware driver. */
typedef SPIClass SpiPort_t;
#elif SPI_DRIVER_SELECT == 2
class SoftSPIClass;
class SdSpiSoftDriver;
/** Port type for software SPI driver. */
typedef SoftSPIClass SpiPort_t;
#else // SPI_DRIVER_SELECT
#include "SdSpiBaseClass.h"
typedef SdSpiSoftDriver SpiPort_t;
#elif SPI_DRIVER_SELECT == 3
class SdSpiBaseClass;
/** Port type for extrernal SPI driver. */
typedef SdSpiBaseClass SpiPort_t;
#else // SPI_DRIVER_SELECT
typedef void* SpiPort_t;
#endif // SPI_DRIVER_SELECT
//------------------------------------------------------------------------------
/**
@@ -110,13 +113,13 @@ class SdSpiConfig {
* \param[in] opt Options.
*/
SdSpiConfig(SdCsPin_t cs, uint8_t opt) :
csPin(cs), options(opt), maxSck(SPI_FULL_SPEED), spiPort(nullptr) {}
csPin(cs), options(opt), maxSck(SD_SCK_MHZ(50)), spiPort(nullptr) {}
/** SdSpiConfig constructor.
*
* \param[in] cs Chip select pin.
*/
explicit SdSpiConfig(SdCsPin_t cs) : csPin(cs), options(SHARED_SPI),
maxSck(SPI_FULL_SPEED), spiPort(nullptr) {}
maxSck(SD_SCK_MHZ(50)), spiPort(nullptr) {}

/** Chip select pin. */
const SdCsPin_t csPin;
@@ -127,16 +130,13 @@ class SdSpiConfig {
/** SPI port */
SpiPort_t* spiPort;
};

#if SPI_DRIVER_SELECT < 2
#include "SdSpiArduinoDriver.h"
#elif SPI_DRIVER_SELECT == 2
#include "SdSpiSoftDriver.h"
#elif SPI_DRIVER_SELECT == 3
#include "SdSpiExternalDriver.h"
#elif SPI_DRIVER_SELECT == 4
#include "SdSpiBareUnoDriver.h"
typedef SdSpiDriverBareUno SdSpiDriver;
#include "SdSpiBaseClass.h"
typedef SdSpiBaseClass SdSpiDriver;
#else // SPI_DRIVER_SELECT
#error Invalid SPI_DRIVER_SELECT
#endif // SPI_DRIVER_SELECT

+ 0
- 90
src/SpiDriver/SdSpiExternalDriver.h Переглянути файл

@@ -1,90 +0,0 @@
/**
* Copyright (c) 2011-2019 Bill Greiman
* This file is part of the SdFat library for SD memory cards.
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* \file
* \brief Class for external drivers.
*/
#ifndef SdSpiExternalDriver_h
#define SdSpiExternalDriver_h
/**
* \class SdExternalSpiDriver
* \brief Class for external SPI.
*/
class SdExternalSpiDriver {
public:
/** Activate SPI hardware. */
void activate() {if (m_spi) m_spi->activate();}
/** Initialize the SPI bus.
*
* \param[in] spiConfig SD card configuration.
*/
void begin(SdSpiConfig spiConfig) {
m_spi = spiConfig.spiPort;
if (m_spi) m_spi->begin();
}
/** Deactivate SPI hardware. */
void deactivate() {if (m_spi) m_spi->deactivate();}
/** Receive a byte.
*
* \return The byte.
*/
uint8_t receive() {return m_spi ? m_spi->receive(): 0XFF;}
/** Receive multiple bytes.
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
uint8_t receive(uint8_t* buf, size_t count) {
return m_spi ? m_spi->receive(buf, count) : 1;
}
/** Send a byte.
*
* \param[in] data Byte to send
*/
void send(uint8_t data) {if (m_spi) m_spi->send(data);}
/** Send multiple bytes.
*
* \param[in] buf Buffer for data to be sent.
* \param[in] count Number of bytes to send.
*/
void send(const uint8_t* buf, size_t count) {
if (m_spi) m_spi->send(buf, count);
}
/** Save high speed SPISettings after SD initialization.
*
* \param[in] maxSck Maximum SCK frequency.
*/
void setSckSpeed(uint32_t maxSck) {
if (m_spi) m_spi->setSckSpeed(maxSck);
}

private:
SdSpiBaseClass* m_spi;
};
/** Typedef for use of SdExternalSpiDriver */
typedef SdExternalSpiDriver SdSpiDriver;
#endif // SdSpiExternalDriver_h

+ 38
- 59
src/SpiDriver/SdSpiSoftDriver.h Переглянути файл

@@ -30,64 +30,22 @@
#define SdSpiSoftDriver_h
#include "../DigitalIO/SoftSPI.h"
/**
* \class SoftSPIClass
* \class SdSpiSoftDriver
* \brief Base class for external soft SPI.
*/
class SoftSPIClass {
public:
/** Initialize the SPI bus. */
virtual void begin() = 0;
/** Receive a byte.
*
* \return The byte.
*/
virtual uint8_t receive() = 0;
/** Send a byte.
*
* \param[in] data Byte to send
*/
virtual void send(uint8_t data) = 0;
};
//------------------------------------------------------------------------------
/**
* \class SoftSpiDriver
* \brief Class for external soft SPI.
*/
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
class SoftSpiDriver : public SoftSPIClass {
public:
/** Initialize the SPI bus. */
void begin() {m_spi.begin();}
/** Receive a byte.
*
* \return The byte.
*/
uint8_t receive() {return m_spi.receive();}
/** Send a byte.
*
* \param[in] data Byte to send
*/
void send(uint8_t data) {m_spi.send(data);}
private:
SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi;
};

//------------------------------------------------------------------------------
/**
* \class SdSoftSpiDriver
* \brief Class for SdSoftSpiDriver.
*/
class SdSoftSpiDriver {
class SdSpiSoftDriver {
public:
/** Activate SPI hardware. */
void activate() {}
/** Initialize the SPI bus. */
virtual void begin() = 0;
/** Initialize the SPI bus.
*
* \param[in] spiConfig SD card configuration.
*/
void begin(SdSpiConfig spiConfig) {
m_spi = spiConfig.spiPort;
if (m_spi) m_spi->begin();
(void)spiConfig;
begin();
}
/** Deactivate SPI hardware. */
void deactivate() {}
@@ -95,14 +53,14 @@ class SdSoftSpiDriver {
*
* \return The byte.
*/
uint8_t receive() {return m_spi ? m_spi->receive() : 0XFF;}
virtual uint8_t receive() = 0;
/** Receive multiple bytes.
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
uint8_t receive(uint8_t* buf, size_t count) {
for (size_t i = 0; i < count; i++) {
buf[i] = receive();
@@ -113,7 +71,7 @@ class SdSoftSpiDriver {
*
* \param[in] data Byte to send
*/
void send(uint8_t data) {if (m_spi) m_spi->send(data);}
virtual void send(uint8_t data) = 0;
/** Send multiple bytes.
*
* \param[in] buf Buffer for data to be sent.
@@ -131,10 +89,31 @@ class SdSoftSpiDriver {
void setSckSpeed(uint32_t maxSck) {
(void)maxSck;
}

};
//------------------------------------------------------------------------------
/**
* \class SoftSpiDriver
* \brief Class for external soft SPI.
*/
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
class SoftSpiDriver : public SdSpiSoftDriver {
public:
/** Initialize the SPI bus. */
void begin() {m_spi.begin();}
/** Receive a byte.
*
* \return The byte.
*/
uint8_t receive() {return m_spi.receive();}
/** Send a byte.
*
* \param[in] data Byte to send
*/
void send(uint8_t data) {m_spi.send(data);}
private:
SoftSPIClass* m_spi;
SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi;
};

/** Typedef for use of SdSoftSpiDriver */
typedef SdSoftSpiDriver SdSpiDriver;
typedef SdSpiSoftDriver SdSpiDriver;
#endif // SdSpiSoftDriver_h

Завантаження…
Відмінити
Зберегти