1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Update to SdFat 2.0.2, speed SD access (#7779)

* Update to upstream SdFat 2.0.2

Increases the read/write performance for SD card accesses
by a significant amount, up to 5x (3+MB/s) in testing.

Fixes #7772 

* Add SDFS::availableForWrite handler

Peek into the sector cache to determine the maximum number of
bytes that can be written w/o needing a (slow) SD operation.

Fixes #7650
This commit is contained in:
Earle F. Philhower, III 2020-12-23 11:39:12 -08:00 committed by GitHub
parent 9de8373f1b
commit c487ca5233
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 452 deletions

@ -1 +1 @@
Subproject commit b240d2231a117bbd89b79902eb54cae948ee2f42 Subproject commit 0a46e4ebb2de585c5a64f981dbc2b2223a438984

View File

@ -32,7 +32,7 @@
class SDClass { class SDClass {
public: public:
boolean begin(uint8_t csPin, SPISettings cfg = SPI_HALF_SPEED) { boolean begin(uint8_t csPin, uint32_t cfg = SPI_HALF_SPEED) {
SDFS.setConfig(SDFSConfig(csPin, cfg)); SDFS.setConfig(SDFSConfig(csPin, cfg));
return (boolean)SDFS.begin(); return (boolean)SDFS.begin();
} }

View File

@ -25,7 +25,6 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "SDFS.h" #include "SDFS.h"
#include "SDFSFormatter.h"
#include <FS.h> #include <FS.h>
using namespace fs; using namespace fs;
@ -65,13 +64,13 @@ FileImplPtr SDFSImpl::open(const char* path, OpenMode openMode, AccessMode acces
} }
free(pathStr); free(pathStr);
} }
sdfat::File fd = _fs.open(path, flags); sdfat::File32 fd = _fs.open(path, flags);
if (!fd) { if (!fd) {
DEBUGV("SDFSImpl::openFile: fd=%p path=`%s` openMode=%d accessMode=%d", DEBUGV("SDFSImpl::openFile: fd=%p path=`%s` openMode=%d accessMode=%d",
&fd, path, openMode, accessMode); &fd, path, openMode, accessMode);
return FileImplPtr(); return FileImplPtr();
} }
auto sharedFd = std::make_shared<sdfat::File>(fd); auto sharedFd = std::make_shared<sdfat::File32>(fd);
return std::make_shared<SDFSFileImpl>(this, sharedFd, path); return std::make_shared<SDFSFileImpl>(this, sharedFd, path);
} }
@ -91,7 +90,7 @@ DirImplPtr SDFSImpl::openDir(const char* path)
} }
// At this point we have a name of "/blah/blah/blah" or "blah" or "" // At this point we have a name of "/blah/blah/blah" or "blah" or ""
// If that references a directory, just open it and we're done. // If that references a directory, just open it and we're done.
sdfat::File dirFile; sdfat::File32 dirFile;
const char *filter = ""; const char *filter = "";
if (!pathStr[0]) { if (!pathStr[0]) {
// openDir("") === openDir("/") // openDir("") === openDir("/")
@ -136,7 +135,7 @@ DirImplPtr SDFSImpl::openDir(const char* path)
DEBUGV("SDFSImpl::openDir: path=`%s`\n", path); DEBUGV("SDFSImpl::openDir: path=`%s`\n", path);
return DirImplPtr(); return DirImplPtr();
} }
auto sharedDir = std::make_shared<sdfat::File>(dirFile); auto sharedDir = std::make_shared<sdfat::File32>(dirFile);
auto ret = std::make_shared<SDFSDirImpl>(filter, this, sharedDir, pathStr); auto ret = std::make_shared<SDFSDirImpl>(filter, this, sharedDir, pathStr);
free(pathStr); free(pathStr);
return ret; return ret;
@ -146,8 +145,15 @@ bool SDFSImpl::format() {
if (_mounted) { if (_mounted) {
return false; return false;
} }
SDFSFormatter formatter; sdfat::SdCardFactory cardFactory;
bool ret = formatter.format(&_fs, _cfg._csPin, _cfg._spiSettings); sdfat::SdCard* card = cardFactory.newCard(sdfat::SdSpiConfig(_cfg._csPin, DEDICATED_SPI, _cfg._spiSettings));
if (!card || card->errorCode()) {
return false;
}
sdfat::FatFormatter fatFormatter;
uint8_t *sectorBuffer = new uint8_t[512];
bool ret = fatFormatter.format(card, sectorBuffer, nullptr);
delete[] sectorBuffer;
return ret; return ret;
} }

