Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e617597

Browse files
Add File::availableForWrite API
1 parent b8a78d4 commit e617597

File tree

7 files changed

+126
-28
lines changed

7 files changed

+126
-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] blocking If the write should be blocking.
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: 55 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
//------------------------------------------------------------------------------
@@ -1121,12 +1122,14 @@ uint8_t SdFile::seekSet(uint32_t pos) {
11211122
The sync() call causes all modified data and directory fields
11221123
to be written to the storage device.
11231124
1125+
\param[in] blocking If the sync should block until fully complete.
1126+
11241127
\return The value one, true, is returned for success and
11251128
the value zero, false, is returned for failure.
11261129
Reasons for failure include a call to sync() before a file has been
11271130
opened or an I/O error.
11281131
*/
1129-
uint8_t SdFile::sync(void) {
1132+
uint8_t SdFile::sync(uint8_t blocking) {
11301133
// only allow open files and directories
11311134
if (!isOpen()) {
11321135
return false;
@@ -1155,7 +1158,12 @@ uint8_t SdFile::sync(void) {
11551158
// clear directory dirty
11561159
flags_ &= ~F_FILE_DIR_DIRTY;
11571160
}
1158-
return SdVolume::cacheFlush();
1161+
1162+
if (!blocking) {
1163+
flags_ &= ~F_FILE_NON_BLOCKING_WRITE;
1164+
}
1165+
1166+
return SdVolume::cacheFlush(blocking);
11591167
}
11601168
//------------------------------------------------------------------------------
11611169
/**
@@ -1325,6 +1333,8 @@ size_t SdFile::write(const void* buf, uint16_t nbyte) {
13251333

13261334
// number of bytes left to write - must be before goto statements
13271335
uint16_t nToWrite = nbyte;
1336+
// if blocking writes should be used
1337+
uint8_t blocking = (flags_ & F_FILE_NON_BLOCKING_WRITE) == 0x00;
13281338

13291339
// error if not a normal file or is read-only
13301340
if (!isFile() || !(flags_ & O_WRITE)) {
@@ -1383,7 +1393,7 @@ size_t SdFile::write(const void* buf, uint16_t nbyte) {
13831393
if (SdVolume::cacheBlockNumber_ == block) {
13841394
SdVolume::cacheBlockNumber_ = 0XFFFFFFFF;
13851395
}
1386-
if (!vol_->writeBlock(block, src)) {
1396+
if (!vol_->writeBlock(block, src, blocking)) {
13871397
goto writeErrorReturn;
13881398
}
13891399
src += 512;
@@ -1473,3 +1483,45 @@ void SdFile::writeln_P(PGM_P str) {
14731483
println();
14741484
}
14751485
#endif
1486+
//------------------------------------------------------------------------------
1487+
/**
1488+
Check how many bytes can be written without blocking.
1489+
1490+
\return The number of bytes that can be written without blocking.
1491+
*/
1492+
int SdFile::availableForWrite() {
1493+
if (!isFile() || !(flags_ & O_WRITE)) {
1494+
return 0;
1495+
}
1496+
1497+
// seek to end of file if append flag
1498+
if ((flags_ & O_APPEND) && curPosition_ != fileSize_) {
1499+
if (!seekEnd()) {
1500+
return 0;
1501+
}
1502+
}
1503+
1504+
if (vol_->isBusy()) {
1505+
return 0;
1506+
}
1507+
1508+
if (flags_ & F_FILE_CLUSTER_ADDED) {
1509+
// new cluster added, trigger a non-blocking sync
1510+
sync(0);
1511+
flags_ &= ~F_FILE_CLUSTER_ADDED;
1512+
return 0;
1513+
}
1514+
1515+
if (vol_->isCacheMirrorBlockDirty()) {
1516+
// cache mirror block is dirty, trigger a non-blocking sync
1517+
vol_->cacheMirrorBlockFlush(0);
1518+
return 0;
1519+
}
1520+
1521+
flags_ |= F_FILE_NON_BLOCKING_WRITE;
1522+
1523+
uint16_t blockOffset = curPosition_ & 0X1FF;
1524+
uint16_t n = 512 - blockOffset;
1525+
1526+
return n;
1527+
}

‎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 true;
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)

AltStyle によって変換されたページ (->オリジナル) /