Restructure for RTOS use, getName mods, bug fixes
This commit is contained in:
parent
fb7415151b
commit
bab0061a51
60 changed files with 678 additions and 283 deletions
BIN
doc/html.zip
BIN
doc/html.zip
Binary file not shown.
|
|
@ -1,10 +1,10 @@
|
|||
name=SdFat
|
||||
version=2.1.1
|
||||
version=2.1.2
|
||||
license=MIT
|
||||
author=Bill Greiman <fat16lib@sbcglobal.net>
|
||||
maintainer=Bill Greiman <fat16lib@sbcglobal.net>
|
||||
sentence=FAT16/FAT32/exFAT file system.
|
||||
paragraph=FAT16/FAT32/exFAT file system.
|
||||
sentence=Provides access to SD memory cards.
|
||||
paragraph=The SdFat library supports FAT16, FAT32, and exFAT file systems on Standard SD, SDHC, and SDXC cards.
|
||||
category=Data Storage
|
||||
url=https://github.com/greiman/SdFat
|
||||
repository=https://github.com/greiman/SdFat.git
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@
|
|||
#define ExFatConfig_h
|
||||
#include "SdFatConfig.h"
|
||||
|
||||
#ifndef READ_ONLY
|
||||
#define READ_ONLY 0
|
||||
#endif // READ_ONLY
|
||||
#ifndef EXFAT_READ_ONLY
|
||||
#define EXFAT_READ_ONLY 0
|
||||
#endif // EXFAT_READ_ONLY
|
||||
|
||||
#endif // ExFatConfig_h
|
||||
|
|
|
|||
|
|
@ -361,13 +361,13 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
|
|||
}
|
||||
// Write, truncate, or at end is an error for a directory or read-only file.
|
||||
if ((oflag & (O_TRUNC | O_AT_END)) || (m_flags & FILE_FLAG_WRITE)) {
|
||||
if (isSubDir() || isReadOnly() || READ_ONLY) {
|
||||
if (isSubDir() || isReadOnly() || EXFAT_READ_ONLY) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
#if !READ_ONLY
|
||||
#if !EXFAT_READ_ONLY
|
||||
if (oflag & O_TRUNC) {
|
||||
if (!(m_flags & FILE_FLAG_WRITE)) {
|
||||
DBG_FAIL_MACRO;
|
||||
|
|
@ -381,14 +381,14 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
#endif // !READ_ONLY
|
||||
#endif // !EXFAT_READ_ONLY
|
||||
return true;
|
||||
|
||||
create:
|
||||
#if READ_ONLY
|
||||
#if EXFAT_READ_ONLY
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
#else // READ_ONLY
|
||||
#else // EXFAT_READ_ONLY
|
||||
// don't create unless O_CREAT and write
|
||||
if (!(oflag & O_CREAT) || !(modeFlags & FILE_FLAG_WRITE) || !fname) {
|
||||
DBG_WARN_MACRO;
|
||||
|
|
@ -471,7 +471,7 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
|
|||
}
|
||||
}
|
||||
return sync();
|
||||
#endif // READ_ONLY
|
||||
#endif // EXFAT_READ_ONLY
|
||||
|
||||
fail:
|
||||
// close file
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ class ExFatFile {
|
|||
return isOpen() ? m_error & WRITE_ERROR : true;
|
||||
}
|
||||
/**
|
||||
* Check for BlockDevice busy.
|
||||
* Check for FsBlockDevice busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#include "../common/DebugMacros.h"
|
||||
#include "ExFatLib.h"
|
||||
//==============================================================================
|
||||
#if READ_ONLY
|
||||
#if EXFAT_READ_ONLY
|
||||
bool ExFatFile::mkdir(ExFatFile* parent, const char* path, bool pFlag) {
|
||||
(void) parent;
|
||||
(void)path;
|
||||
|
|
@ -58,7 +58,7 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) {
|
|||
return false;
|
||||
}
|
||||
//==============================================================================
|
||||
#else // READ_ONLY
|
||||
#else // EXFAT_READ_ONLY
|
||||
//------------------------------------------------------------------------------
|
||||
static uint16_t exFatDirChecksum(const uint8_t* data, uint16_t checksum) {
|
||||
bool skip = data[0] == EXFAT_TYPE_FILE;
|
||||
|
|
@ -753,4 +753,4 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) {
|
|||
m_error |= WRITE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
#endif // READ_ONLY
|
||||
#endif // EXFAT_READ_ONLY
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ const uint32_t ROOT_CLUSTER = 4;
|
|||
#define writeMsg(pr, str) if (pr) pr->write(str)
|
||||
#endif // PRINT_FORMAT_PROGRESS
|
||||
//------------------------------------------------------------------------------
|
||||
bool ExFatFormatter::format(BlockDevice* dev, uint8_t* secBuf, print_t* pr) {
|
||||
bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
|
||||
#if !PRINT_FORMAT_PROGRESS
|
||||
(void)pr;
|
||||
#endif // !PRINT_FORMAT_PROGRESS
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
#ifndef ExFatFormatter_h
|
||||
#define ExFatFormatter_h
|
||||
#include "../common/BlockDevice.h"
|
||||
#include "../common/FsBlockDevice.h"
|
||||
/**
|
||||
* \class ExFatFormatter
|
||||
* \brief Format an exFAT volume.
|
||||
|
|
@ -40,7 +40,7 @@ class ExFatFormatter {
|
|||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool format(BlockDevice* dev, uint8_t* secBuf, print_t* pr = nullptr);
|
||||
bool format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr = nullptr);
|
||||
private:
|
||||
bool syncUpcase();
|
||||
bool writeUpcase(uint32_t sector);
|
||||
|
|
@ -49,7 +49,7 @@ class ExFatFormatter {
|
|||
uint32_t m_upcaseSector;
|
||||
uint32_t m_upcaseChecksum;
|
||||
uint32_t m_upcaseSize;
|
||||
BlockDevice* m_dev;
|
||||
FsBlockDevice* m_dev;
|
||||
uint8_t* m_secBuf;
|
||||
};
|
||||
#endif // ExFatFormatter_h
|
||||
|
|
|
|||
|
|
@ -83,9 +83,13 @@ size_t ExFatFile::getName7(char* name, size_t count) {
|
|||
}
|
||||
for (uint8_t in = 0; in < 15; in++) {
|
||||
uint16_t c = getLe16(dn->unicode + 2*in);
|
||||
if (c == 0 || (n + 1) >= count) {
|
||||
if (c == 0) {
|
||||
goto done;
|
||||
}
|
||||
if ((n + 1) >= count) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
name[n++] = c < 0X7F ? c : '?';
|
||||
}
|
||||
}
|
||||
|
|
@ -140,8 +144,8 @@ size_t ExFatFile::getName8(char* name, size_t count) {
|
|||
// Save space for zero byte.
|
||||
ptr = FsUtf::cpToMb(cp, str, end - 1);
|
||||
if (!ptr) {
|
||||
// Truncate name. Could goto fail.
|
||||
goto done;
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
str = ptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ uint32_t ExFatPartition::freeClusterCount() {
|
|||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ExFatPartition::init(BlockDevice* dev, uint8_t part) {
|
||||
bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part) {
|
||||
uint32_t volStart = 0;
|
||||
uint8_t* cache;
|
||||
pbs_t* pbs;
|
||||
|
|
|
|||
|
|
@ -29,10 +29,13 @@
|
|||
* \brief ExFatPartition include file.
|
||||
*/
|
||||
#include "../common/SysCall.h"
|
||||
#include "../common/BlockDevice.h"
|
||||
#include "../common/FsBlockDevice.h"
|
||||
#include "../common/FsCache.h"
|
||||
#include "../common/FsStructs.h"
|
||||
#include "ExFatConfig.h"
|
||||
/** Set EXFAT_READ_ONLY non-zero for read only */
|
||||
#ifndef EXFAT_READ_ONLY
|
||||
#define EXFAT_READ_ONLY 0
|
||||
#endif // EXFAT_READ_ONLY
|
||||
/** Type for exFAT partition */
|
||||
const uint8_t FAT_TYPE_EXFAT = 64;
|
||||
|
||||
|
|
@ -79,6 +82,13 @@ class ExFatPartition {
|
|||
uint32_t clusterCount() const {return m_clusterCount;}
|
||||
/** \return the cluster heap start sector. */
|
||||
uint32_t clusterHeapStartSector() const {return m_clusterHeapStartSector;}
|
||||
/** End access to volume
|
||||
* \return pointer to sector size buffer for format.
|
||||
*/
|
||||
uint8_t* end() {
|
||||
m_fatType = 0;
|
||||
return cacheClear();
|
||||
}
|
||||
/** \return the FAT length in sectors */
|
||||
uint32_t fatLength() const {return m_fatLength;}
|
||||
/** \return the FAT start sector number. */
|
||||
|
|
@ -96,9 +106,9 @@ class ExFatPartition {
|
|||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool init(BlockDevice* dev, uint8_t part);
|
||||
bool init(FsBlockDevice* dev, uint8_t part);
|
||||
/**
|
||||
* Check for BlockDevice busy.
|
||||
* Check for device busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
|
|
@ -142,7 +152,7 @@ class ExFatPartition {
|
|||
return m_dataCache.prepare(sector, option);
|
||||
#endif // USE_EXFAT_BITMAP_CACHE
|
||||
}
|
||||
void cacheInit(BlockDevice* dev) {
|
||||
void cacheInit(FsBlockDevice* dev) {
|
||||
#if USE_EXFAT_BITMAP_CACHE
|
||||
m_bitmapCache.init(dev);
|
||||
#endif // USE_EXFAT_BITMAP_CACHE
|
||||
|
|
@ -213,7 +223,7 @@ class ExFatPartition {
|
|||
uint32_t m_rootDirectoryCluster;
|
||||
uint32_t m_clusterMask;
|
||||
uint32_t m_bytesPerCluster;
|
||||
BlockDevice* m_blockDev;
|
||||
FsBlockDevice* m_blockDev;
|
||||
uint8_t m_fatType = 0;
|
||||
uint8_t m_sectorsPerClusterShift;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class ExFatVolume : public ExFatPartition {
|
|||
* \param[in] part partition to initialize.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(BlockDevice* dev, bool setCwv = true, uint8_t part = 1) {
|
||||
bool begin(FsBlockDevice* dev, bool setCwv = true, uint8_t part = 1) {
|
||||
if (!init(dev, part)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ class FatFile {
|
|||
return isOpen() ? m_error & WRITE_ERROR : true;
|
||||
}
|
||||
/**
|
||||
* Check for BlockDevice busy.
|
||||
* Check for device busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
|
|
@ -442,14 +442,6 @@ class FatFile {
|
|||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool mkdir(FatFile* dir, const char* path, bool pFlag = true);
|
||||
/** No longer implemented due to Long File Names.
|
||||
*
|
||||
* Use getName(char* name, size_t size).
|
||||
* \return a pointer to replacement suggestion.
|
||||
*/
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
const char* __attribute__((error("use getName(name, size)"))) name();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
/** Open a file in the volume root directory.
|
||||
*
|
||||
* \param[in] vol Volume where the file is located.
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ bool FatFile::makeUniqueSfn(FatLfn_t* fname) {
|
|||
const uint8_t FIRST_HASH_SEQ = 2; // min value is 2
|
||||
uint8_t pos = fname->seqPos;
|
||||
DirFat_t* dir;
|
||||
uint16_t hex;
|
||||
uint16_t hex = 0;
|
||||
|
||||
DBG_HALT_IF(!(fname->flags & FNAME_FLAG_LOST_CHARS));
|
||||
DBG_HALT_IF(fname->sfn[pos] != '~' && fname->sfn[pos + 1] != '1');
|
||||
|
|
@ -242,7 +242,7 @@ bool FatFile::makeUniqueSfn(FatLfn_t* fname) {
|
|||
#ifdef USE_LFN_HASH
|
||||
hex = Bernstein(fname->begin, fname->end, seq);
|
||||
#else
|
||||
hex = micros();
|
||||
hex += millis();
|
||||
#endif
|
||||
if (pos > 3) {
|
||||
// Make space in name for ~HHHH.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) {
|
|||
uint8_t checksum;
|
||||
#endif // SFN_OPEN_USES_CHKSUM
|
||||
uint8_t lfnOrd = 0;
|
||||
uint16_t emptyIndex;
|
||||
uint16_t emptyIndex = 0;
|
||||
uint16_t index = 0;
|
||||
DirFat_t* dir;
|
||||
DirLfn_t* ldir;
|
||||
|
|
@ -53,7 +53,7 @@ bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) {
|
|||
// At EOF if no error.
|
||||
break;
|
||||
}
|
||||
if (dir->name[0] == FAT_NAME_FREE || dir->name[0] == FAT_NAME_FREE) {
|
||||
if (dir->name[0] == FAT_NAME_DELETED || dir->name[0] == FAT_NAME_FREE) {
|
||||
if (!emptyFound) {
|
||||
emptyIndex = index;
|
||||
emptyFound = true;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ const uint16_t FAT16_ROOT_SECTOR_COUNT =
|
|||
#define writeMsg(str) if (m_pr) m_pr->write(str)
|
||||
#endif // PRINT_FORMAT_PROGRESS
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFormatter::format(BlockDevice* dev, uint8_t* secBuf, print_t* pr) {
|
||||
bool FatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
|
||||
bool rtn;
|
||||
m_dev = dev;
|
||||
m_secBuf = secBuf;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#ifndef FatFormatter_h
|
||||
#define FatFormatter_h
|
||||
#include "../common/SysCall.h"
|
||||
#include "../common/BlockDevice.h"
|
||||
#include "../common/FsBlockDevice.h"
|
||||
/**
|
||||
* \class FatFormatter
|
||||
* \brief Format a FAT volume.
|
||||
|
|
@ -41,7 +41,7 @@ class FatFormatter {
|
|||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool format(BlockDevice* dev, uint8_t* secBuffer, print_t* pr = nullptr);
|
||||
bool format(FsBlockDevice* dev, uint8_t* secBuffer, print_t* pr = nullptr);
|
||||
|
||||
private:
|
||||
bool initFatDir(uint8_t fatType, uint32_t sectorCount);
|
||||
|
|
@ -56,7 +56,7 @@ class FatFormatter {
|
|||
uint32_t m_relativeSectors;
|
||||
uint32_t m_sectorCount;
|
||||
uint32_t m_totalSectors;
|
||||
BlockDevice* m_dev;
|
||||
FsBlockDevice* m_dev;
|
||||
print_t* m_pr;
|
||||
uint8_t* m_secBuf;
|
||||
uint16_t m_reservedSectorCount;
|
||||
|
|
|
|||
|
|
@ -52,8 +52,7 @@ size_t FatFile::getName(char* name, size_t size) {
|
|||
size_t FatFile::getName7(char* name, size_t size) {
|
||||
FatFile dir;
|
||||
DirLfn_t* ldir;
|
||||
char* ptr = name;
|
||||
char* end = ptr + size;
|
||||
size_t n = 0;
|
||||
if (!isOpen()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
|
|
@ -78,15 +77,19 @@ size_t FatFile::getName7(char* name, size_t size) {
|
|||
}
|
||||
for (uint8_t i = 0; i < 13; i++) {
|
||||
uint16_t c = getLfnChar(ldir, i);
|
||||
if (c == 0 || (ptr + 1) == end) {
|
||||
if (c == 0) {
|
||||
goto done;
|
||||
}
|
||||
*ptr++ = c >= 0X7F ? '?' : c;
|
||||
if ((n + 1) >= size) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
name[n++] = c >= 0X7F ? '?' : c;
|
||||
}
|
||||
}
|
||||
done:
|
||||
*ptr = '\0';
|
||||
return ptr - name;
|
||||
name[n] = 0;
|
||||
return n;
|
||||
|
||||
fail:
|
||||
name[0] = '\0';
|
||||
|
|
@ -147,8 +150,8 @@ size_t FatFile::getName8(char* name, size_t size) {
|
|||
// Save space for zero byte.
|
||||
ptr = FsUtf::cpToMb(cp, str, end - 1);
|
||||
if (!ptr) {
|
||||
// Truncate name. Could goto fail.
|
||||
goto done;
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
str = ptr;
|
||||
}
|
||||
|
|
@ -205,8 +208,9 @@ size_t FatFile::getSFN(char* name, size_t size) {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if ((j + 1u) == size) {
|
||||
break;
|
||||
if ((j + 1u) >= size) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
name[j++] = c;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ int32_t FatPartition::freeClusterCount() {
|
|||
return -1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatPartition::init(BlockDevice* dev, uint8_t part) {
|
||||
bool FatPartition::init(FsBlockDevice* dev, uint8_t part) {
|
||||
uint32_t clusterCount;
|
||||
uint32_t totalSectors;
|
||||
uint32_t volumeStartSector = 0;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
#include <stddef.h>
|
||||
#include "../common/SysCall.h"
|
||||
#include "../common/BlockDevice.h"
|
||||
#include "../common/FsBlockDevice.h"
|
||||
#include "../common/FsCache.h"
|
||||
#include "../common/FsStructs.h"
|
||||
|
||||
|
|
@ -107,6 +107,13 @@ class FatPartition {
|
|||
uint32_t dataStartSector() const {
|
||||
return m_dataStartSector;
|
||||
}
|
||||
/** End access to volume
|
||||
* \return pointer to sector size buffer for format.
|
||||
*/
|
||||
uint8_t* end() {
|
||||
m_fatType = 0;
|
||||
return cacheClear();
|
||||
}
|
||||
/** \return The number of File Allocation Tables. */
|
||||
uint8_t fatCount() const {
|
||||
return 2;
|
||||
|
|
@ -126,7 +133,7 @@ class FatPartition {
|
|||
int32_t freeClusterCount();
|
||||
/** Initialize a FAT partition.
|
||||
*
|
||||
* \param[in] dev BlockDevice for this partition.
|
||||
* \param[in] dev FsBlockDevice for this partition.
|
||||
* \param[in] part The partition to be used. Legal values for \a part are
|
||||
* 1-4 to use the corresponding partition on a device formatted with
|
||||
* a MBR, Master Boot Record, or zero if the device is formatted as
|
||||
|
|
@ -134,7 +141,7 @@ class FatPartition {
|
|||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool init(BlockDevice* dev, uint8_t part = 1);
|
||||
bool init(FsBlockDevice* dev, uint8_t part = 1);
|
||||
/** \return The number of entries in the root directory for FAT16 volumes. */
|
||||
uint16_t rootDirEntryCount() const {
|
||||
return m_rootDirEntryCount;
|
||||
|
|
@ -158,7 +165,7 @@ class FatPartition {
|
|||
return fatGet(n, v);
|
||||
}
|
||||
/**
|
||||
* Check for BlockDevice busy.
|
||||
* Check for FsBlockDevice busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
|
|
@ -179,7 +186,7 @@ class FatPartition {
|
|||
static const uint16_t m_bytesPerSector = 1 << m_bytesPerSectorShift;
|
||||
static const uint16_t m_sectorMask = m_bytesPerSector - 1;
|
||||
//----------------------------------------------------------------------------
|
||||
BlockDevice* m_blockDev; // sector device
|
||||
FsBlockDevice* m_blockDev; // sector device
|
||||
uint8_t m_sectorsPerCluster; // Cluster size in sectors.
|
||||
uint8_t m_clusterSectorMask; // Mask to extract sector of cluster.
|
||||
uint8_t m_sectorsPerClusterShift; // Cluster count to sector count shift.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class FatVolume : public FatPartition {
|
|||
* \param[in] part partition to initialize.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(BlockDevice* dev, bool setCwv = true, uint8_t part = 1) {
|
||||
bool begin(FsBlockDevice* dev, bool setCwv = true, uint8_t part = 1) {
|
||||
if (!init(dev, part)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -72,7 +72,6 @@ class FatVolume : public FatPartition {
|
|||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool chdir(const char *path);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Test for the existence of a file.
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ class FsBaseFile {
|
|||
m_xFile ? m_xFile->getWriteError() : true;
|
||||
}
|
||||
/**
|
||||
* Check for BlockDevice busy.
|
||||
* Check for FsBlockDevice busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
|
|
@ -355,14 +355,6 @@ class FsBaseFile {
|
|||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool mkdir(FsBaseFile* dir, const char* path, bool pFlag = true);
|
||||
/** No longer implemented due to Long File Names.
|
||||
*
|
||||
* Use getName(char* name, size_t size).
|
||||
* \return a pointer to replacement suggestion.
|
||||
*/
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
const char* __attribute__((error("use getName(name, size)"))) name();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
/** Open a file or directory by name.
|
||||
*
|
||||
* \param[in] dir An open file instance for the directory containing
|
||||
|
|
@ -761,6 +753,14 @@ class FsBaseFile {
|
|||
return m_fFile ? length < (1ULL << 32) && m_fFile->truncate(length) :
|
||||
m_xFile ? m_xFile->truncate(length) : false;
|
||||
}
|
||||
/** Write a string to a file. Used by the Arduino Print class.
|
||||
* \param[in] str Pointer to the string.
|
||||
* Use getWriteError to check for errors.
|
||||
* \return count of characters written for success or -1 for failure.
|
||||
*/
|
||||
size_t write(const char* str) {
|
||||
return write(str, strlen(str));
|
||||
}
|
||||
/** Write a byte to a file. Required by the Arduino Print class.
|
||||
* \param[in] b the byte to be written.
|
||||
* Use getWriteError to check for errors.
|
||||
|
|
|
|||
57
src/FsLib/FsFormatter.h
Normal file
57
src/FsLib/FsFormatter.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2021 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.
|
||||
*/
|
||||
#ifndef FsFormatter_h
|
||||
#define FsFormatter_h
|
||||
#include "FatLib/FatLib.h"
|
||||
#include "ExFatLib/ExFatLib.h"
|
||||
/**
|
||||
* \class FsFormatter
|
||||
* \brief Format a exFAT/FAT volume.
|
||||
*/
|
||||
class FsFormatter {
|
||||
public:
|
||||
/**
|
||||
* Format a FAT volume.
|
||||
*
|
||||
* \param[in] dev Block device for volume.
|
||||
* \param[in] secBuffer buffer for writing to volume.
|
||||
* \param[in] pr Print device for progress output.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool format(FsBlockDevice* dev, uint8_t* secBuffer, print_t* pr = nullptr) {
|
||||
uint32_t sectorCount = dev->sectorCount();
|
||||
if (sectorCount == 0) {
|
||||
return false;
|
||||
}
|
||||
return sectorCount <= 67108864 ?
|
||||
m_fFmt.format(dev, secBuffer, pr) :
|
||||
m_xFmt.format(dev, secBuffer, pr);
|
||||
}
|
||||
private:
|
||||
FatFormatter m_fFmt;
|
||||
ExFatFormatter m_xFmt;
|
||||
};
|
||||
#endif // FsFormatter_h
|
||||
|
|
@ -30,4 +30,5 @@
|
|||
*/
|
||||
#include "FsVolume.h"
|
||||
#include "FsFile.h"
|
||||
#include "FsFormatter.h"
|
||||
#endif // FsLib_h
|
||||
|
|
|
|||
|
|
@ -25,16 +25,16 @@
|
|||
#include "FsLib.h"
|
||||
FsVolume* FsVolume::m_cwv = nullptr;
|
||||
//------------------------------------------------------------------------------
|
||||
bool FsVolume::begin(BlockDevice* blockDev) {
|
||||
bool FsVolume::begin(FsBlockDevice* blockDev, bool setCwv, uint8_t part) {
|
||||
m_blockDev = blockDev;
|
||||
m_fVol = nullptr;
|
||||
m_xVol = new (m_volMem) ExFatVolume;
|
||||
if (m_xVol && m_xVol->begin(m_blockDev, false)) {
|
||||
if (m_xVol && m_xVol->begin(m_blockDev, false, part)) {
|
||||
goto done;
|
||||
}
|
||||
m_xVol = nullptr;
|
||||
m_fVol = new (m_volMem) FatVolume;
|
||||
if (m_fVol && m_fVol->begin(m_blockDev, false)) {
|
||||
if (m_fVol && m_fVol->begin(m_blockDev, false, part)) {
|
||||
goto done;
|
||||
}
|
||||
m_cwv = nullptr;
|
||||
|
|
@ -42,7 +42,9 @@ bool FsVolume::begin(BlockDevice* blockDev) {
|
|||
return false;
|
||||
|
||||
done:
|
||||
m_cwv = this;
|
||||
if (setCwv || !m_cwv) {
|
||||
m_cwv = this;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -46,9 +46,11 @@ class FsVolume {
|
|||
/**
|
||||
* Initialize an FatVolume object.
|
||||
* \param[in] blockDev Device block driver.
|
||||
* \param[in] setCwv Set current working volume if true.
|
||||
* \param[in] part partition to initialize.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(BlockDevice* blockDev);
|
||||
bool begin(FsBlockDevice* blockDev, bool setCwv = true, uint8_t part = 1);
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
uint32_t __attribute__((error("use sectorsPerCluster()"))) blocksPerCluster();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
|
@ -86,10 +88,14 @@ class FsVolume {
|
|||
return m_fVol ? m_fVol->dataStartSector() :
|
||||
m_xVol ? m_xVol->clusterHeapStartSector() : 0;
|
||||
}
|
||||
/** free dynamic memory and end access to volume */
|
||||
void end() {
|
||||
/** End access to volume
|
||||
* \return pointer to sector size buffer for format.
|
||||
*/
|
||||
uint8_t* end() {
|
||||
m_fVol = nullptr;
|
||||
m_xVol = nullptr;
|
||||
static_assert(sizeof(m_volMem) >= 512, "m_volMem too small");
|
||||
return reinterpret_cast<uint8_t*>(m_volMem);
|
||||
}
|
||||
/** Test for the existence of a file in a directory
|
||||
*
|
||||
|
|
@ -119,7 +125,7 @@ class FsVolume {
|
|||
m_xVol ? m_xVol->freeClusterCount() : 0;
|
||||
}
|
||||
/**
|
||||
* Check for BlockDevice busy.
|
||||
* Check for device busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
|
|
@ -379,6 +385,6 @@ class FsVolume {
|
|||
static FsVolume* m_cwv;
|
||||
FatVolume* m_fVol = nullptr;
|
||||
ExFatVolume* m_xVol = nullptr;
|
||||
BlockDevice* m_blockDev;
|
||||
FsBlockDevice* m_blockDev;
|
||||
};
|
||||
#endif // FsVolume_h
|
||||
|
|
|
|||
|
|
@ -24,14 +24,16 @@
|
|||
*/
|
||||
#ifndef SdCardInterface_h
|
||||
#define SdCardInterface_h
|
||||
#include "../common/BlockDeviceInterface.h"
|
||||
#include "../common/FsBlockDeviceInterface.h"
|
||||
#include "SdCardInfo.h"
|
||||
/**
|
||||
* \class SdCardInterface
|
||||
* \brief Abstract interface for an SD card.
|
||||
*/
|
||||
class SdCardInterface : public BlockDeviceInterface {
|
||||
class SdCardInterface : public FsBlockDeviceInterface {
|
||||
public:
|
||||
/** end use of card */
|
||||
virtual void end() = 0;
|
||||
/** Erase a range of sectors.
|
||||
*
|
||||
* \param[in] firstSector The address of the first sector in the range.
|
||||
|
|
@ -46,6 +48,18 @@ class SdCardInterface : public BlockDeviceInterface {
|
|||
virtual uint32_t errorData() const = 0;
|
||||
/** \return true if card is busy. */
|
||||
virtual bool isBusy() = 0;
|
||||
/** \return false by default */
|
||||
virtual bool hasDedicatedSpi() {return false;}
|
||||
/** \return false by default */
|
||||
bool virtual isDedicatedSpi() {return false;}
|
||||
/** Set SPI sharing state
|
||||
* \param[in] value desired state.
|
||||
* \return false by default.
|
||||
*/
|
||||
virtual bool setDedicatedSpi(bool value) {
|
||||
(void)value;
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Read a card's CID register.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -665,7 +665,7 @@ bool DedicatedSpiCard::begin(SdSpiConfig spiConfig) {
|
|||
if (!SharedSpiCard::begin(spiConfig)) {
|
||||
return false;
|
||||
}
|
||||
m_sharedSpi = spiOptionShared(spiConfig.options);
|
||||
m_dedicatedSpi = spiOptionDedicated(spiConfig.options);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -687,18 +687,25 @@ bool DedicatedSpiCard::readSectors(
|
|||
}
|
||||
}
|
||||
m_curSector += ns;
|
||||
return m_sharedSpi ? readStop() : true;
|
||||
return m_dedicatedSpi ? true : readStop();
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::setDedicatedSpi(bool value) {
|
||||
if (!syncDevice()) {
|
||||
return false;
|
||||
}
|
||||
m_dedicatedSpi = value;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
if (m_sharedSpi) {
|
||||
return SharedSpiCard::writeSector(sector, src);
|
||||
} else {
|
||||
if (m_dedicatedSpi) {
|
||||
return writeSectors(sector, src, 1);
|
||||
}
|
||||
return SharedSpiCard::writeSector(sector, src);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::writeSectors(
|
||||
|
|
@ -715,7 +722,7 @@ bool DedicatedSpiCard::writeSectors(
|
|||
}
|
||||
}
|
||||
m_curSector += ns;
|
||||
return m_sharedSpi ? writeStop() : true;
|
||||
return m_dedicatedSpi ? true : writeStop();
|
||||
|
||||
fail:
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#if HAS_SDIO_CLASS
|
||||
class SharedSpiCard : public SdCardInterface {
|
||||
#elif USE_BLOCK_DEVICE_INTERFACE
|
||||
class SharedSpiCard : public BlockDeviceInterface {
|
||||
class SharedSpiCard : public FsBlockDeviceInterface {
|
||||
#else // HAS_SDIO_CLASS
|
||||
class SharedSpiCard {
|
||||
#endif // HAS_SDIO_CLASS
|
||||
|
|
@ -59,6 +59,10 @@ class SharedSpiCard {
|
|||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(SdSpiConfig spiConfig);
|
||||
/** End use of card */
|
||||
void end() {
|
||||
spiEnd();
|
||||
}
|
||||
/** Erase a range of sectors.
|
||||
*
|
||||
* \param[in] firstSector The address of the first sector in the range.
|
||||
|
|
@ -96,12 +100,16 @@ class SharedSpiCard {
|
|||
uint32_t errorData() const {
|
||||
return m_status;
|
||||
}
|
||||
/** \return false for shared class. */
|
||||
bool hasDedicatedSpi() {return false;}
|
||||
/**
|
||||
* Check for busy. MISO low indicates the card is busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
bool isBusy();
|
||||
/** \return false, can't be in dedicated state. */
|
||||
bool isDedicatedSpi() {return false;}
|
||||
/**
|
||||
* Read a card's CID register. The CID contains card identification
|
||||
* information such as Manufacturer ID, Product name, Product serial
|
||||
|
|
@ -189,6 +197,14 @@ class SharedSpiCard {
|
|||
// Use sectorCount(). cardSize() will be removed in the future.
|
||||
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
/** Set SPI sharing state
|
||||
* \param[in] value desired state.
|
||||
* \return false for shared card
|
||||
*/
|
||||
bool setDedicatedSpi(bool value) {
|
||||
(void)value;
|
||||
return false;
|
||||
}
|
||||
/** end a mult-sector transfer.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
|
|
@ -263,7 +279,6 @@ class SharedSpiCard {
|
|||
}
|
||||
bool waitReady(uint16_t ms);
|
||||
bool writeData(uint8_t token, const uint8_t* src);
|
||||
|
||||
#if SPI_DRIVER_SELECT < 2
|
||||
void spiActivate() {
|
||||
m_spiDriver.activate();
|
||||
|
|
@ -274,6 +289,9 @@ class SharedSpiCard {
|
|||
void spiDeactivate() {
|
||||
m_spiDriver.deactivate();
|
||||
}
|
||||
void spiEnd() {
|
||||
m_spiDriver.end();
|
||||
}
|
||||
uint8_t spiReceive() {
|
||||
return m_spiDriver.receive();
|
||||
}
|
||||
|
|
@ -300,6 +318,9 @@ class SharedSpiCard {
|
|||
void spiDeactivate() {
|
||||
m_spiDriverPtr->deactivate();
|
||||
}
|
||||
void spiEnd() {
|
||||
m_spiDriverPtr->end();
|
||||
}
|
||||
uint8_t spiReceive() {
|
||||
return m_spiDriverPtr->receive();
|
||||
}
|
||||
|
|
@ -317,7 +338,6 @@ class SharedSpiCard {
|
|||
}
|
||||
SdSpiDriver* m_spiDriverPtr;
|
||||
#endif // SPI_DRIVER_SELECT < 2
|
||||
|
||||
SdCsPin_t m_csPin;
|
||||
uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED;
|
||||
bool m_spiActive;
|
||||
|
|
@ -340,6 +360,10 @@ class DedicatedSpiCard : public SharedSpiCard {
|
|||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(SdSpiConfig spiConfig);
|
||||
/** \return true, can be in dedicaded state. */
|
||||
bool hasDedicatedSpi() {return true;}
|
||||
/** \return true if in dedicated SPI state. */
|
||||
bool isDedicatedSpi() {return m_dedicatedSpi;}
|
||||
/**
|
||||
* Read a 512 byte sector from an SD card.
|
||||
*
|
||||
|
|
@ -357,6 +381,11 @@ class DedicatedSpiCard : public SharedSpiCard {
|
|||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSectors(uint32_t sector, uint8_t* dst, size_t ns);
|
||||
/** Set SPI sharing state
|
||||
* \param[in] value desired state.
|
||||
* \return true for success else false;
|
||||
*/
|
||||
bool setDedicatedSpi(bool value);
|
||||
/**
|
||||
* Write a 512 byte sector to an SD card.
|
||||
*
|
||||
|
|
@ -377,7 +406,7 @@ class DedicatedSpiCard : public SharedSpiCard {
|
|||
|
||||
private:
|
||||
uint32_t m_curSector;
|
||||
bool m_sharedSpi = true;
|
||||
bool m_dedicatedSpi = false;
|
||||
};
|
||||
//==============================================================================
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
|
|
|
|||
|
|
@ -61,9 +61,9 @@ class SdioCard : public SdCardInterface {
|
|||
*/
|
||||
bool begin(SdioConfig sdioConfig);
|
||||
/** Disable an SDIO card.
|
||||
* \return false - not implemented.
|
||||
* not implemented.
|
||||
*/
|
||||
bool end() {return false;}
|
||||
void end() {}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
|
||||
|
|
|
|||
|
|
@ -572,7 +572,6 @@ static bool transferStop() {
|
|||
if (!cardCommand(CMD12_XFERTYP, 0)) {
|
||||
return sdError(SD_CARD_ERROR_CMD12);
|
||||
}
|
||||
// if (yieldTimeout(isBusyCMD13)) {
|
||||
if (yieldTimeout(isBusyDat)) {
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
|
|
@ -599,7 +598,7 @@ static bool yieldTimeout(bool (*fcn)()) {
|
|||
m_busyFcn = 0;
|
||||
return true;
|
||||
}
|
||||
SysCall::yield();
|
||||
yield();
|
||||
}
|
||||
m_busyFcn = 0;
|
||||
return false; // Caller will set errorCode.
|
||||
|
|
|
|||
136
src/SdFat.h
136
src/SdFat.h
|
|
@ -38,15 +38,15 @@
|
|||
#endif // INCLUDE_SDIOS
|
||||
//------------------------------------------------------------------------------
|
||||
/** SdFat version for cpp use. */
|
||||
#define SD_FAT_VERSION 20101
|
||||
#define SD_FAT_VERSION 20102
|
||||
/** SdFat version as string. */
|
||||
#define SD_FAT_VERSION_STR "2.1.1"
|
||||
#define SD_FAT_VERSION_STR "2.1.2"
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SdBase
|
||||
* \brief base SD file system template class.
|
||||
*/
|
||||
template <class Vol>
|
||||
template <class Vol, class Fmt>
|
||||
class SdBase : public Vol {
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -115,6 +115,14 @@ class SdBase : public Vol {
|
|||
return m_card && !m_card->errorCode();
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** End use of card. */
|
||||
void end() {
|
||||
Vol::end();
|
||||
if (m_card) {
|
||||
m_card->end();
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** %Print error info and halt.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
|
|
@ -128,7 +136,7 @@ class SdBase : public Vol {
|
|||
} else if (!Vol::fatType()) {
|
||||
pr->println(F("Check SD format."));
|
||||
}
|
||||
SysCall::halt();
|
||||
while (true) {}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** %Print error info and halt.
|
||||
|
|
@ -153,13 +161,51 @@ class SdBase : public Vol {
|
|||
errorHalt(pr);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Format SD card
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool format(print_t* pr = nullptr) {
|
||||
Fmt fmt;
|
||||
uint8_t* mem = Vol::end();
|
||||
if (!mem) {
|
||||
return false;
|
||||
}
|
||||
bool switchSpi = hasDedicatedSpi() && !isDedicatedSpi();
|
||||
if (switchSpi && !setDedicatedSpi(true)) {
|
||||
return 0;
|
||||
}
|
||||
bool rtn = fmt.format(card(), mem, pr);
|
||||
if (switchSpi && !setDedicatedSpi(false)) {
|
||||
return 0;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** \return the free cluster count. */
|
||||
uint32_t freeClusterCount() {
|
||||
bool switchSpi = hasDedicatedSpi() && !isDedicatedSpi();
|
||||
if (switchSpi && !setDedicatedSpi(true)) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t rtn = Vol::freeClusterCount();
|
||||
if (switchSpi && !setDedicatedSpi(false)) {
|
||||
return 0;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** \return true if can be in dedicated SPI state */
|
||||
bool hasDedicatedSpi() {return m_card ? m_card->hasDedicatedSpi() : false;}
|
||||
//----------------------------------------------------------------------------
|
||||
/** %Print error info and halt.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
*/
|
||||
void initErrorHalt(print_t* pr) {
|
||||
initErrorPrint(pr);
|
||||
SysCall::halt();
|
||||
while (true) {}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** %Print error info and halt.
|
||||
|
|
@ -177,7 +223,7 @@ class SdBase : public Vol {
|
|||
* \param[in] pr Print destination.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void initErrorHalt(Print* pr, const __FlashStringHelper* msg) {
|
||||
void initErrorHalt(print_t* pr, const __FlashStringHelper* msg) {
|
||||
pr->println(msg);
|
||||
initErrorHalt(pr);
|
||||
}
|
||||
|
|
@ -186,7 +232,7 @@ class SdBase : public Vol {
|
|||
*
|
||||
* \param[in] pr Print destination.
|
||||
*/
|
||||
void initErrorPrint(Print* pr) {
|
||||
void initErrorPrint(print_t* pr) {
|
||||
pr->println(F("begin() failed"));
|
||||
if (sdErrorCode()) {
|
||||
pr->println(F("Do not reformat the SD."));
|
||||
|
|
@ -197,6 +243,9 @@ class SdBase : public Vol {
|
|||
errorPrint(pr);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** \return true if in dedicated SPI state. */
|
||||
bool isDedicatedSpi() {return m_card ? m_card->isDedicatedSpi() : false;}
|
||||
//----------------------------------------------------------------------------
|
||||
/** %Print volume FAT/exFAT type.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
|
|
@ -241,7 +290,7 @@ class SdBase : public Vol {
|
|||
* \param[in] pr Print destination.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void errorPrint(Print* pr, const __FlashStringHelper* msg) {
|
||||
void errorPrint(print_t* pr, const __FlashStringHelper* msg) {
|
||||
pr->print(F("error: "));
|
||||
pr->println(msg);
|
||||
errorPrint(pr);
|
||||
|
|
@ -278,6 +327,17 @@ class SdBase : public Vol {
|
|||
/** \return SD card error data. */
|
||||
uint8_t sdErrorData() {return m_card ? m_card->errorData() : 0;}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set SPI sharing state
|
||||
* \param[in] value desired state.
|
||||
* \return true for success else false;
|
||||
*/
|
||||
bool setDedicatedSpi(bool value) {
|
||||
if (m_card) {
|
||||
return m_card->setDedicatedSpi(value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** \return pointer to base volume */
|
||||
Vol* vol() {return reinterpret_cast<Vol*>(this);}
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -341,7 +401,7 @@ class SdBase : public Vol {
|
|||
#endif // ENABLE_ARDUINO_SERIAL
|
||||
//----------------------------------------------------------------------------
|
||||
private:
|
||||
SdCard* m_card;
|
||||
SdCard* m_card = nullptr;
|
||||
SdCardFactory m_cardFactory;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -349,73 +409,27 @@ class SdBase : public Vol {
|
|||
* \class SdFat32
|
||||
* \brief SD file system class for FAT volumes.
|
||||
*/
|
||||
class SdFat32 : public SdBase<FatVolume> {
|
||||
class SdFat32 : public SdBase<FatVolume, FatFormatter> {
|
||||
public:
|
||||
/** Format a SD card FAT32/FAT16.
|
||||
*
|
||||
* \param[in] pr Optional Print information.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool format(print_t* pr = nullptr) {
|
||||
FatFormatter fmt;
|
||||
uint8_t* cache = cacheClear();
|
||||
if (!cache) {
|
||||
return false;
|
||||
}
|
||||
return fmt.format(card(), cache, pr);
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SdExFat
|
||||
* \brief SD file system class for exFAT volumes.
|
||||
*/
|
||||
class SdExFat : public SdBase<ExFatVolume> {
|
||||
class SdExFat : public SdBase<ExFatVolume, ExFatFormatter> {
|
||||
public:
|
||||
/** Format a SD card exFAT.
|
||||
*
|
||||
* \param[in] pr Optional Print information.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool format(print_t* pr = nullptr) {
|
||||
ExFatFormatter fmt;
|
||||
uint8_t* cache = cacheClear();
|
||||
if (!cache) {
|
||||
return false;
|
||||
}
|
||||
return fmt.format(card(), cache, pr);
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SdFs
|
||||
* \brief SD file system class for FAT16, FAT32, and exFAT volumes.
|
||||
*/
|
||||
class SdFs : public SdBase<FsVolume> {
|
||||
class SdFs : public SdBase<FsVolume, FsFormatter> {
|
||||
public:
|
||||
/** Format a SD card FAT or exFAT.
|
||||
*
|
||||
* \param[in] pr Optional Print information.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool format(print_t* pr = nullptr) {
|
||||
static_assert(sizeof(m_volMem) >= 512, "m_volMem too small");
|
||||
uint32_t sectorCount = card()->sectorCount();
|
||||
if (sectorCount == 0) {
|
||||
return false;
|
||||
}
|
||||
end();
|
||||
if (sectorCount > 67108864) {
|
||||
ExFatFormatter fmt;
|
||||
return fmt.format(card(), reinterpret_cast<uint8_t*>(m_volMem), pr);
|
||||
} else {
|
||||
FatFormatter fmt;
|
||||
return fmt.format(card(), reinterpret_cast<uint8_t*>(m_volMem), pr);
|
||||
}
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#if SDFAT_FILE_TYPE == 1
|
||||
#if SDFAT_FILE_TYPE == 1 || defined(DOXYGEN)
|
||||
/** Select type for SdFat. */
|
||||
typedef SdFat32 SdFat;
|
||||
/** Select type for SdBaseFile. */
|
||||
|
|
@ -435,11 +449,11 @@ typedef FsBaseFile SdBaseFile;
|
|||
#if defined __has_include
|
||||
#if __has_include(<FS.h>)
|
||||
#define HAS_INCLUDE_FS_H
|
||||
#warning File not defined because __has__include(FS.h)
|
||||
#warning File not defined because __has_include(FS.h)
|
||||
#endif // __has_include(<FS.h>)
|
||||
#endif // defined __has_include
|
||||
#ifndef HAS_INCLUDE_FS_H
|
||||
#if SDFAT_FILE_TYPE == 1
|
||||
#if SDFAT_FILE_TYPE == 1 || defined(DOXYGEN)
|
||||
/** Select type for File. */
|
||||
typedef File32 File;
|
||||
#elif SDFAT_FILE_TYPE == 2
|
||||
|
|
|
|||
|
|
@ -137,10 +137,10 @@
|
|||
#endif // SD_MAX_INIT_RATE_KHZ
|
||||
/**
|
||||
* Set USE_BLOCK_DEVICE_INTERFACE nonzero to use a generic block device.
|
||||
* This allow use of an external BlockDevice driver that is derived from
|
||||
* the BlockDeviceInterface like this:
|
||||
* This allow use of an external FsBlockDevice driver that is derived from
|
||||
* the FsBlockDeviceInterface like this:
|
||||
*
|
||||
* class UsbMscDriver : public BlockDeviceInterface {
|
||||
* class UsbMscDriver : public FsBlockDeviceInterface {
|
||||
* ... code for USB mass storage class driver.
|
||||
* };
|
||||
*
|
||||
|
|
@ -341,19 +341,6 @@ typedef uint8_t SdCsPin_t;
|
|||
#define ENDL_CALLS_FLUSH 0
|
||||
#endif // ENDL_CALLS_FLUSH
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Handle Watchdog Timer for WiFi modules.
|
||||
*
|
||||
* Yield will be called before accessing the SPI bus if it has been more
|
||||
* than WDT_YIELD_TIME_MILLIS milliseconds since the last yield call by SdFat.
|
||||
*/
|
||||
#if defined(PLATFORM_ID) || defined(ESP8266)
|
||||
// If Particle device or ESP8266 call yield.
|
||||
#define WDT_YIELD_TIME_MILLIS 100
|
||||
#else // defined(PLATFORM_ID) || defined(ESP8266)
|
||||
#define WDT_YIELD_TIME_MILLIS 0
|
||||
#endif // defined(PLATFORM_ID) || defined(ESP8266)
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set USE_SIMPLE_LITTLE_ENDIAN nonzero for little endian processors
|
||||
* with no memory alignment restrictions.
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ void SdSpiArduinoDriver::deactivate() {
|
|||
m_spi->endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::end() {
|
||||
m_spi->end();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdSpiArduinoDriver::receive() {
|
||||
return m_spi->transfer(0XFF);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,19 +27,23 @@
|
|||
// Use of in-line for AVR to save flash.
|
||||
#define nop asm volatile ("nop\n\t")
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiArduinoDriver::activate() {
|
||||
SPI.beginTransaction(m_spiSettings);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) {
|
||||
(void)spiConfig;
|
||||
SPI.begin();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiArduinoDriver::activate() {
|
||||
SPI.beginTransaction(m_spiSettings);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiArduinoDriver::deactivate() {
|
||||
SPI.endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiArduinoDriver::end() {
|
||||
SPI.end();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline uint8_t SdSpiArduinoDriver::receive() {
|
||||
return SPI.transfer(0XFF);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,10 +92,6 @@ class SdSpiDriverBareUno {
|
|||
public:
|
||||
/** Activate SPI hardware. */
|
||||
void activate() {}
|
||||
/** deactivate SPI driver. */
|
||||
void end() {}
|
||||
/** Deactivate SPI hardware. */
|
||||
void deactivate() {}
|
||||
/** Initialize the SPI bus.
|
||||
*
|
||||
* \param[in] spiConfig SD card configuration.
|
||||
|
|
@ -112,6 +108,10 @@ class SdSpiDriverBareUno {
|
|||
unoPinMode(UNO_SCK, OUTPUT);
|
||||
unoPinMode(UNO_MOSI, OUTPUT);
|
||||
}
|
||||
/** Deactivate SPI hardware. */
|
||||
void deactivate() {}
|
||||
/** deactivate SPI driver. */
|
||||
void end() {}
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ class SdSpiBaseClass {
|
|||
virtual void begin(SdSpiConfig config) = 0;
|
||||
/** Deactivate SPI hardware. */
|
||||
virtual void deactivate() {}
|
||||
/** deactivate SPI driver. */
|
||||
virtual void end() {}
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
|
|
|
|||
|
|
@ -50,16 +50,15 @@ const uint8_t SHARED_SPI = 0;
|
|||
const uint8_t DEDICATED_SPI = 1;
|
||||
/**
|
||||
* \param[in] opt option field of SdSpiConfig.
|
||||
* \return true for shared SPI.
|
||||
* \return true for dedicated SPI.
|
||||
*/
|
||||
inline bool spiOptionShared(uint8_t opt) {return !(opt & DEDICATED_SPI);}
|
||||
|
||||
inline bool spiOptionDedicated(uint8_t opt) {return opt & DEDICATED_SPI;}
|
||||
#else // ENABLE_DEDICATED_SPI
|
||||
/**
|
||||
* \param[in] opt option field of SdSpiConfig.
|
||||
* \return true for shared SPI.
|
||||
* \return true for dedicated SPI.
|
||||
*/
|
||||
inline bool spiOptionShared(uint8_t opt) {(void)opt; return true;}
|
||||
inline bool spiOptionDedicated(uint8_t opt) {(void)opt; return false;}
|
||||
#endif // ENABLE_DEDICATED_SPI
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPISettings for SCK frequency in Hz. */
|
||||
|
|
|
|||
|
|
@ -62,25 +62,6 @@ static bool dmac_channel_transfer_done(uint32_t ul_num) {
|
|||
return (DMAC->DMAC_CHSR & (DMAC_CHSR_ENA0 << ul_num)) ? false : true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) {
|
||||
(void)spiConfig;
|
||||
SPI.begin();
|
||||
#if USE_SAM3X_DMAC
|
||||
pmc_enable_periph_clk(ID_DMAC);
|
||||
dmac_disable();
|
||||
DMAC->DMAC_GCFG = DMAC_GCFG_ARB_CFG_FIXED;
|
||||
dmac_enable();
|
||||
#if USE_SAM3X_BUS_MATRIX_FIX
|
||||
MATRIX->MATRIX_WPMR = 0x4d415400;
|
||||
MATRIX->MATRIX_MCFG[1] = 1;
|
||||
MATRIX->MATRIX_MCFG[2] = 1;
|
||||
MATRIX->MATRIX_SCFG[0] = 0x01000010;
|
||||
MATRIX->MATRIX_SCFG[1] = 0x01000010;
|
||||
MATRIX->MATRIX_SCFG[7] = 0x01000010;
|
||||
#endif // USE_SAM3X_BUS_MATRIX_FIX
|
||||
#endif // USE_SAM3X_DMAC
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// start RX DMA
|
||||
static void spiDmaRX(uint8_t* dst, uint16_t count) {
|
||||
dmac_channel_disable(SPI_DMAC_RX_CH);
|
||||
|
|
@ -141,10 +122,33 @@ void SdSpiArduinoDriver::activate() {
|
|||
pSpi->SPI_CR |= SPI_CR_SPIEN;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) {
|
||||
(void)spiConfig;
|
||||
SPI.begin();
|
||||
#if USE_SAM3X_DMAC
|
||||
pmc_enable_periph_clk(ID_DMAC);
|
||||
dmac_disable();
|
||||
DMAC->DMAC_GCFG = DMAC_GCFG_ARB_CFG_FIXED;
|
||||
dmac_enable();
|
||||
#if USE_SAM3X_BUS_MATRIX_FIX
|
||||
MATRIX->MATRIX_WPMR = 0x4d415400;
|
||||
MATRIX->MATRIX_MCFG[1] = 1;
|
||||
MATRIX->MATRIX_MCFG[2] = 1;
|
||||
MATRIX->MATRIX_SCFG[0] = 0x01000010;
|
||||
MATRIX->MATRIX_SCFG[1] = 0x01000010;
|
||||
MATRIX->MATRIX_SCFG[7] = 0x01000010;
|
||||
#endif // USE_SAM3X_BUS_MATRIX_FIX
|
||||
#endif // USE_SAM3X_DMAC
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::deactivate() {
|
||||
SPI.endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::end() {
|
||||
SPI.end();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static inline uint8_t spiTransfer(uint8_t b) {
|
||||
Spi* pSpi = SPI0;
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ void SdSpiArduinoDriver::deactivate() {
|
|||
m_spi->endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::end() {
|
||||
m_spi->end();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdSpiArduinoDriver::receive() {
|
||||
return m_spi->transfer(0XFF);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ inline void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) {
|
|||
m_spi->begin();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiArduinoDriver::end() {
|
||||
m_spi->end();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiArduinoDriver::deactivate() {
|
||||
m_spi->endTransaction();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ void SdSpiArduinoDriver::deactivate() {
|
|||
m_spi->endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::end() {
|
||||
m_spi->end();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdSpiArduinoDriver::receive() {
|
||||
return m_spi->transfer(0XFF);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ void SdSpiArduinoDriver::deactivate() {
|
|||
m_spi->endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::end() {
|
||||
m_spi->end();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdSpiArduinoDriver::receive() {
|
||||
return m_spi->transfer(0XFF);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ void SdSpiArduinoDriver::deactivate() {
|
|||
m_spi->endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::end() {
|
||||
m_spi->end();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdSpiArduinoDriver::receive() {
|
||||
return m_spi->transfer(0XFF);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ class SdSpiSoftDriver {
|
|||
}
|
||||
/** Deactivate SPI hardware. */
|
||||
void deactivate() {}
|
||||
/** deactivate SPI driver. */
|
||||
void end() {}
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ void SdSpiArduinoDriver::deactivate() {
|
|||
m_spi->endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::end() {
|
||||
m_spi->end();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdSpiArduinoDriver::receive() {
|
||||
return m_spi->transfer(0XFF);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
#ifndef ArduinoFiles_h
|
||||
#define ArduinoFiles_h
|
||||
#include "SdFatConfig.h"
|
||||
#include "SysCall.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/** Arduino SD.h style flag for open for read. */
|
||||
#ifndef FILE_READ
|
||||
|
|
@ -91,9 +91,8 @@ class StreamFile : public stream_t, public BaseFile {
|
|||
* \return a pointer to replacement suggestion.
|
||||
*/
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
const char* __attribute__((error("use getName(name, size)"))) name();
|
||||
char* __attribute__((error("use getName(name, size)"))) name();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
const char* name() const {return "use getName()";}
|
||||
/** Return the next available byte without consuming it.
|
||||
*
|
||||
* \return The byte if no error and not at eof else -1;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
#ifndef DebugMacros_h
|
||||
#define DebugMacros_h
|
||||
#include "SdFatConfig.h"
|
||||
#include "SysCall.h"
|
||||
|
||||
// 0 - disable, 1 - fail, halt 2 - fail, halt, warn
|
||||
#define USE_DBG_MACROS 0
|
||||
|
|
|
|||
|
|
@ -139,8 +139,7 @@ void divmod10(uint32_t in, uint32_t &div, uint32_t &mod)
|
|||
if (r > 9) mod = r - 10;
|
||||
else mod = r;
|
||||
}
|
||||
// Hackers delight function is here:
|
||||
// http://www.hackersdelight.org/hdcodetxt/divuc.c.txt
|
||||
// See: https://github.com/hcs0/Hackers-Delight
|
||||
// Code below uses 8/10 = 0.1100 1100 1100 1100 1100 1100 1100 1100.
|
||||
// 15 ops including the multiply, or 17 elementary ops.
|
||||
unsigned divu10(unsigned n) {
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@
|
|||
*/
|
||||
#ifndef FsApiConstants_h
|
||||
#define FsApiConstants_h
|
||||
#include "SdFatConfig.h"
|
||||
|
||||
#include "SysCall.h"
|
||||
#if USE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
/* values for GNU Arm Embedded Toolchain.
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef BlockDevice_h
|
||||
#define BlockDevice_h
|
||||
#ifndef FsBlockDevice_h
|
||||
#define FsBlockDevice_h
|
||||
#include "SdCard/SdCard.h"
|
||||
#if HAS_SDIO_CLASS || USE_BLOCK_DEVICE_INTERFACE
|
||||
typedef BlockDeviceInterface BlockDevice;
|
||||
typedef FsBlockDeviceInterface FsBlockDevice;
|
||||
#else
|
||||
typedef SdCard BlockDevice;
|
||||
typedef SdCard FsBlockDevice;
|
||||
#endif
|
||||
#endif // BlockDevice_h
|
||||
#endif // FsBlockDevice_h
|
||||
|
|
@ -24,22 +24,24 @@
|
|||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief BlockDeviceInterface include file.
|
||||
* \brief FsBlockDeviceInterface include file.
|
||||
*/
|
||||
#ifndef BlockDeviceInterface_h
|
||||
#define BlockDeviceInterface_h
|
||||
#ifndef FsBlockDeviceInterface_h
|
||||
#define FsBlockDeviceInterface_h
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "SdFatConfig.h"
|
||||
/**
|
||||
* \class BlockDeviceInterface
|
||||
* \brief BlockDeviceInterface class.
|
||||
* \class FsBlockDeviceInterface
|
||||
* \brief FsBlockDeviceInterface class.
|
||||
*/
|
||||
class BlockDeviceInterface {
|
||||
class FsBlockDeviceInterface {
|
||||
public:
|
||||
virtual ~BlockDeviceInterface() {}
|
||||
virtual ~FsBlockDeviceInterface() {}
|
||||
|
||||
/** end use of device */
|
||||
virtual void end() {}
|
||||
/**
|
||||
* Check for BlockDevice busy.
|
||||
* Check for FsBlockDevice busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
|
|
@ -90,4 +92,4 @@ class BlockDeviceInterface {
|
|||
*/
|
||||
virtual bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns) = 0;
|
||||
};
|
||||
#endif // BlockDeviceInterface_h
|
||||
#endif // FsBlockDeviceInterface_h
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
* \brief Common cache code for exFAT and FAT.
|
||||
*/
|
||||
#include "SysCall.h"
|
||||
#include "BlockDevice.h"
|
||||
#include "FsBlockDevice.h"
|
||||
/**
|
||||
* \class FsCache
|
||||
* \brief Sector cache.
|
||||
|
|
@ -127,7 +127,7 @@ class FsCache {
|
|||
/** Initialize the cache.
|
||||
* \param[in] blockDev Block device for this cache.
|
||||
*/
|
||||
void init(BlockDevice* blockDev) {
|
||||
void init(FsBlockDevice* blockDev) {
|
||||
m_blockDev = blockDev;
|
||||
invalidate();
|
||||
}
|
||||
|
|
@ -153,6 +153,12 @@ class FsCache {
|
|||
bool isDirty() {
|
||||
return m_status & CACHE_STATUS_DIRTY;
|
||||
}
|
||||
/** Prepare cache to access sector.
|
||||
* \param[in] sector Sector to read.
|
||||
* \param[in] option mode for cached sector.
|
||||
* \return Address of cached sector.
|
||||
*/
|
||||
uint8_t* prepare(uint32_t sector, uint8_t option);
|
||||
/** \return Logical sector number for cached sector. */
|
||||
uint32_t sector() {
|
||||
return m_sector;
|
||||
|
|
@ -163,12 +169,6 @@ class FsCache {
|
|||
void setMirrorOffset(uint32_t offset) {
|
||||
m_mirrorOffset = offset;
|
||||
}
|
||||
/** Prepare cache to access sector.
|
||||
* \param[in] sector Sector to read.
|
||||
* \param[in] option mode for cached sector.
|
||||
* \return Address of cached sector.
|
||||
*/
|
||||
uint8_t* prepare(uint32_t sector, uint8_t option);
|
||||
/** Write current sector if dirty.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
|
|
@ -176,7 +176,7 @@ class FsCache {
|
|||
|
||||
private:
|
||||
uint8_t m_status;
|
||||
BlockDevice* m_blockDev;
|
||||
FsBlockDevice* m_blockDev;
|
||||
uint32_t m_mirrorOffset;
|
||||
uint32_t m_sector;
|
||||
uint8_t m_buffer[512];
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
#ifndef FsName_h
|
||||
#define FsName_h
|
||||
#include "SdFatConfig.h"
|
||||
#include "SysCall.h"
|
||||
#include <stdint.h>
|
||||
/**
|
||||
* \file
|
||||
|
|
|
|||
91
src/common/PrintBasic.cpp
Normal file
91
src/common/PrintBasic.cpp
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2020 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.
|
||||
*/
|
||||
#include "PrintBasic.h"
|
||||
#if ENABLE_ARDUINO_FEATURES == 0
|
||||
#include <math.h>
|
||||
|
||||
size_t PrintBasic::print(long n, uint8_t base) {
|
||||
if (n < 0 && base == 10) {
|
||||
return print('-') + printNum(-n, base);
|
||||
}
|
||||
return printNum(n, base);
|
||||
}
|
||||
size_t PrintBasic::printNum(unsigned long n, uint8_t base) {
|
||||
const uint8_t DIM = 8*sizeof(long);
|
||||
char buf[DIM];
|
||||
char *str = &buf[DIM];
|
||||
|
||||
if (base < 2) return 0;
|
||||
|
||||
do {
|
||||
char c = n%base;
|
||||
n /= base;
|
||||
*--str = c + (c < 10 ? '0' : 'A' - 10);
|
||||
} while (n);
|
||||
return write(str, &buf[DIM] - str);
|
||||
}
|
||||
|
||||
size_t PrintBasic::printDouble(double n, uint8_t prec) {
|
||||
// Max printable 32-bit floating point number. AVR uses 32-bit double.
|
||||
const double maxfp = static_cast<double>(0XFFFFFF00UL);
|
||||
size_t rtn = 0;
|
||||
|
||||
if (isnan(n)) {
|
||||
return write("NaN");
|
||||
}
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
rtn += print('-');
|
||||
}
|
||||
if (isinf(n)) {
|
||||
return rtn + write("Inf");
|
||||
}
|
||||
if (n > maxfp) {
|
||||
return rtn + write("Ovf");
|
||||
}
|
||||
|
||||
double round = 0.5;
|
||||
for (uint8_t i = 0; i < prec; ++i) {
|
||||
round *= 0.1;
|
||||
}
|
||||
|
||||
n += round;
|
||||
|
||||
uint32_t whole = (uint32_t)n;
|
||||
rtn += print(whole);
|
||||
|
||||
if (prec) {
|
||||
rtn += print('.');
|
||||
double fraction = n - static_cast<double>(whole);
|
||||
for (uint8_t i = 0; i < prec; i++) {
|
||||
fraction *= 10.0;
|
||||
uint8_t digit = fraction;
|
||||
rtn += print(digit);
|
||||
fraction -= digit;
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
#endif // ENABLE_ARDUINO_FEATURES == 0
|
||||
169
src/common/PrintBasic.h
Normal file
169
src/common/PrintBasic.h
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2020 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.
|
||||
*/
|
||||
#ifndef PrintBasic_h
|
||||
#define PrintBasic_h
|
||||
/**
|
||||
* \file
|
||||
* \brief Stream/Print like replacement for non-Arduino systems.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "../SdFatConfig.h"
|
||||
|
||||
#ifndef F
|
||||
#if defined(__AVR__)
|
||||
#include <avr/pgmspace.h>
|
||||
class __FlashStringHelper;
|
||||
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
||||
#else // defined(__AVR__)
|
||||
#define F(str) (str)
|
||||
#endif // defined(__AVR__)
|
||||
#endif // F
|
||||
|
||||
#ifdef BIN
|
||||
#undef BIN
|
||||
#endif // BIN
|
||||
#define BIN 2
|
||||
#define OCT 8
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
|
||||
class PrintBasic {
|
||||
public:
|
||||
PrintBasic() : m_error(0) {}
|
||||
|
||||
void clearWriteError() {
|
||||
setWriteError(0);
|
||||
}
|
||||
int getWriteError() {
|
||||
return m_error;
|
||||
}
|
||||
size_t print(char c) {
|
||||
return write(c);
|
||||
}
|
||||
size_t print(const char* str) {
|
||||
return write(str);
|
||||
}
|
||||
size_t print(const __FlashStringHelper *str) {
|
||||
#ifdef __AVR__
|
||||
PGM_P p = reinterpret_cast<PGM_P>(str);
|
||||
size_t n = 0;
|
||||
for (uint8_t c; (c = pgm_read_byte(p + n)) && write(c); n++) {}
|
||||
return n;
|
||||
#else // __AVR__
|
||||
return print(reinterpret_cast<const char *>(str));
|
||||
#endif // __AVR__
|
||||
}
|
||||
size_t println(const __FlashStringHelper *str) {
|
||||
#ifdef __AVR__
|
||||
return print(str) + println();
|
||||
#else // __AVR__
|
||||
return println(reinterpret_cast<const char *>(str));
|
||||
#endif // __AVR__
|
||||
}
|
||||
size_t print(double n, uint8_t prec = 2) {
|
||||
return printDouble(n, prec);
|
||||
}
|
||||
size_t print(signed char n, uint8_t base = 10) {
|
||||
return print((long)n, base);
|
||||
}
|
||||
size_t print(unsigned char n, uint8_t base = 10) {
|
||||
return print((unsigned long)n, base);
|
||||
}
|
||||
size_t print(int n, uint8_t base = 10) {
|
||||
return print((long)n, base);
|
||||
}
|
||||
size_t print(unsigned int n, uint8_t base = 10) {
|
||||
return print((unsigned long)n, base);
|
||||
}
|
||||
size_t print(long n, uint8_t base = 10);
|
||||
size_t print(unsigned long n, uint8_t base = 10) {
|
||||
return printNum(n, base);
|
||||
}
|
||||
size_t println() {
|
||||
return write("\r\n");
|
||||
}
|
||||
size_t println(char c) {
|
||||
return write(c) + println();
|
||||
}
|
||||
size_t println(const char* str) {
|
||||
return print(str) + println();
|
||||
}
|
||||
size_t println(double n, uint8_t prec = 2) {
|
||||
return print(n, prec) + println();
|
||||
}
|
||||
size_t println(signed char n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(unsigned char n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(int n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(unsigned int n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(long n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(unsigned long n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t write(const char *str) {
|
||||
return write(str, strlen(str));
|
||||
}
|
||||
virtual size_t write(uint8_t b) = 0;
|
||||
|
||||
virtual size_t write(const uint8_t* buffer, size_t size) {
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (!write(buffer[i])) break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
return write((const uint8_t*)buffer, size);
|
||||
}
|
||||
|
||||
protected:
|
||||
void setWriteError(int err = 1) {
|
||||
m_error = err;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t printDouble(double n, uint8_t prec);
|
||||
size_t printNum(unsigned long n, uint8_t base);
|
||||
int m_error;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
class StreamBasic : public PrintBasic {
|
||||
public:
|
||||
virtual int available() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual int read() = 0;
|
||||
};
|
||||
#endif // PrintBasic_h
|
||||
|
|
@ -30,30 +30,13 @@
|
|||
#define SysCall_h
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "SdFatConfig.h"
|
||||
#include "../SdFatConfig.h"
|
||||
#if __cplusplus < 201103
|
||||
#warning nullptr defined
|
||||
/** Define nullptr if not C++11 */
|
||||
#define nullptr NULL
|
||||
#endif // __cplusplus < 201103
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SysCall
|
||||
* \brief SysCall - Class to wrap system calls.
|
||||
*/
|
||||
class SysCall {
|
||||
public:
|
||||
/** Halt execution of this thread. */
|
||||
static void halt() {
|
||||
while (1) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
/** Yield to other threads. */
|
||||
static void yield();
|
||||
};
|
||||
#if ENABLE_ARDUINO_FEATURES
|
||||
#if defined(ARDUINO)
|
||||
/** Use Arduino Print. */
|
||||
|
|
@ -69,28 +52,11 @@ typedef Stream stream_t;
|
|||
#define F(str) (str)
|
||||
#endif // F
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(PLATFORM_ID) // Only defined if a Particle device
|
||||
inline void SysCall::yield() {
|
||||
// Recommended to only call Particle.process() if system threading is disabled
|
||||
if (system_thread_get_state(NULL) == spark::feature::DISABLED) {
|
||||
Particle.process();
|
||||
}
|
||||
}
|
||||
#elif defined(ARDUINO)
|
||||
inline void SysCall::yield() {
|
||||
// Use the external Arduino yield() function.
|
||||
::yield();
|
||||
}
|
||||
#else // defined(PLATFORM_ID)
|
||||
inline void SysCall::yield() {}
|
||||
#endif // defined(PLATFORM_ID)
|
||||
//------------------------------------------------------------------------------
|
||||
#else // ENABLE_ARDUINO_FEATURES
|
||||
#include "PrintBasic.h"
|
||||
/** If not Arduino */
|
||||
typedef PrintBasic print_t;
|
||||
/** If not Arduino */
|
||||
typedef PrintBasic stream_t;
|
||||
inline void SysCall::yield() {}
|
||||
#endif // ENABLE_ARDUINO_FEATURES
|
||||
#endif // SysCall_h
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
* \file
|
||||
* \brief ArduinoInStream and ArduinoOutStream classes
|
||||
*/
|
||||
#include "SdFatConfig.h"
|
||||
#include "bufstream.h"
|
||||
//==============================================================================
|
||||
/**
|
||||
|
|
@ -54,7 +53,7 @@ class ArduinoInStream : public ibufstream {
|
|||
uint32_t t;
|
||||
m_line[0] = '\0';
|
||||
while (!m_hw->available()) {
|
||||
SysCall::yield();
|
||||
yield();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
|
@ -111,7 +110,7 @@ class ArduinoOutStream : public ostream {
|
|||
*
|
||||
* \param[in] pr Print object for this ArduinoOutStream.
|
||||
*/
|
||||
explicit ArduinoOutStream(Print& pr) : m_pr(&pr) {}
|
||||
explicit ArduinoOutStream(print_t& pr) : m_pr(&pr) {}
|
||||
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
|
|
@ -146,6 +145,6 @@ class ArduinoOutStream : public ostream {
|
|||
/// @endcond
|
||||
private:
|
||||
ArduinoOutStream() {}
|
||||
Print* m_pr;
|
||||
print_t* m_pr;
|
||||
};
|
||||
#endif // ArduinoStream_h
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ class StdioStream : private StreamBaseFile {
|
|||
return n > 0 ? n : 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a number.
|
||||
/** Print a number.
|
||||
*
|
||||
* \param[in] val the number to be printed.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
/** For internal use in c++ streams */
|
||||
typedef fspos_t pos_t;
|
||||
//==============================================================================
|
||||
#if SDFAT_FILE_TYPE == 1
|
||||
#if SDFAT_FILE_TYPE == 1 || defined(DOXYGEN)
|
||||
/** Set File type for iostreams. */
|
||||
typedef FatFile StreamBaseFile;
|
||||
#elif SDFAT_FILE_TYPE == 2
|
||||
|
|
|
|||
Loading…
Reference in a new issue