View File

@ -47,7 +47,7 @@ class SDFSConfig : public FSConfig
public: public:
static constexpr uint32_t FSId = 0x53444653; static constexpr uint32_t FSId = 0x53444653;
SDFSConfig(uint8_t csPin = 4, SPISettings spi = SD_SCK_MHZ(10)) : FSConfig(FSId, false), _csPin(csPin), _part(0), _spiSettings(spi) { } SDFSConfig(uint8_t csPin = 4, uint32_t spi = SD_SCK_MHZ(10)) : FSConfig(FSId, false), _csPin(csPin), _part(0), _spiSettings(spi) { }
SDFSConfig setAutoFormat(bool val = true) { SDFSConfig setAutoFormat(bool val = true) {
_autoFormat = val; _autoFormat = val;
@ -57,7 +57,7 @@ public:
_csPin = pin; _csPin = pin;
return *this; return *this;
} }
SDFSConfig setSPI(SPISettings spi) { SDFSConfig setSPI(uint32_t spi) {
_spiSettings = spi; _spiSettings = spi;
return *this; return *this;
} }
@ -69,7 +69,7 @@ public:
// Inherit _type and _autoFormat // Inherit _type and _autoFormat
uint8_t _csPin; uint8_t _csPin;
uint8_t _part; uint8_t _part;
SPISettings _spiSettings; uint32_t _spiSettings;
}; };
class SDFSImpl : public FSImpl class SDFSImpl : public FSImpl
@ -97,11 +97,11 @@ public:
return false; return false;
} }
info.maxOpenFiles = 999; // TODO - not valid info.maxOpenFiles = 999; // TODO - not valid
info.blockSize = _fs.vol()->blocksPerCluster() * 512; info.blockSize = _fs.vol()->sectorsPerCluster() * _fs.vol()->bytesPerSector();
info.pageSize = 0; // TODO ? info.pageSize = 0; // TODO ?
info.maxPathLength = 255; // TODO ? info.maxPathLength = 255; // TODO ?
info.totalBytes =_fs.vol()->volumeBlockCount() * 512LL; info.totalBytes =_fs.vol()->clusterCount() * info.blockSize;
info.usedBytes = info.totalBytes - (_fs.vol()->freeClusterCount() * _fs.vol()->blocksPerCluster() * 512LL); info.usedBytes = info.totalBytes - (_fs.vol()->freeClusterCount() * _fs.vol()->sectorsPerCluster() * _fs.vol()->bytesPerSector());
return true; return true;
} }
@ -156,7 +156,7 @@ public:
format(); format();
_mounted = _fs.begin(_cfg._csPin, _cfg._spiSettings); _mounted = _fs.begin(_cfg._csPin, _cfg._spiSettings);
} }
sdfat::SdFile::dateTimeCallback(dateTimeCB); sdfat::FsDateTime::setCallback(dateTimeCB);
return _mounted; return _mounted;
} }
@ -176,7 +176,7 @@ public:
return _fs.vol()->fatType(); return _fs.vol()->fatType();
} }
size_t blocksPerCluster() { size_t blocksPerCluster() {
return _fs.vol()->blocksPerCluster(); return _fs.vol()->sectorsPerCluster();
} }
size_t totalClusters() { size_t totalClusters() {
return _fs.vol()->clusterCount(); return _fs.vol()->clusterCount();
@ -185,7 +185,7 @@ public:
return (totalClusters() / blocksPerCluster()); return (totalClusters() / blocksPerCluster());
} }
size_t clusterSize() { size_t clusterSize() {
return blocksPerCluster() * 512; // 512b block size return blocksPerCluster() * _fs.vol()->bytesPerSector();
} }
size_t size() { size_t size() {
return (clusterSize() * totalClusters()); return (clusterSize() * totalClusters());
@ -264,7 +264,7 @@ protected:
class SDFSFileImpl : public FileImpl class SDFSFileImpl : public FileImpl
{ {
public: public:
SDFSFileImpl(SDFSImpl *fs, std::shared_ptr<sdfat::File> fd, const char *name) SDFSFileImpl(SDFSImpl *fs, std::shared_ptr<sdfat::File32> fd, const char *name)
: _fs(fs), _fd(fd), _opened(true) : _fs(fs), _fd(fd), _opened(true)
{ {
_name = std::shared_ptr<char>(new char[strlen(name) + 1], std::default_delete<char[]>()); _name = std::shared_ptr<char>(new char[strlen(name) + 1], std::default_delete<char[]>());
@ -279,7 +279,7 @@ public:
int availableForWrite() override int availableForWrite() override
{ {
return _opened ? _fd->availableForWrite() : 0; return _opened ? _fd->availableSpaceForWrite() : 0;
} }
size_t write(const uint8_t *buf, size_t size) override size_t write(const uint8_t *buf, size_t size) override
@ -295,7 +295,6 @@ public:
void flush() override void flush() override
{ {
if (_opened) { if (_opened) {
_fd->flush();
_fd->sync(); _fd->sync();
} }
} }
@ -375,15 +374,15 @@ public:
bool isDirectory() const override bool isDirectory() const override
{ {
return _opened ? _fd->isDirectory() : false; return _opened ? _fd->isDir() : false;
} }
time_t getLastWrite() override { time_t getLastWrite() override {
time_t ftime = 0; time_t ftime = 0;
if (_opened && _fd) { if (_opened && _fd) {
sdfat::dir_t tmp; sdfat::DirFat_t tmp;
if (_fd.get()->dirEntry(&tmp)) { if (_fd.get()->dirEntry(&tmp)) {
ftime = SDFSImpl::FatToTimeT(tmp.lastWriteDate, tmp.lastWriteTime); ftime = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.modifyDate, *(uint16_t*)tmp.modifyTime);
} }
} }
return ftime; return ftime;
@ -392,19 +391,17 @@ public:
time_t getCreationTime() override { time_t getCreationTime() override {
time_t ftime = 0; time_t ftime = 0;
if (_opened && _fd) { if (_opened && _fd) {
sdfat::dir_t tmp; sdfat::DirFat_t tmp;
if (_fd.get()->dirEntry(&tmp)) { if (_fd.get()->dirEntry(&tmp)) {
ftime = SDFSImpl::FatToTimeT(tmp.creationDate, tmp.creationTime); ftime = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.createDate, *(uint16_t*)tmp.createTime);
} }
} }
return ftime; return ftime;
} }
protected: protected:
SDFSImpl* _fs; SDFSImpl* _fs;
std::shared_ptr<sdfat::File> _fd; std::shared_ptr<sdfat::File32> _fd;
std::shared_ptr<char> _name; std::shared_ptr<char> _name;
bool _opened; bool _opened;
}; };
@ -412,7 +409,7 @@ protected:
class SDFSDirImpl : public DirImpl class SDFSDirImpl : public DirImpl
{ {
public: public:
SDFSDirImpl(const String& pattern, SDFSImpl* fs, std::shared_ptr<sdfat::File> dir, const char *dirPath = nullptr) SDFSDirImpl(const String& pattern, SDFSImpl* fs, std::shared_ptr<sdfat::File32> dir, const char *dirPath = nullptr)
: _pattern(pattern), _fs(fs), _dir(dir), _valid(false), _dirPath(nullptr) : _pattern(pattern), _fs(fs), _dir(dir), _valid(false), _dirPath(nullptr)
{ {
if (dirPath) { if (dirPath) {
@ -487,17 +484,17 @@ public:
{ {
const int n = _pattern.length(); const int n = _pattern.length();
do { do {
sdfat::File file; sdfat::File32 file;
file.openNext(_dir.get(), sdfat::O_READ); file.openNext(_dir.get(), sdfat::O_READ);
if (file) { if (file) {
_valid = 1; _valid = 1;
_size = file.fileSize(); _size = file.fileSize();
_isFile = file.isFile(); _isFile = file.isFile();
_isDirectory = file.isDirectory(); _isDirectory = file.isDir();
sdfat::dir_t tmp; sdfat::DirFat_t tmp;
if (file.dirEntry(&tmp)) { if (file.dirEntry(&tmp)) {
_time = SDFSImpl::FatToTimeT(tmp.lastWriteDate, tmp.lastWriteTime); _time = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.modifyDate, *(uint16_t*)tmp.modifyTime);
_creation = SDFSImpl::FatToTimeT(tmp.creationDate, tmp.creationTime); _creation = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.createDate, *(uint16_t*)tmp.createTime);
} else { } else {
_time = 0; _time = 0;
_creation = 0; _creation = 0;
@ -521,7 +518,7 @@ public:
protected: protected:
String _pattern; String _pattern;
SDFSImpl* _fs; SDFSImpl* _fs;
std::shared_ptr<sdfat::File> _dir; std::shared_ptr<sdfat::File32> _dir;
bool _valid; bool _valid;
char _lfn[64]; char _lfn[64];
time_t _time; time_t _time;

View File

@ -1,405 +0,0 @@
/*
SDFSFormatter.cpp - Formatter for SdFat SD cards
Copyright (c) 2019 Earle F. Philhower, III. All rights reserved.
A C++ implementation of the SdFat/examples/SdFormatter sketch:
| Copyright (c) 2011-2018 Bill Greiman
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SDFSFORMATTER_H
#define _SDFSFORMATTER_H
#include "SDFS.h"
#include <FS.h>
#include <PolledTimeout.h>
namespace sdfs {
class SDFSFormatter {
private:
// Taken from main FS object
sdfat::Sd2Card *card;
sdfat::cache_t *cache;
uint32_t cardSizeBlocks;
uint32_t cardCapacityMB;
// MBR information
uint8_t partType;
uint32_t relSector;
uint32_t partSize;
// Fake disk geometry
uint8_t numberOfHeads;
uint8_t sectorsPerTrack;
// FAT parameters
uint16_t reservedSectors;
uint8_t sectorsPerCluster;
uint32_t fatStart;
uint32_t fatSize;
uint32_t dataStart;
uint8_t writeCache(uint32_t lbn) {
return card->writeBlock(lbn, cache->data);
}
void clearCache(uint8_t addSig) {
memset(cache, 0, sizeof(*cache));
if (addSig) {
cache->mbr.mbrSig0 = sdfat::BOOTSIG0;
cache->mbr.mbrSig1 = sdfat::BOOTSIG1;
}
}
bool clearFatDir(uint32_t bgn, uint32_t count) {
clearCache(false);
if (!card->writeStart(bgn, count)) {
DEBUGV("SDFS: Clear FAT/DIR writeStart failed");
return false;
}
esp8266::polledTimeout::periodicFastMs timeToYield(5); // Yield every 5ms of runtime
for (uint32_t i = 0; i < count; i++) {
if (timeToYield) {
delay(0); // WDT feed
}
if (!card->writeData(cache->data)) {
DEBUGV("SDFS: Clear FAT/DIR writeData failed");
return false;
}
}
if (!card->writeStop()) {
DEBUGV("SDFS: Clear FAT/DIR writeStop failed");
return false;
}
return true;
}
uint16_t lbnToCylinder(uint32_t lbn) {
return lbn / (numberOfHeads * sectorsPerTrack);
}
uint8_t lbnToHead(uint32_t lbn) {
return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
}
uint8_t lbnToSector(uint32_t lbn) {
return (lbn % sectorsPerTrack) + 1;
}
bool writeMbr() {
clearCache(true);
sdfat::part_t* p = cache->mbr.part;
p->boot = 0;
uint16_t c = lbnToCylinder(relSector);
if (c > 1023) {
DEBUGV("SDFS: MBR CHS");
return false;
}
p->beginCylinderHigh = c >> 8;
p->beginCylinderLow = c & 0XFF;
p->beginHead = lbnToHead(relSector);
p->beginSector = lbnToSector(relSector);
p->type = partType;
uint32_t endLbn = relSector + partSize - 1;
c = lbnToCylinder(endLbn);
if (c <= 1023) {
p->endCylinderHigh = c >> 8;
p->endCylinderLow = c & 0XFF;
p->endHead = lbnToHead(endLbn);
p->endSector = lbnToSector(endLbn);
} else {
// Too big flag, c = 1023, h = 254, s = 63
p->endCylinderHigh = 3;
p->endCylinderLow = 255;
p->endHead = 254;
p->endSector = 63;
}
p->firstSector = relSector;
p->totalSectors = partSize;
if (!writeCache(0)) {
DEBUGV("SDFS: write MBR");
return false;
}
return true;
}
uint32_t volSerialNumber() {
return (cardSizeBlocks << 8) + micros();
}
bool makeFat16() {
uint16_t const BU16 = 128;
uint32_t nc;
for (dataStart = 2 * BU16;; dataStart += BU16) {
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
fatSize = (nc + 2 + 255)/256;
uint32_t r = BU16 + 1 + 2 * fatSize + 32;
if (dataStart < r) {
continue;
}
relSector = dataStart - r + BU16;
break;
}
// check valid cluster count for FAT16 volume
if (nc < 4085 || nc >= 65525) {
DEBUGV("SDFS: Bad cluster count");
}
reservedSectors = 1;
fatStart = relSector + reservedSectors;
partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32;
if (partSize < 32680) {
partType = 0X01;
} else if (partSize < 65536) {
partType = 0X04;
} else {
partType = 0X06;
}
// write MBR
if (!writeMbr()) {
DEBUGV("SDFS: writembr failed");
return false;
}
clearCache(true);
sdfat::fat_boot_t* pb = &cache->fbs;
pb->jump[0] = 0XEB;
pb->jump[1] = 0X00;
pb->jump[2] = 0X90;
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
pb->oemId[i] = ' ';
}
pb->bytesPerSector = 512;
pb->sectorsPerCluster = sectorsPerCluster;
pb->reservedSectorCount = reservedSectors;
pb->fatCount = 2;
pb->rootDirEntryCount = 512;
pb->mediaType = 0XF8;
pb->sectorsPerFat16 = fatSize;
pb->sectorsPerTrack = sectorsPerTrack;
pb->headCount = numberOfHeads;
pb->hidddenSectors = relSector;
pb->totalSectors32 = partSize;
pb->driveNumber = 0X80;
pb->bootSignature = sdfat::EXTENDED_BOOT_SIG;
pb->volumeSerialNumber = volSerialNumber();
memcpy_P(pb->volumeLabel, PSTR("NO NAME "), sizeof(pb->volumeLabel));
memcpy_P(pb->fileSystemType, PSTR("FAT16 "), sizeof(pb->fileSystemType));
// write partition boot sector
if (!writeCache(relSector)) {
DEBUGV("SDFS: FAT16 write PBS failed");
return false;
}
// clear FAT and root directory
if (!clearFatDir(fatStart, dataStart - fatStart)) {
DEBUGV("SDFS: FAT16 clear root failed\n");
return false;
}
clearCache(false);
cache->fat16[0] = 0XFFF8;
cache->fat16[1] = 0XFFFF;
// write first block of FAT and backup for reserved clusters
if (!writeCache(fatStart) || !writeCache(fatStart + fatSize)) {
DEBUGV("FAT16 reserve failed");
return false;
}
return true;
}
bool makeFat32() {
uint16_t const BU32 = 8192;
uint32_t nc;
relSector = BU32;
for (dataStart = 2 * BU32;; dataStart += BU32) {
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
fatSize = (nc + 2 + 127)/128;
uint32_t r = relSector + 9 + 2 * fatSize;
if (dataStart >= r) {
break;
}
}
// error if too few clusters in FAT32 volume
if (nc < 65525) {
DEBUGV("SDFS: Bad cluster count");
return false;
}
reservedSectors = dataStart - relSector - 2 * fatSize;
fatStart = relSector + reservedSectors;
partSize = nc * sectorsPerCluster + dataStart - relSector;
// type depends on address of end sector
// max CHS has lbn = 16450560 = 1024*255*63
if ((relSector + partSize) <= 16450560) {
// FAT32
partType = 0X0B;
} else {
// FAT32 with INT 13
partType = 0X0C;
}
if (!writeMbr()) {
DEBUGV("SDFS: writembr failed");
return false;
}
clearCache(true);
sdfat::fat32_boot_t* pb = &cache->fbs32;
pb->jump[0] = 0XEB;
pb->jump[1] = 0X00;
pb->jump[2] = 0X90;
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
pb->oemId[i] = ' ';
}
pb->bytesPerSector = 512;
pb->sectorsPerCluster = sectorsPerCluster;
pb->reservedSectorCount = reservedSectors;
pb->fatCount = 2;
pb->mediaType = 0XF8;
pb->sectorsPerTrack = sectorsPerTrack;
pb->headCount = numberOfHeads;
pb->hidddenSectors = relSector;
pb->totalSectors32 = partSize;
pb->sectorsPerFat32 = fatSize;
pb->fat32RootCluster = 2;
pb->fat32FSInfo = 1;
pb->fat32BackBootBlock = 6;
pb->driveNumber = 0X80;
pb->bootSignature = sdfat::EXTENDED_BOOT_SIG;
pb->volumeSerialNumber = volSerialNumber();
memcpy_P(pb->volumeLabel, PSTR("NO NAME "), sizeof(pb->volumeLabel));
memcpy_P(pb->fileSystemType, PSTR("FAT32 "), sizeof(pb->fileSystemType));
// write partition boot sector and backup
if (!writeCache(relSector) || !writeCache(relSector + 6)) {
DEBUGV("SDFS: FAT32 write PBS failed");
return false;
}
clearCache(true);
// write extra boot area and backup
if (!writeCache(relSector + 2) || !writeCache(relSector + 8)) {
DEBUGV("SDFS: FAT32 PBS ext failed");
return false;
}
sdfat::fat32_fsinfo_t* pf = &cache->fsinfo;
pf->leadSignature = sdfat::FSINFO_LEAD_SIG;
pf->structSignature = sdfat::FSINFO_STRUCT_SIG;
pf->freeCount = 0XFFFFFFFF;
pf->nextFree = 0XFFFFFFFF;
// write FSINFO sector and backup
if (!writeCache(relSector + 1) || !writeCache(relSector + 7)) {
DEBUGV("SDFS: FAT32 FSINFO failed");
return false;
}
clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster);
clearCache(false);
cache->fat32[0] = 0x0FFFFFF8;
cache->fat32[1] = 0x0FFFFFFF;
cache->fat32[2] = 0x0FFFFFFF;
// write first block of FAT and backup for reserved clusters
if (!writeCache(fatStart) || !writeCache(fatStart + fatSize)) {
DEBUGV("SDFS: FAT32 reserve failed");
return false;
}
return true;
}
public:
bool format(sdfat::SdFat *_fs, int8_t _csPin, SPISettings _spiSettings) {
card = static_cast<sdfat::Sd2Card*>(_fs->card());
cache = _fs->cacheClear();
if (!card->begin(_csPin, _spiSettings)) {
return false;
}
cardSizeBlocks = card->cardSize();
if (cardSizeBlocks == 0) {
return false;
}
cardCapacityMB = (cardSizeBlocks + 2047)/2048;
if (cardCapacityMB <= 6) {
return false; // Card is too small
} else if (cardCapacityMB <= 16) {
sectorsPerCluster = 2;
} else if (cardCapacityMB <= 32) {
sectorsPerCluster = 4;
} else if (cardCapacityMB <= 64) {
sectorsPerCluster = 8;
} else if (cardCapacityMB <= 128) {
sectorsPerCluster = 16;
} else if (cardCapacityMB <= 1024) {
sectorsPerCluster = 32;
} else if (cardCapacityMB <= 32768) {
sectorsPerCluster = 64;
} else {
// SDXC cards
sectorsPerCluster = 128;
}
// set fake disk geometry
sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63;
if (cardCapacityMB <= 16) {
numberOfHeads = 2;
} else if (cardCapacityMB <= 32) {
numberOfHeads = 4;
} else if (cardCapacityMB <= 128) {
numberOfHeads = 8;
} else if (cardCapacityMB <= 504) {
numberOfHeads = 16;
} else if (cardCapacityMB <= 1008) {
numberOfHeads = 32;
} else if (cardCapacityMB <= 2016) {
numberOfHeads = 64;
} else if (cardCapacityMB <= 4032) {
numberOfHeads = 128;
} else {
numberOfHeads = 255;
}
// Erase all data on card (TRIM)
uint32_t const ERASE_SIZE = 262144L;
uint32_t firstBlock = 0;
uint32_t lastBlock;
do {
lastBlock = firstBlock + ERASE_SIZE - 1;
if (lastBlock >= cardSizeBlocks) {
lastBlock = cardSizeBlocks - 1;
}
if (!card->erase(firstBlock, lastBlock)) {
return false; // Erase fail
}
delay(0); // yield to the OS to avoid WDT
firstBlock += ERASE_SIZE;
} while (firstBlock < cardSizeBlocks);
if (!card->readBlock(0, cache->data)) {
return false;
}
if (card->type() != sdfat::SD_CARD_TYPE_SDHC) {
return makeFat16();
} else {
return makeFat32();
}
}
}; // class SDFSFormatter
}; // namespace sdfs
#endif // _SDFSFORMATTER_H

View File

@ -8,15 +8,19 @@ function skip_ino()
# Add items to the following list with "\n" netween them to skip running. No spaces, tabs, etc. allowed # Add items to the following list with "\n" netween them to skip running. No spaces, tabs, etc. allowed
read -d '' skiplist << EOL || true read -d '' skiplist << EOL || true
/#attic/ /#attic/
/AnalogBinLogger/ /AvrAdcLogger/
/LowLatencyLogger/ /BackwardCompatibility/
/LowLatencyLoggerADXL345/ /examplesV1/
/LowLatencyLoggerMPU6050/ /ExFatFormatter/
/PrintBenchmark/ /ExFatLogger/
/TeensySdioDemo/ /ExFatUnicodeTest/
/RtcTimestampTest/
/SoftwareSpi/ /SoftwareSpi/
/STM32Test/ /STM32Test/
/extras/ /TeensyRtcTimestamp/
/TeensySdioDemo/
/UserChipSelectFunction/
/UserSPIDriver/
EOL EOL
echo $ino | grep -q -F "$skiplist" echo $ino | grep -q -F "$skiplist"
echo $(( 1 - $? )) echo $(( 1 - $? ))

View File

@ -102,9 +102,13 @@ CORE_CPP_FILES := \
FatLib/FatFileLFN.cpp \ FatLib/FatFileLFN.cpp \
FatLib/FatFilePrint.cpp \ FatLib/FatFilePrint.cpp \
FatLib/FatFileSFN.cpp \ FatLib/FatFileSFN.cpp \
FatLib/FatFormatter.cpp \
FatLib/FatVolume.cpp \ FatLib/FatVolume.cpp \
FatLib/FmtNumber.cpp \ FatLib/FatPartition.cpp \
FatLib/StdioStream.cpp \ common/FmtNumber.cpp \
common/FsStructs.cpp \
common/FsDateTime.cpp \
common/PrintBasic.cpp \
) \ ) \
$(abspath $(LIBRARIES_PATH)/SDFS/src/SDFS.cpp) \ $(abspath $(LIBRARIES_PATH)/SDFS/src/SDFS.cpp) \
$(abspath $(LIBRARIES_PATH)/SD/src/SD.cpp) \ $(abspath $(LIBRARIES_PATH)/SD/src/SD.cpp) \