Skip to content

Commit 287d50c

Browse files
committed
Add File::availableForWrite API
Rename "sync" arguments to "blocking", add auto mirror block flush
1 parent b8a78d4 commit 287d50c

File tree

7 files changed

+117
-28
lines changed

7 files changed

+117
-28
lines changed

src/File.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ size_t File::write(const uint8_t *buf, size_t size) {
7373
return t;
7474
}
7575

76+
int File::availableForWrite() {
77+
if (_file) {
78+
return _file->availableForWrite();
79+
}
80+
return 0;
81+
}
82+
7683
int File::peek() {
7784
if (! _file) {
7885
return 0;

src/SD.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace SDLib {
3535
File(void); // 'empty' constructor
3636
virtual size_t write(uint8_t);
3737
virtual size_t write(const uint8_t *buf, size_t size);
38+
virtual int availableForWrite();
3839
virtual int read();
3940
virtual int peek();
4041
virtual int available();

src/utility/Sd2Card.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -608,10 +608,11 @@ uint8_t Sd2Card::waitStartBlock(void) {
608608
609609
\param[in] blockNumber Logical block to be written.
610610
\param[in] src Pointer to the location of the data to be written.
611+
\param[in] sync If the write should be synchronous.
611612
\return The value one, true, is returned for success and
612613
the value zero, false, is returned for failure.
613614
*/
614-
uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
615+
uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t blocking) {
615616
#if SD_PROTECT_BLOCK_ZERO
616617
// don't allow write to first block
617618
if (blockNumber == 0) {
@@ -631,16 +632,17 @@ uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
631632
if (!writeData(DATA_START_BLOCK, src)) {
632633
goto fail;
633634
}
634-
635-
// wait for flash programming to complete
636-
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
637-
error(SD_CARD_ERROR_WRITE_TIMEOUT);
638-
goto fail;
639-
}
640-
// response is r2 so get and check two bytes for nonzero
641-
if (cardCommand(CMD13, 0) || spiRec()) {
642-
error(SD_CARD_ERROR_WRITE_PROGRAMMING);
643-
goto fail;
635+
if (blocking) {
636+
// wait for flash programming to complete
637+
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
638+
error(SD_CARD_ERROR_WRITE_TIMEOUT);
639+
goto fail;
640+
}
641+
// response is r2 so get and check two bytes for nonzero
642+
if (cardCommand(CMD13, 0) || spiRec()) {
643+
error(SD_CARD_ERROR_WRITE_PROGRAMMING);
644+
goto fail;
645+
}
644646
}
645647
chipSelectHigh();
646648
return true;
@@ -760,3 +762,16 @@ uint8_t Sd2Card::writeStop(void) {
760762
chipSelectHigh();
761763
return false;
762764
}
765+
//------------------------------------------------------------------------------
766+
/** Check if the SD card is busy
767+
768+
\return The value one, true, is returned when is busy and
769+
the value zero, false, is returned for when is NOT busy.
770+
*/
771+
uint8_t Sd2Card::isBusy(void) {
772+
chipSelectLow();
773+
byte b = spiRec();
774+
chipSelectHigh();
775+
776+
return (b != 0XFF);
777+
}

src/utility/Sd2Card.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,11 @@ class Sd2Card {
236236
uint8_t type(void) const {
237237
return type_;
238238
}
239-
uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src);
239+
uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t blocking = 1);
240240
uint8_t writeData(const uint8_t* src);
241241
uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount);
242242
uint8_t writeStop(void);
243+
uint8_t isBusy(void);
243244
private:
244245
uint32_t block_;
245246
uint8_t chipSelectPin_;

src/utility/SdFat.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ class SdFile : public Print {
295295
}
296296
uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
297297
uint8_t hour, uint8_t minute, uint8_t second);
298-
uint8_t sync(void);
298+
uint8_t sync(uint8_t blocking = 1);
299299
/** Type of this SdFile. You should use isFile() or isDir() instead of type()
300300
if possible.
301301
@@ -320,6 +320,7 @@ class SdFile : public Print {
320320
void write_P(PGM_P str);
321321
void writeln_P(PGM_P str);
322322
#endif
323+
int availableForWrite(void);
323324
//------------------------------------------------------------------------------
324325
#if ALLOW_DEPRECATED_FUNCTIONS
325326
// Deprecated functions - suppress cpplint warnings with NOLINT comment
@@ -407,14 +408,16 @@ class SdFile : public Print {
407408
// should be 0XF
408409
static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
409410
// available bits
410-
static uint8_t const F_UNUSED = 0X30;
411+
static uint8_t const F_FILE_NON_BLOCKING_WRITE = 0X10;
412+
// a new cluster was added to the file
413+
static uint8_t const F_FILE_CLUSTER_ADDED = 0X20;
411414
// use unbuffered SD read
412415
static uint8_t const F_FILE_UNBUFFERED_READ = 0X40;
413416
// sync of directory entry required
414417
static uint8_t const F_FILE_DIR_DIRTY = 0X80;
415418

416419
// make sure F_OFLAG is ok
417-
#if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG)
420+
#if ((F_FILE_NON_BLOCKING_WRITE | F_FILE_CLUSTER_ADDED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG)
418421
#error flags_ bits conflict
419422
#endif // flags_ bits
420423

@@ -587,7 +590,8 @@ class SdVolume {
587590
uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
588591
return clusterStartBlock(cluster) + blockOfCluster(position);
589592
}
590-
static uint8_t cacheFlush(void);
593+
static uint8_t cacheFlush(uint8_t blocking = 1);
594+
static uint8_t cacheMirrorBlockFlush(uint8_t blocking);
591595
static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action);
592596
static void cacheSetDirty(void) {
593597
cacheDirty_ |= CACHE_FOR_WRITE;
@@ -610,8 +614,14 @@ class SdVolume {
610614
uint16_t count, uint8_t* dst) {
611615
return sdCard_->readData(block, offset, count, dst);
612616
}
613-
uint8_t writeBlock(uint32_t block, const uint8_t* dst) {
614-
return sdCard_->writeBlock(block, dst);
617+
uint8_t writeBlock(uint32_t block, const uint8_t* dst, uint8_t blocking = 1) {
618+
return sdCard_->writeBlock(block, dst, blocking);
619+
}
620+
uint8_t isBusy(void) {
621+
return sdCard_->isBusy();
622+
}
623+
uint8_t isCacheMirrorBlockDirty(void) {
624+
return (cacheMirrorBlock_ != 0);
615625
}
616626
};
617627
#endif // SdFat_h

src/utility/SdFile.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ uint8_t SdFile::addCluster() {
4242
firstCluster_ = curCluster_;
4343
flags_ |= F_FILE_DIR_DIRTY;
4444
}
45+
flags_ |= F_FILE_CLUSTER_ADDED;
4546
return true;
4647
}
4748
//------------------------------------------------------------------------------
@@ -1126,7 +1127,7 @@ uint8_t SdFile::seekSet(uint32_t pos) {
11261127
Reasons for failure include a call to sync() before a file has been
11271128
opened or an I/O error.
11281129
*/
1129-
uint8_t SdFile::sync(void) {
1130+
uint8_t SdFile::sync(uint8_t blocking) {
11301131
// only allow open files and directories
11311132
if (!isOpen()) {
11321133
return false;
@@ -1155,7 +1156,12 @@ uint8_t SdFile::sync(void) {
11551156
// clear directory dirty
11561157
flags_ &= ~F_FILE_DIR_DIRTY;
11571158
}
1158-
return SdVolume::cacheFlush();
1159+
1160+
if (!blocking) {
1161+
flags_ &= ~F_FILE_NON_BLOCKING_WRITE;
1162+
}
1163+
1164+
return SdVolume::cacheFlush(blocking);
11591165
}
11601166
//------------------------------------------------------------------------------
11611167
/**
@@ -1383,7 +1389,7 @@ size_t SdFile::write(const void* buf, uint16_t nbyte) {
13831389
if (SdVolume::cacheBlockNumber_ == block) {
13841390
SdVolume::cacheBlockNumber_ = 0XFFFFFFFF;
13851391
}
1386-
if (!vol_->writeBlock(block, src)) {
1392+
if (!vol_->writeBlock(block, src, 0)) {
13871393
goto writeErrorReturn;
13881394
}
13891395
src += 512;
@@ -1473,3 +1479,40 @@ void SdFile::writeln_P(PGM_P str) {
14731479
println();
14741480
}
14751481
#endif
1482+
//------------------------------------------------------------------------------
1483+
int SdFile::availableForWrite() {
1484+
if (!isFile() || !(flags_ & O_WRITE)) {
1485+
return 0;
1486+
}
1487+
1488+
// seek to end of file if append flag
1489+
if ((flags_ & O_APPEND) && curPosition_ != fileSize_) {
1490+
if (!seekEnd()) {
1491+
return 0;
1492+
}
1493+
}
1494+
1495+
flags_ |= F_FILE_NON_BLOCKING_WRITE;
1496+
1497+
if (vol_->isBusy()) {
1498+
return 0;
1499+
}
1500+
1501+
if (flags_ & F_FILE_CLUSTER_ADDED) {
1502+
// new cluster added, trigger a non-blocking sync
1503+
sync(0);
1504+
flags_ &= ~F_FILE_CLUSTER_ADDED;
1505+
return 0;
1506+
}
1507+
1508+
if (vol_->isCacheMirrorBlockDirty()) {
1509+
// cache mirror block is dirty, trigger a non-blocking sync
1510+
vol_->cacheMirrorBlockFlush(0);
1511+
return 0;
1512+
}
1513+
1514+
uint16_t blockOffset = curPosition_ & 0X1FF;
1515+
uint16_t n = 512 - blockOffset;
1516+
1517+
return n;
1518+
}

src/utility/SdVolume.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,23 +108,35 @@ uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
108108
return true;
109109
}
110110
//------------------------------------------------------------------------------
111-
uint8_t SdVolume::cacheFlush(void) {
111+
uint8_t SdVolume::cacheFlush(uint8_t blocking) {
112112
if (cacheDirty_) {
113-
if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
113+
if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data, blocking)) {
114114
return false;
115115
}
116+
117+
if (!blocking) {
118+
return 0;
119+
}
120+
116121
// mirror FAT tables
117-
if (cacheMirrorBlock_) {
118-
if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
119-
return false;
120-
}
121-
cacheMirrorBlock_ = 0;
122+
if (!cacheMirrorBlockFlush(blocking)) {
123+
return false;
122124
}
123125
cacheDirty_ = 0;
124126
}
125127
return true;
126128
}
127129
//------------------------------------------------------------------------------
130+
uint8_t SdVolume::cacheMirrorBlockFlush(uint8_t blocking) {
131+
if (cacheMirrorBlock_) {
132+
if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data, blocking)) {
133+
return false;
134+
}
135+
cacheMirrorBlock_ = 0;
136+
}
137+
return true;
138+
}
139+
//------------------------------------------------------------------------------
128140
uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) {
129141
if (cacheBlockNumber_ != blockNumber) {
130142
if (!cacheFlush()) {

0 commit comments

Comments
 (0)