@@ -1,11 +1,5 @@ | |||
### Warning: This beta is for testing with Particle IoT mesh devices. | |||
This version of SdFat has been modified to use standard POSIX/Linux | |||
definitions of open flags from fcntl.h. | |||
Open flags are access modes, O_RDONLY, O_RDWR, O_WRONLY, and modifiers | |||
O_APPEND, O_CREAT, O_EXCL, O_SYNC, O_TRUNC. | |||
Rename this folder SdFat and place it in the standard place for libraries. | |||
I tested with a particle CLI project with a SdFat in a lib | |||
@@ -20,6 +14,33 @@ SdFat | |||
src: | |||
SdFatMod.ino | |||
``` | |||
Changess Version 1.0.10: | |||
Added custom Particle driver to use DMA and allow use of SPI1. | |||
To use SPI1 declare SdFat/SdFatEX class like this: | |||
``` | |||
SdFat sd1(&SPI1); | |||
// or | |||
SdFatEX sd1(&SPI1); | |||
``` | |||
Changed STM32 use of SPI ports. See STM32Test example. | |||
To use second SPI port: | |||
``` | |||
// Use second SPI port | |||
SPIClass SPI_2(2); | |||
SdFat sd2(&SPI_2); | |||
``` | |||
Changes Version 1.0.9: | |||
This version of SdFat has been modified to use standard POSIX/Linux | |||
definitions of open flags from fcntl.h. | |||
Open flags are access modes, O_RDONLY, O_RDWR, O_WRONLY, and modifiers | |||
O_APPEND, O_CREAT, O_EXCL, O_SYNC, O_TRUNC. | |||
The mods required changing the type for open flags from uint8_t to int so | |||
bugs are likely if any uint8_t local variables were missed. |
@@ -9,13 +9,15 @@ | |||
// set ENABLE_EXTENDED_TRANSFER_CLASS non-zero to use faster EX classes | |||
// Use first SPI port | |||
SdFat sd1(1); | |||
// SdFatEX sd1(1); | |||
SdFat sd1; | |||
// SdFatEX sd1; | |||
const uint8_t SD1_CS = PA4; // chip select for sd1 | |||
// Use second SPI port | |||
SdFat sd2(2); | |||
// SdFatEX sd2(2); | |||
SPIClass SPI_2(2); | |||
SdFat sd2(&SPI_2); | |||
// SdFatEX sd2(&SPI_2); | |||
const uint8_t SD2_CS = PB12; // chip select for sd2 | |||
const uint8_t BUF_DIM = 100; | |||
@@ -170,4 +172,4 @@ void setup() { | |||
Serial.println(F("Done")); | |||
} | |||
//------------------------------------------------------------------------------ | |||
void loop() {} | |||
void loop() {} |
@@ -110,7 +110,7 @@ void loop() { | |||
while (!Serial.available()) { | |||
SysCall::yield(); | |||
} | |||
cout << F("chipSelect: ") << int(chipSelect) << endl; | |||
cout << F("FreeStack: ") << FreeStack() << endl; | |||
#if USE_SDIO |
@@ -1,5 +1,5 @@ | |||
/** | |||
* Copyright (c) 20011-2017 Bill Greiman | |||
* Copyright (c) 20011-2018 Bill Greiman | |||
* This file is part of the SdFat library for SD memory cards. | |||
* | |||
* MIT License | |||
@@ -24,7 +24,7 @@ | |||
*/ | |||
/** | |||
\mainpage Arduino %SdFat Library | |||
<CENTER>Copyright © 2012, 2013, 2014, 2015, 2016 by William Greiman | |||
<CENTER>Copyright © 2012-2018 by William Greiman | |||
</CENTER> | |||
\section Intro Introduction |
@@ -1,5 +1,5 @@ | |||
name=SdFat | |||
version=1.0.9 | |||
version=1.0.10 | |||
author=Bill Greiman <fat16lib@sbcglobal.net> | |||
maintainer=Bill Greiman <fat16lib@sbcglobal.net> | |||
sentence=FAT16/FAT32 file system for SD cards. |
@@ -505,36 +505,36 @@ bool FatFile::openCachedEntry(FatFile* dirFile, uint16_t dirIndex, | |||
m_attr |= FILE_ATTR_FILE; | |||
} | |||
m_lfnOrd = lfnOrd; | |||
switch(oflag & O_ACCMODE){ | |||
switch (oflag & O_ACCMODE) { | |||
case O_RDONLY: | |||
if (oflag & O_TRUNC) { | |||
DBG_FAIL_MACRO; | |||
goto fail; | |||
goto fail; | |||
} | |||
m_flags = F_READ; | |||
break; | |||
case O_RDWR: | |||
m_flags = F_READ | F_WRITE; | |||
break; | |||
case O_WRONLY: | |||
m_flags = F_WRITE; | |||
m_flags = F_WRITE; | |||
break; | |||
default: | |||
DBG_FAIL_MACRO; | |||
goto fail; | |||
} | |||
if (m_flags & F_WRITE) { | |||
if (isSubDir() || isReadOnly()) { | |||
DBG_FAIL_MACRO; | |||
goto fail; | |||
} | |||
} | |||
m_flags |= (oflag & O_APPEND ? F_APPEND : 0) | (oflag & O_SYNC ? F_SYNC : 0); | |||
m_dirBlock = m_vol->cacheBlockNumber(); |
@@ -263,9 +263,9 @@ class FatVolume { | |||
//------------------------------------------------------------------------------ | |||
private: | |||
// Allow FatFile and FatCache access to FatVolume private functions. | |||
friend class FatCache; | |||
friend class FatFile; | |||
friend class FatFileSystem; | |||
friend class FatCache; ///< Allow access to FatVolume. | |||
friend class FatFile; ///< Allow access to FatVolume. | |||
friend class FatFileSystem; ///< Allow access to FatVolume. | |||
//------------------------------------------------------------------------------ | |||
BlockDriver* m_blockDev; // block device | |||
uint8_t m_blocksPerCluster; // Cluster size in blocks. |
@@ -101,19 +101,19 @@ bool StdioStream::fopen(const char* path, const char* mode) { | |||
case 'a': | |||
m = O_WRONLY; | |||
oflag = O_CREAT | O_APPEND; | |||
m_status = S_SWR; | |||
m_status = S_SWR; | |||
break; | |||
case 'r': | |||
m = O_RDONLY; | |||
oflag = 0; | |||
m_status = S_SRD; | |||
m_status = S_SRD; | |||
break; | |||
case 'w': | |||
m = O_WRONLY; | |||
oflag = O_CREAT | O_TRUNC; | |||
m_status = S_SWR; | |||
m_status = S_SWR; | |||
break; | |||
default: | |||
@@ -236,28 +236,6 @@ int32_t StdioStream::ftell() { | |||
//------------------------------------------------------------------------------ | |||
size_t StdioStream::fwrite(const void* ptr, size_t size, size_t count) { | |||
return write(ptr, count*size) < 0 ? EOF : count; | |||
#if 0 //////////////////////////////////////////////////////////////////////////////////// | |||
const uint8_t* src = static_cast<const uint8_t*>(ptr); | |||
size_t total = count*size; | |||
if (total == 0) { | |||
return 0; | |||
} | |||
size_t todo = total; | |||
while (todo > m_w) { | |||
memcpy(m_p, src, m_w); | |||
m_p += m_w; | |||
src += m_w; | |||
todo -= m_w; | |||
if (!flushBuf()) { | |||
return (total - todo)/size; | |||
} | |||
} | |||
memcpy(m_p, src, todo); | |||
m_p += todo; | |||
m_w -= todo; | |||
return count; | |||
#endif ////////////////////////////////////////////////////////////////////////////////// | |||
} | |||
//------------------------------------------------------------------------------ | |||
int StdioStream::write(const void* buf, size_t count) { |
@@ -81,6 +81,7 @@ typedef enum { | |||
SD_CARD_ERROR_WRITE, | |||
SD_CARD_ERROR_WRITE_FIFO, | |||
SD_CARD_ERROR_WRITE_START, | |||
SD_CARD_ERROR_FLASH_PROGRAMMING, | |||
SD_CARD_ERROR_WRITE_TIMEOUT, | |||
// Misc errors. | |||
@@ -124,9 +125,9 @@ const uint16_t SD_INIT_TIMEOUT = 2000; | |||
/** erase timeout ms */ | |||
const uint16_t SD_ERASE_TIMEOUT = 10000; | |||
/** read timeout ms */ | |||
const uint16_t SD_READ_TIMEOUT = 300; | |||
const uint16_t SD_READ_TIMEOUT = 1000; | |||
/** write time out ms */ | |||
const uint16_t SD_WRITE_TIMEOUT = 600; | |||
const uint16_t SD_WRITE_TIMEOUT = 2000; | |||
//------------------------------------------------------------------------------ | |||
// SD card commands | |||
/** GO_IDLE_STATE - init card in spi mode if CS low */ |
@@ -543,7 +543,7 @@ bool SdSpiCard::writeBlock(uint32_t blockNumber, const uint8_t* src) { | |||
#if CHECK_FLASH_PROGRAMMING | |||
// wait for flash programming to complete | |||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) { | |||
error(SD_CARD_ERROR_WRITE_TIMEOUT); | |||
error(SD_CARD_ERROR_FLASH_PROGRAMMING); | |||
goto fail; | |||
} | |||
// response is r2 so get and check two bytes for nonzero |
@@ -37,7 +37,7 @@ | |||
#endif // INCLUDE_SDIOS | |||
//------------------------------------------------------------------------------ | |||
/** SdFat version */ | |||
#define SD_FAT_VERSION "1.0.9" | |||
#define SD_FAT_VERSION "1.0.10" | |||
//============================================================================== | |||
/** | |||
* \class SdBaseFile | |||
@@ -311,13 +311,13 @@ class SdFat : public SdFileSystem<SdSpiCard> { | |||
public: | |||
#if IMPLEMENT_SPI_PORT_SELECTION || defined(DOXYGEN) | |||
SdFat() { | |||
m_spi.setPortNumber(0); | |||
m_spi.setPort(nullptr); | |||
} | |||
/** Constructor with SPI port selection. | |||
* \param[in] spiPort SPI port number. | |||
*/ | |||
explicit SdFat(uint8_t spiPort) { | |||
m_spi.setPortNumber(spiPort); | |||
explicit SdFat(SPIClass* spiPort) { | |||
m_spi.setPort(spiPort); | |||
} | |||
#endif // IMPLEMENT_SPI_PORT_SELECTION | |||
/** Initialize SD card and file system. | |||
@@ -444,13 +444,13 @@ class SdFatEX : public SdFileSystem<SdSpiCardEX> { | |||
public: | |||
#if IMPLEMENT_SPI_PORT_SELECTION || defined(DOXYGEN) | |||
SdFatEX() { | |||
m_spi.setPortNumber(0); | |||
m_spi.setPort(nullptr); | |||
} | |||
/** Constructor with SPI port selection. | |||
* \param[in] spiPort SPI port number. | |||
*/ | |||
explicit SdFatEX(uint8_t spiPort) { | |||
m_spi.setPortNumber(spiPort); | |||
explicit SdFatEX(SPIClass* spiPort) { | |||
m_spi.setPort(spiPort); | |||
} | |||
#endif // IMPLEMENT_SPI_PORT_SELECTION | |||
/** Initialize SD card and file system. |
@@ -69,14 +69,16 @@ | |||
* the SPI bus may not be shared with other devices in this mode. | |||
*/ | |||
#define ENABLE_EXTENDED_TRANSFER_CLASS 0 | |||
//----------------------------------------------------------------------------- | |||
//------------------------------------------------------------------------------ | |||
/** | |||
* If the symbol USE_STANDARD_SPI_LIBRARY is nonzero, the classes SdFat and | |||
* SdFatEX use the standard Arduino SPI.h library. If USE_STANDARD_SPI_LIBRARY | |||
* is zero, an optimized custom SPI driver is used if it exists. | |||
* If the symbol USE_STANDARD_SPI_LIBRARY is zero, an optimized custom SPI | |||
* driver is used if it exists. If the symbol USE_STANDARD_SPI_LIBRARY is | |||
* one, the standard Arduino SPI.h library is used with SPI. If the symbol | |||
* USE_STANDARD_SPI_LIBRARY is two, the SPI port can be selected with the | |||
* constructors SdFat(SPIClass* spiPort) and SdFatEX(SPIClass* spiPort). | |||
*/ | |||
#define USE_STANDARD_SPI_LIBRARY 0 | |||
//----------------------------------------------------------------------------- | |||
//------------------------------------------------------------------------------ | |||
/** | |||
* If the symbol ENABLE_SOFTWARE_SPI_CLASS is nonzero, the class SdFatSoftSpi | |||
* will be defined. If ENABLE_EXTENDED_TRANSFER_CLASS is also nonzero, | |||
@@ -86,14 +88,14 @@ | |||
//------------------------------------------------------------------------------ | |||
/** If the symbol USE_FCNTL_H is nonzero, open flags for access modes O_RDONLY, | |||
* O_WRONLY, O_RDWR and the open modifiers O_APPEND, O_CREAT, O_EXCL, O_SYNC | |||
* will be defined by including the system file fcntl.h. | |||
* will be defined by including the system file fcntl.h. | |||
*/ | |||
#if defined(__AVR__) | |||
// AVR fcntl.h does not define open flags. | |||
#define USE_FCNTL_H 0 | |||
#elif defined(PLATFORM_ID) | |||
// Particle boards - use fcntl.h. | |||
#define USE_FCNTL_H 1 | |||
#define USE_FCNTL_H 1 | |||
#elif defined(__arm__) | |||
// ARM gcc defines open flags. | |||
#define USE_FCNTL_H 1 | |||
@@ -102,7 +104,7 @@ | |||
#endif // defined(__AVR__) | |||
//------------------------------------------------------------------------------ | |||
/** | |||
* If CHECK_FLASH_PROGRAMMING is zero, overlap of single sector flash | |||
* If CHECK_FLASH_PROGRAMMING is zero, overlap of single sector flash | |||
* programming and other operations will be allowed for faster write | |||
* performance. | |||
* | |||
@@ -207,7 +209,7 @@ | |||
/** | |||
* Determine the default SPI configuration. | |||
*/ | |||
#if defined(__STM32F1__) || defined(__STM32F4__) | |||
#if defined(__STM32F1__) || defined(__STM32F4__) || defined(PLATFORM_ID) | |||
// has multiple SPI ports | |||
#define SD_HAS_CUSTOM_SPI 2 | |||
#elif defined(__AVR__)\ | |||
@@ -223,9 +225,9 @@ | |||
/** | |||
* Check if API to select HW SPI port is needed. | |||
*/ | |||
#if (USE_STANDARD_SPI_LIBRARY || SD_HAS_CUSTOM_SPI < 2) | |||
#define IMPLEMENT_SPI_PORT_SELECTION 0 | |||
#else // USE_STANDARD_SPI_LIBRARY | |||
#if USE_STANDARD_SPI_LIBRARY > 1 || SD_HAS_CUSTOM_SPI > 1 | |||
#define IMPLEMENT_SPI_PORT_SELECTION 1 | |||
#endif // USE_STANDARD_SPI_LIBRARY | |||
#else // IMPLEMENT_SPI_PORT_SELECTION | |||
#define IMPLEMENT_SPI_PORT_SELECTION 0 | |||
#endif // IMPLEMENT_SPI_PORT_SELECTION | |||
#endif // SdFatConfig_h |
@@ -32,12 +32,12 @@ | |||
#include "SPI.h" | |||
#include "SdSpiBaseDriver.h" | |||
#include "SdFatConfig.h" | |||
//----------------------------------------------------------------------------- | |||
//------------------------------------------------------------------------------ | |||
/** SDCARD_SPI is defined if board has built-in SD card socket */ | |||
#ifndef SDCARD_SPI | |||
#define SDCARD_SPI SPI | |||
#endif // SDCARD_SPI | |||
//----------------------------------------------------------------------------- | |||
//------------------------------------------------------------------------------ | |||
/** | |||
* \class SdSpiLibDriver | |||
* \brief SdSpiLibDriver - use standard SPI library. | |||
@@ -48,6 +48,63 @@ class SdSpiLibDriver : public SdSpiBaseDriver { | |||
class SdSpiLibDriver { | |||
#endif // ENABLE_SOFTWARE_SPI_CLASS | |||
public: | |||
#if IMPLEMENT_SPI_PORT_SELECTION | |||
/** Activate SPI hardware. */ | |||
void activate() { | |||
m_spi->beginTransaction(m_spiSettings); | |||
} | |||
/** Deactivate SPI hardware. */ | |||
void deactivate() { | |||
m_spi->endTransaction(); | |||
} | |||
/** Initialize the SPI bus. | |||
* | |||
* \param[in] csPin SD card chip select pin. | |||
*/ | |||
void begin(uint8_t csPin) { | |||
m_csPin = csPin; | |||
digitalWrite(csPin, HIGH); | |||
pinMode(csPin, OUTPUT); | |||
m_spi->begin(); | |||
} | |||
/** Receive a byte. | |||
* | |||
* \return The byte. | |||
*/ | |||
uint8_t receive() { | |||
return m_spi->transfer( 0XFF); | |||
} | |||
/** Receive multiple bytes. | |||
* | |||
* \param[out] buf Buffer to receive the data. | |||
* \param[in] n Number of bytes to receive. | |||
* | |||
* \return Zero for no error or nonzero error code. | |||
*/ | |||
uint8_t receive(uint8_t* buf, size_t n) { | |||
for (size_t i = 0; i < n; i++) { | |||
buf[i] = m_spi->transfer(0XFF); | |||
} | |||
return 0; | |||
} | |||
/** Send a byte. | |||
* | |||
* \param[in] data Byte to send | |||
*/ | |||
void send(uint8_t data) { | |||
m_spi->transfer(data); | |||
} | |||
/** Send multiple bytes. | |||
* | |||
* \param[in] buf Buffer for data to be sent. | |||
* \param[in] n Number of bytes to send. | |||
*/ | |||
void send(const uint8_t* buf, size_t n) { | |||
for (size_t i = 0; i < n; i++) { | |||
m_spi->transfer(buf[i]); | |||
} | |||
} | |||
#else // IMPLEMENT_SPI_PORT_SELECTION | |||
/** Activate SPI hardware. */ | |||
void activate() { | |||
SDCARD_SPI.beginTransaction(m_spiSettings); | |||
@@ -103,6 +160,7 @@ class SdSpiLibDriver { | |||
SDCARD_SPI.transfer(buf[i]); | |||
} | |||
} | |||
#endif // IMPLEMENT_SPI_PORT_SELECTION | |||
/** Set CS low. */ | |||
void select() { | |||
digitalWrite(m_csPin, LOW); | |||
@@ -118,12 +176,22 @@ class SdSpiLibDriver { | |||
void unselect() { | |||
digitalWrite(m_csPin, HIGH); | |||
} | |||
#if IMPLEMENT_SPI_PORT_SELECTION || defined(DOXYGEN) | |||
/** Set SPI port. | |||
* \param[in] spiPort Hardware SPI port. | |||
*/ | |||
void setPort(SPIClass* spiPort) { | |||
m_spi = spiPort ? spiPort : &SDCARD_SPI; | |||
} | |||
private: | |||
SPIClass* m_spi; | |||
#else // IMPLEMENT_SPI_PORT_SELECTION | |||
private: | |||
#endif // IMPLEMENT_SPI_PORT_SELECTION | |||
SPISettings m_spiSettings; | |||
uint8_t m_csPin; | |||
}; | |||
//----------------------------------------------------------------------------- | |||
//------------------------------------------------------------------------------ | |||
/** | |||
* \class SdSpiAltDriver | |||
* \brief Optimized SPI class for access to SD and SDHC flash memory cards. | |||
@@ -184,9 +252,11 @@ class SdSpiAltDriver { | |||
} | |||
#if IMPLEMENT_SPI_PORT_SELECTION || defined(DOXYGEN) | |||
/** Set SPI port number. | |||
* \param[in] portNumber Hardware SPI port number. | |||
* \param[in] spiPort Hardware SPI port. | |||
*/ | |||
void setPortNumber(uint8_t portNumber); | |||
void setPort(SPIClass* spiPort) { | |||
m_spi = spiPort ? spiPort : &SDCARD_SPI; | |||
} | |||
private: | |||
SPIClass* m_spi; | |||
#else // IMPLEMENT_SPI_PORT_SELECTION | |||
@@ -281,7 +351,7 @@ class SdSpiSoftDriver : public SdSpiBaseDriver { | |||
SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi; | |||
}; | |||
#endif // ENABLE_SOFTWARE_SPI_CLASS || defined(DOXYGEN) | |||
//----------------------------------------------------------------------------- | |||
//------------------------------------------------------------------------------ | |||
// Choose SPI driver for SdFat and SdFatEX classes. | |||
#if USE_STANDARD_SPI_LIBRARY || !SD_HAS_CUSTOM_SPI | |||
/** SdFat uses Arduino library SPI. */ | |||
@@ -299,7 +369,7 @@ typedef SdSpiBaseDriver SdSpiDriver; | |||
// Don't need virtual driver. | |||
typedef SdFatSpiDriver SdSpiDriver; | |||
#endif // ENABLE_SOFTWARE_SPI_CLASS | |||
//============================================================================= | |||
//============================================================================== | |||
// Use of in-line for AVR to save flash. | |||
#ifdef __AVR__ | |||
//------------------------------------------------------------------------------ |
@@ -0,0 +1,102 @@ | |||
/** | |||
* Copyright (c) 2011-2018 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. | |||
*/ | |||
#if defined(PLATFORM_ID) | |||
#include "SdSpiDriver.h" | |||
static volatile bool SPI_DMA_TransferCompleted = false; | |||
//----------------------------------------------------------------------------- | |||
static void SD_SPI_DMA_TransferComplete_Callback(void) { | |||
SPI_DMA_TransferCompleted = true; | |||
} | |||
//------------------------------------------------------------------------------ | |||
/** Set SPI options for access to SD/SDHC cards. | |||
* | |||
* \param[in] divisor SCK clock divider relative to the APB1 or APB2 clock. | |||
*/ | |||
void SdSpiAltDriver::activate() { | |||
m_spi->beginTransaction(m_spiSettings); | |||
} | |||
//------------------------------------------------------------------------------ | |||
/** Initialize the SPI bus. | |||
* | |||
* \param[in] chipSelectPin SD card chip select pin. | |||
*/ | |||
void SdSpiAltDriver::begin(uint8_t csPin) { | |||
m_csPin = csPin; | |||
pinMode(m_csPin, OUTPUT); | |||
digitalWrite(m_csPin, HIGH); | |||
m_spi->begin(); | |||
} | |||
//------------------------------------------------------------------------------ | |||
/** | |||
* End SPI transaction. | |||
*/ | |||
void SdSpiAltDriver::deactivate() { | |||
m_spi->endTransaction(); | |||
} | |||
//------------------------------------------------------------------------------ | |||
/** Receive a byte. | |||
* | |||
* \return The byte. | |||
*/ | |||
uint8_t SdSpiAltDriver::receive() { | |||
return m_spi->transfer(0XFF); | |||
} | |||
//------------------------------------------------------------------------------ | |||
/** Receive multiple bytes. | |||
* | |||
* \param[out] buf Buffer to receive the data. | |||
* \param[in] n Number of bytes to receive. | |||
* | |||
* \return Zero for no error or nonzero error code. | |||
*/ | |||
uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) { | |||
SPI_DMA_TransferCompleted = false; | |||
m_spi->transfer(0, buf, n, SD_SPI_DMA_TransferComplete_Callback); | |||
while (!SPI_DMA_TransferCompleted) {} | |||
return 0; | |||
} | |||
//------------------------------------------------------------------------------ | |||
/** Send a byte. | |||
* | |||
* \param[in] b Byte to send | |||
*/ | |||
void SdSpiAltDriver::send(uint8_t b) { | |||
m_spi->transfer(b); | |||
} | |||
//------------------------------------------------------------------------------ | |||
/** Send multiple bytes. | |||
* | |||
* \param[in] buf Buffer for data to be sent. | |||
* \param[in] n Number of bytes to send. | |||
*/ | |||
void SdSpiAltDriver::send(const uint8_t* buf , size_t n) { | |||
SPI_DMA_TransferCompleted = false; | |||
m_spi->transfer(const_cast<uint8_t*>(buf), 0, n, | |||
SD_SPI_DMA_TransferComplete_Callback); | |||
while (!SPI_DMA_TransferCompleted) {} | |||
} | |||
#endif // defined(PLATFORM_ID) |
@@ -167,7 +167,7 @@ uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) { | |||
int rtn = 0; | |||
#if USE_SAM3X_DMAC | |||
// clear overrun error | |||
uint32_t s = pSpi->SPI_SR; | |||
pSpi->SPI_SR; | |||
spiDmaRX(buf, n); | |||
spiDmaTX(0, n); | |||
@@ -213,6 +213,6 @@ void SdSpiAltDriver::send(const uint8_t* buf , size_t n) { | |||
#endif // #if USE_SAM3X_DMAC | |||
while ((pSpi->SPI_SR & SPI_SR_TXEMPTY) == 0) {} | |||
// leave RDR empty | |||
uint8_t b = pSpi->SPI_RDR; | |||
pSpi->SPI_RDR; | |||
} | |||
#endif // defined(__SAM3X8E__) || defined(__SAM3X8H__) |
@@ -32,17 +32,6 @@ | |||
#error Unknown STM32 type | |||
#endif // defined(__STM32F1__) | |||
//------------------------------------------------------------------------------ | |||
static SPIClass m_SPI1(1); | |||
#if BOARD_NR_SPI >= 2 | |||
static SPIClass m_SPI2(2); | |||
#endif // BOARD_NR_SPI >= 2 | |||
#if BOARD_NR_SPI >= 3 | |||
static SPIClass m_SPI3(3); | |||
#endif // BOARD_NR_SPI >= 3 | |||
#if BOARD_NR_SPI > 3 | |||
#error BOARD_NR_SPI too large | |||
#endif | |||
//------------------------------------------------------------------------------ | |||
/** Set SPI options for access to SD/SDHC cards. | |||
* | |||
* \param[in] divisor SCK clock divider relative to the APB1 or APB2 clock. | |||
@@ -113,18 +102,4 @@ void SdSpiAltDriver::send(const uint8_t* buf , size_t n) { | |||
m_spi->write(const_cast<uint8*>(buf), n); | |||
#endif // USE_STM32_DMA | |||
} | |||
//------------------------------------------------------------------------------ | |||
void SdSpiAltDriver::setPortNumber(uint8_t portNumber) { | |||
m_spi = &m_SPI1; | |||
#if BOARD_NR_SPI >= 2 | |||
if (portNumber == 2) { | |||
m_spi = &m_SPI2; | |||
} | |||
#endif // BOARD_NR_SPI >= 2 | |||
#if BOARD_NR_SPI >= 3 | |||
if (portNumber == 3) { | |||
m_spi = &m_SPI3; | |||
} | |||
#endif // BOARD_NR_SPI >= 2 | |||
} | |||
#endif // defined(__STM32F1__) || defined(__STM32F4__) |