Browse Source

SDCARD_READONLY (#17884)

Leandro A. F. Pereira 4 years ago
parent
commit
801f99edad
No account linked to committer's email address

+ 2
- 0
Marlin/Configuration_adv.h View File

1084
   // Enable this option and set to HIGH if your SD cards are incorrectly detected.
1084
   // Enable this option and set to HIGH if your SD cards are incorrectly detected.
1085
   //#define SD_DETECT_STATE HIGH
1085
   //#define SD_DETECT_STATE HIGH
1086
 
1086
 
1087
+  //#define SDCARD_READONLY                 // Read-only SD card (to save over 2K of flash)
1088
+
1087
   #define SD_PROCEDURE_DEPTH 1              // Increase if you need more nested M32 calls
1089
   #define SD_PROCEDURE_DEPTH 1              // Increase if you need more nested M32 calls
1088
 
1090
 
1089
   #define SD_FINISHED_STEPPERRELEASE true   // Disable steppers when SD Print is finished
1091
   #define SD_FINISHED_STEPPERRELEASE true   // Disable steppers when SD Print is finished

+ 14
- 0
Marlin/src/inc/SanityCheck.h View File

2063
 #endif
2063
 #endif
2064
 
2064
 
2065
 /**
2065
 /**
2066
+ * Make sure features that need to write to the SD card are
2067
+ * disabled unless write support is enabled.
2068
+ */
2069
+#if ENABLED(SDCARD_READONLY)
2070
+  #if ENABLED(POWER_LOSS_RECOVERY)
2071
+    #error "POWER_LOSS_RECOVERY is incompatible with SDCARD_READONLY."
2072
+  #elif ENABLED(BINARY_FILE_TRANSFER)
2073
+    #error "BINARY_FILE_TRANSFER is incompatible with SDCARD_READONLY."
2074
+  #elif ENABLED(SDCARD_EEPROM_EMULATION)
2075
+    #error "SDCARD_EEPROM_EMULATION is incompatible with SDCARD_READONLY."
2076
+  #endif
2077
+#endif
2078
+
2079
+/**
2066
  * Make sure only one display is enabled
2080
  * Make sure only one display is enabled
2067
  */
2081
  */
2068
 #if 1 < 0 \
2082
 #if 1 < 0 \

+ 13
- 8
Marlin/src/sd/Sd2Card.cpp View File

179
  * \return true for success, false for failure.
179
  * \return true for success, false for failure.
180
  */
180
  */
181
 bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
181
 bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
182
+  if (ENABLED(SDCARD_READONLY)) return false;
183
+
182
   csd_t csd;
184
   csd_t csd;
183
   if (!readCSD(&csd)) goto FAIL;
185
   if (!readCSD(&csd)) goto FAIL;
186
+
184
   // check for single block erase
187
   // check for single block erase
185
   if (!csd.v1.erase_blk_en) {
188
   if (!csd.v1.erase_blk_en) {
186
     // erase size mask
189
     // erase size mask
535
  * \return true for success, false for failure.
538
  * \return true for success, false for failure.
536
  */
539
  */
537
 bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
540
 bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
538
-  if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;   // Use address if not SDHC card
541
+  if (ENABLED(SDCARD_READONLY)) return false;
539
 
542
 
540
   bool success = false;
543
   bool success = false;
544
+  if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;   // Use address if not SDHC card
541
   if (!cardCommand(CMD24, blockNumber)) {
545
   if (!cardCommand(CMD24, blockNumber)) {
542
     if (writeData(DATA_START_BLOCK, src)) {
546
     if (writeData(DATA_START_BLOCK, src)) {
543
       if (waitNotBusy(SD_WRITE_TIMEOUT)) {              // Wait for flashing to complete
547
       if (waitNotBusy(SD_WRITE_TIMEOUT)) {              // Wait for flashing to complete
561
  * \return true for success, false for failure.
565
  * \return true for success, false for failure.
562
  */
566
  */
563
 bool Sd2Card::writeData(const uint8_t* src) {
567
 bool Sd2Card::writeData(const uint8_t* src) {
568
+  if (ENABLED(SDCARD_READONLY)) return false;
569
+
564
   bool success = true;
570
   bool success = true;
565
   chipSelect();
571
   chipSelect();
566
   // Wait for previous write to finish
572
   // Wait for previous write to finish
574
 
580
 
575
 // Send one block of data for write block or write multiple blocks
581
 // Send one block of data for write block or write multiple blocks
576
 bool Sd2Card::writeData(const uint8_t token, const uint8_t* src) {
582
 bool Sd2Card::writeData(const uint8_t token, const uint8_t* src) {
583
+  if (ENABLED(SDCARD_READONLY)) return false;
577
 
584
 
578
-  const uint16_t crc =
579
-    #if ENABLED(SD_CHECK_AND_RETRY)
580
-      CRC_CCITT(src, 512)
581
-    #else
582
-      0xFFFF
583
-    #endif
584
-  ;
585
+  const uint16_t crc = TERN(SD_CHECK_AND_RETRY, CRC_CCITT(src, 512), 0xFFFF);
585
   spiSendBlock(token, src);
586
   spiSendBlock(token, src);
586
   spiSend(crc >> 8);
587
   spiSend(crc >> 8);
587
   spiSend(crc & 0xFF);
588
   spiSend(crc & 0xFF);
607
  * \return true for success, false for failure.
608
  * \return true for success, false for failure.
608
  */
609
  */
609
 bool Sd2Card::writeStart(uint32_t blockNumber, const uint32_t eraseCount) {
610
 bool Sd2Card::writeStart(uint32_t blockNumber, const uint32_t eraseCount) {
611
+  if (ENABLED(SDCARD_READONLY)) return false;
612
+
610
   bool success = false;
613
   bool success = false;
611
   if (!cardAcmd(ACMD23, eraseCount)) {                    // Send pre-erase count
614
   if (!cardAcmd(ACMD23, eraseCount)) {                    // Send pre-erase count
612
     if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;   // Use address if not SDHC card
615
     if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;   // Use address if not SDHC card
626
  * \return true for success, false for failure.
629
  * \return true for success, false for failure.
627
  */
630
  */
628
 bool Sd2Card::writeStop() {
631
 bool Sd2Card::writeStop() {
632
+  if (ENABLED(SDCARD_READONLY)) return false;
633
+
629
   bool success = false;
634
   bool success = false;
630
   chipSelect();
635
   chipSelect();
631
   if (waitNotBusy(SD_WRITE_TIMEOUT)) {
636
   if (waitNotBusy(SD_WRITE_TIMEOUT)) {

+ 37
- 3
Marlin/src/sd/SdBaseFile.cpp View File

47
 
47
 
48
 // add a cluster to a file
48
 // add a cluster to a file
49
 bool SdBaseFile::addCluster() {
49
 bool SdBaseFile::addCluster() {
50
+  if (ENABLED(SDCARD_READONLY)) return false;
51
+
50
   if (!vol_->allocContiguous(1, &curCluster_)) return false;
52
   if (!vol_->allocContiguous(1, &curCluster_)) return false;
51
 
53
 
52
   // if first cluster of file link to directory entry
54
   // if first cluster of file link to directory entry
60
 // Add a cluster to a directory file and zero the cluster.
62
 // Add a cluster to a directory file and zero the cluster.
61
 // return with first block of cluster in the cache
63
 // return with first block of cluster in the cache
62
 bool SdBaseFile::addDirCluster() {
64
 bool SdBaseFile::addDirCluster() {
65
+  if (ENABLED(SDCARD_READONLY)) return false;
66
+
63
   uint32_t block;
67
   uint32_t block;
64
   // max folder size
68
   // max folder size
65
   if (fileSize_ / sizeof(dir_t) >= 0xFFFF) return false;
69
   if (fileSize_ / sizeof(dir_t) >= 0xFFFF) return false;
153
  *
157
  *
154
  */
158
  */
155
 bool SdBaseFile::createContiguous(SdBaseFile* dirFile, const char* path, uint32_t size) {
159
 bool SdBaseFile::createContiguous(SdBaseFile* dirFile, const char* path, uint32_t size) {
160
+  if (ENABLED(SDCARD_READONLY)) return false;
161
+
156
   uint32_t count;
162
   uint32_t count;
157
   // don't allow zero length file
163
   // don't allow zero length file
158
   if (size == 0) return false;
164
   if (size == 0) return false;
419
  * directory, \a path is invalid or already exists in \a parent.
425
  * directory, \a path is invalid or already exists in \a parent.
420
  */
426
  */
421
 bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) {
427
 bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) {
428
+  if (ENABLED(SDCARD_READONLY)) return false;
429
+
422
   uint8_t dname[11];
430
   uint8_t dname[11];
423
   SdBaseFile dir1, dir2;
431
   SdBaseFile dir1, dir2;
424
   SdBaseFile* sub = &dir1;
432
   SdBaseFile* sub = &dir1;
449
 }
457
 }
450
 
458
 
451
 bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
459
 bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
460
+  if (ENABLED(SDCARD_READONLY)) return false;
461
+
452
   uint32_t block;
462
   uint32_t block;
453
   dir_t d;
463
   dir_t d;
454
   dir_t* p;
464
   dir_t* p;
632
   }
642
   }
633
   else {
643
   else {
634
     // don't create unless O_CREAT and O_WRITE
644
     // don't create unless O_CREAT and O_WRITE
635
-    if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) return false;
645
+    if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) return false;
636
     if (emptyFound) {
646
     if (emptyFound) {
637
       index = dirIndex_;
647
       index = dirIndex_;
638
       p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
648
       p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
716
 
726
 
717
 // open a cached directory entry. Assumes vol_ is initialized
727
 // open a cached directory entry. Assumes vol_ is initialized
718
 bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
728
 bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
729
+  dir_t* p;
730
+
731
+  #if ENABLED(SDCARD_READONLY)
732
+    if (oflag & (O_WRITE | O_CREAT | O_TRUNC)) goto FAIL;
733
+  #endif
734
+
719
   // location of entry in cache
735
   // location of entry in cache
720
-  dir_t* p = &vol_->cache()->dir[dirIndex];
736
+  p = &vol_->cache()->dir[dirIndex];
721
 
737
 
722
   // write or truncate is an error for a directory or read-only file
738
   // write or truncate is an error for a directory or read-only file
723
   if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) {
739
   if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) {
1135
  * or an I/O error occurred.
1151
  * or an I/O error occurred.
1136
  */
1152
  */
1137
 bool SdBaseFile::remove() {
1153
 bool SdBaseFile::remove() {
1154
+  if (ENABLED(SDCARD_READONLY)) return false;
1155
+
1138
   dir_t* d;
1156
   dir_t* d;
1139
   // free any clusters - will fail if read-only or directory
1157
   // free any clusters - will fail if read-only or directory
1140
   if (!truncate(0)) return false;
1158
   if (!truncate(0)) return false;
1172
  * or an I/O error occurred.
1190
  * or an I/O error occurred.
1173
  */
1191
  */
1174
 bool SdBaseFile::remove(SdBaseFile* dirFile, const char* path) {
1192
 bool SdBaseFile::remove(SdBaseFile* dirFile, const char* path) {
1193
+  if (ENABLED(SDCARD_READONLY)) return false;
1194
+
1175
   SdBaseFile file;
1195
   SdBaseFile file;
1176
   return file.open(dirFile, path, O_WRITE) ? file.remove() : false;
1196
   return file.open(dirFile, path, O_WRITE) ? file.remove() : false;
1177
 }
1197
 }
1187
  * file, newPath is invalid or already exists, or an I/O error occurs.
1207
  * file, newPath is invalid or already exists, or an I/O error occurs.
1188
  */
1208
  */
1189
 bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
1209
 bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
1210
+  if (ENABLED(SDCARD_READONLY)) return false;
1211
+
1190
   dir_t entry;
1212
   dir_t entry;
1191
   uint32_t dirCluster = 0;
1213
   uint32_t dirCluster = 0;
1192
   SdBaseFile file;
1214
   SdBaseFile file;
1279
  * directory, is not empty, or an I/O error occurred.
1301
  * directory, is not empty, or an I/O error occurred.
1280
  */
1302
  */
1281
 bool SdBaseFile::rmdir() {
1303
 bool SdBaseFile::rmdir() {
1304
+  if (ENABLED(SDCARD_READONLY)) return false;
1305
+
1282
   // must be open subdirectory
1306
   // must be open subdirectory
1283
   if (!isSubDir()) return false;
1307
   if (!isSubDir()) return false;
1284
 
1308
 
1317
  * \return true for success, false for failure.
1341
  * \return true for success, false for failure.
1318
  */
1342
  */
1319
 bool SdBaseFile::rmRfStar() {
1343
 bool SdBaseFile::rmRfStar() {
1344
+  if (ENABLED(SDCARD_READONLY)) return false;
1345
+
1320
   uint32_t index;
1346
   uint32_t index;
1321
   SdBaseFile f;
1347
   SdBaseFile f;
1322
   rewind();
1348
   rewind();
1424
  */
1450
  */
1425
 bool SdBaseFile::sync() {
1451
 bool SdBaseFile::sync() {
1426
   // only allow open files and directories
1452
   // only allow open files and directories
1427
-  if (!isOpen()) goto FAIL;
1453
+  if (ENABLED(SDCARD_READONLY) || !isOpen()) goto FAIL;
1428
 
1454
 
1429
   if (flags_ & F_FILE_DIR_DIRTY) {
1455
   if (flags_ & F_FILE_DIR_DIRTY) {
1430
     dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
1456
     dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
1524
  */
1550
  */
1525
 bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
1551
 bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
1526
                            uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
1552
                            uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
1553
+  if (ENABLED(SDCARD_READONLY)) return false;
1554
+
1527
   uint16_t dirDate, dirTime;
1555
   uint16_t dirDate, dirTime;
1528
   dir_t* d;
1556
   dir_t* d;
1529
 
1557
 
1575
  * \a length is greater than the current file size or an I/O error occurs.
1603
  * \a length is greater than the current file size or an I/O error occurs.
1576
  */
1604
  */
1577
 bool SdBaseFile::truncate(uint32_t length) {
1605
 bool SdBaseFile::truncate(uint32_t length) {
1606
+  if (ENABLED(SDCARD_READONLY)) return false;
1607
+
1578
   uint32_t newPos;
1608
   uint32_t newPos;
1579
   // error if not a normal file or read-only
1609
   // error if not a normal file or read-only
1580
   if (!isFile() || !(flags_ & O_WRITE)) return false;
1610
   if (!isFile() || !(flags_ & O_WRITE)) return false;
1636
  *
1666
  *
1637
  */
1667
  */
1638
 int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
1668
 int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
1669
+  #if ENABLED(SDCARD_READONLY)
1670
+    writeError = true; return -1;
1671
+  #endif
1672
+
1639
   // convert void* to uint8_t*  -  must be before goto statements
1673
   // convert void* to uint8_t*  -  must be before goto statements
1640
   const uint8_t* src = reinterpret_cast<const uint8_t*>(buf);
1674
   const uint8_t* src = reinterpret_cast<const uint8_t*>(buf);
1641
 
1675
 

+ 16
- 10
Marlin/src/sd/SdVolume.cpp View File

46
 
46
 
47
 // find a contiguous group of clusters
47
 // find a contiguous group of clusters
48
 bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
48
 bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
49
+  if (ENABLED(SDCARD_READONLY)) return false;
50
+
49
   // start of group
51
   // start of group
50
   uint32_t bgnCluster;
52
   uint32_t bgnCluster;
51
   // end of group
53
   // end of group
117
 }
119
 }
118
 
120
 
119
 bool SdVolume::cacheFlush() {
121
 bool SdVolume::cacheFlush() {
120
-  if (cacheDirty_) {
121
-    if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data))
122
-      return false;
123
-
124
-    // mirror FAT tables
125
-    if (cacheMirrorBlock_) {
126
-      if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data))
122
+  #if DISABLED(SDCARD_READONLY)
123
+    if (cacheDirty_) {
124
+      if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data))
127
         return false;
125
         return false;
128
-      cacheMirrorBlock_ = 0;
126
+
127
+      // mirror FAT tables
128
+      if (cacheMirrorBlock_) {
129
+        if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data))
130
+          return false;
131
+        cacheMirrorBlock_ = 0;
132
+      }
133
+      cacheDirty_ = 0;
129
     }
134
     }
130
-    cacheDirty_ = 0;
131
-  }
135
+  #endif
132
   return true;
136
   return true;
133
 }
137
 }
134
 
138
 
190
 
194
 
191
 // Store a FAT entry
195
 // Store a FAT entry
192
 bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
196
 bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
197
+  if (ENABLED(SDCARD_READONLY)) return false;
198
+
193
   uint32_t lba;
199
   uint32_t lba;
194
   // error if reserved cluster
200
   // error if reserved cluster
195
   if (cluster < 2) return false;
201
   if (cluster < 2) return false;

+ 25
- 17
Marlin/src/sd/cardreader.cpp View File

446
 }
446
 }
447
 
447
 
448
 void CardReader::openLogFile(char * const path) {
448
 void CardReader::openLogFile(char * const path) {
449
-  flag.logging = true;
450
-  openFileWrite(path);
449
+  flag.logging = DISABLED(SDCARD_READONLY);
450
+  TERN(SDCARD_READONLY,,openFileWrite(path));
451
 }
451
 }
452
 
452
 
453
 //
453
 //
573
   const char * const fname = diveToFile(false, curDir, path);
573
   const char * const fname = diveToFile(false, curDir, path);
574
   if (!fname) return;
574
   if (!fname) return;
575
 
575
 
576
-  if (file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
577
-    flag.saving = true;
578
-    selectFileByName(fname);
579
-    TERN_(EMERGENCY_PARSER, emergency_parser.disable());
580
-    echo_write_to_file(fname);
581
-    ui.set_status(fname);
582
-  }
583
-  else
576
+  #if ENABLED(SDCARD_READONLY)
584
     openFailed(fname);
577
     openFailed(fname);
578
+  #else
579
+    if (file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
580
+      flag.saving = true;
581
+      selectFileByName(fname);
582
+      TERN_(EMERGENCY_PARSER, emergency_parser.disable());
583
+      echo_write_to_file(fname);
584
+      ui.set_status(fname);
585
+    }
586
+    else
587
+      openFailed(fname);
588
+  #endif
585
 }
589
 }
586
 
590
 
587
 //
591
 //
596
   const char * const fname = diveToFile(false, curDir, name);
600
   const char * const fname = diveToFile(false, curDir, name);
597
   if (!fname) return;
601
   if (!fname) return;
598
 
602
 
599
-  if (file.remove(curDir, fname)) {
600
-    SERIAL_ECHOLNPAIR("File deleted:", fname);
601
-    sdpos = 0;
602
-    TERN_(SDCARD_SORT_ALPHA, presort());
603
-  }
604
-  else
605
-    SERIAL_ECHOLNPAIR("Deletion failed, File: ", fname, ".");
603
+  #if ENABLED(SDCARD_READONLY)
604
+    SERIAL_ECHOLNPAIR("Deletion failed (read-only), File: ", fname, ".");
605
+  #else
606
+    if (file.remove(curDir, fname)) {
607
+      SERIAL_ECHOLNPAIR("File deleted:", fname);
608
+      sdpos = 0;
609
+      TERN_(SDCARD_SORT_ALPHA, presort());
610
+    }
611
+    else
612
+      SERIAL_ECHOLNPAIR("Deletion failed, File: ", fname, ".");
613
+  #endif
606
 }
614
 }
607
 
615
 
608
 void CardReader::report_status() {
616
 void CardReader::report_status() {

+ 1
- 2
buildroot/share/tests/LPC1768-tests View File

15
 
15
 
16
 restore_configs
16
 restore_configs
17
 opt_set MOTHERBOARD BOARD_RAMPS_14_RE_ARM_EFB
17
 opt_set MOTHERBOARD BOARD_RAMPS_14_RE_ARM_EFB
18
-opt_enable VIKI2 SDSUPPORT SERIAL_PORT_2 NEOPIXEL_LED
19
-
18
+opt_enable VIKI2 SDSUPPORT SDCARD_READONLY SERIAL_PORT_2 NEOPIXEL_LED
20
 opt_set NEOPIXEL_PIN P1_16
19
 opt_set NEOPIXEL_PIN P1_16
21
 exec_test $1 $2 "ReARM EFB VIKI2, SDSUPPORT, 2 Serial ports (USB CDC + UART0), NeoPixel"
20
 exec_test $1 $2 "ReARM EFB VIKI2, SDSUPPORT, 2 Serial ports (USB CDC + UART0), NeoPixel"
22
 
21
 

Loading…
Cancel
Save