Преглед на файлове

Backported latest improvements and fixes from the SdFat liibrary to our own version. This includes support for CRC7 validation on commands and also, made sure that even if using software SPI implementations, SD card speed is properly adjusted when transitioning from INITIALIZATION to DATA TRANSFER mode. ALL HALs implement spiInit, even in SW SPI mode, and we NEED this change to improve 25x the transfer speed of the SD card and allow implementations of USB MSD

etagle преди 7 години
родител
ревизия
9aff55ed1f
променени са 3 файла, в които са добавени 166 реда и са изтрити 73 реда
  1. 155
    64
      Marlin/src/sd/Sd2Card.cpp
  2. 4
    3
      Marlin/src/sd/Sd2Card.h
  3. 7
    6
      Marlin/src/sd/SdInfo.h

+ 155
- 64
Marlin/src/sd/Sd2Card.cpp Целия файл

@@ -23,6 +23,7 @@
23 23
 /**
24 24
  * Arduino Sd2Card Library
25 25
  * Copyright (C) 2009 by William Greiman
26
+ * Updated with backports of the latest SdFat library from the same author
26 27
  *
27 28
  * This file is part of the Arduino Sd2Card Library
28 29
  */
@@ -31,29 +32,92 @@
31 32
 
32 33
 #if ENABLED(SDSUPPORT)
33 34
 
35
+/* Enable FAST CRC computations - You can trade speed for FLASH space if
36
+ * needed by disabling the following define */
37
+#define FAST_CRC 1
38
+
34 39
 #include "Sd2Card.h"
35 40
 
36 41
 #include "../Marlin.h"
37 42
 
43
+#if ENABLED(SD_CHECK_AND_RETRY)
44
+  #ifdef FAST_CRC
45
+    static const uint8_t crctab7[] PROGMEM = {
46
+      0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77,
47
+      0x19,0x10,0x0b,0x02,0x3d,0x34,0x2f,0x26,0x51,0x58,0x43,0x4a,0x75,0x7c,0x67,0x6e,
48
+      0x32,0x3b,0x20,0x29,0x16,0x1f,0x04,0x0d,0x7a,0x73,0x68,0x61,0x5e,0x57,0x4c,0x45,
49
+      0x2b,0x22,0x39,0x30,0x0f,0x06,0x1d,0x14,0x63,0x6a,0x71,0x78,0x47,0x4e,0x55,0x5c,
50
+      0x64,0x6d,0x76,0x7f,0x40,0x49,0x52,0x5b,0x2c,0x25,0x3e,0x37,0x08,0x01,0x1a,0x13,
51
+      0x7d,0x74,0x6f,0x66,0x59,0x50,0x4b,0x42,0x35,0x3c,0x27,0x2e,0x11,0x18,0x03,0x0a,
52
+      0x56,0x5f,0x44,0x4d,0x72,0x7b,0x60,0x69,0x1e,0x17,0x0c,0x05,0x3a,0x33,0x28,0x21,
53
+      0x4f,0x46,0x5d,0x54,0x6b,0x62,0x79,0x70,0x07,0x0e,0x15,0x1c,0x23,0x2a,0x31,0x38,
54
+      0x41,0x48,0x53,0x5a,0x65,0x6c,0x77,0x7e,0x09,0x00,0x1b,0x12,0x2d,0x24,0x3f,0x36,
55
+      0x58,0x51,0x4a,0x43,0x7c,0x75,0x6e,0x67,0x10,0x19,0x02,0x0b,0x34,0x3d,0x26,0x2f,
56
+      0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c,0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04,
57
+      0x6a,0x63,0x78,0x71,0x4e,0x47,0x5c,0x55,0x22,0x2b,0x30,0x39,0x06,0x0f,0x14,0x1d,
58
+      0x25,0x2c,0x37,0x3e,0x01,0x08,0x13,0x1a,0x6d,0x64,0x7f,0x76,0x49,0x40,0x5b,0x52,
59
+      0x3c,0x35,0x2e,0x27,0x18,0x11,0x0a,0x03,0x74,0x7d,0x66,0x6f,0x50,0x59,0x42,0x4b,
60
+      0x17,0x1e,0x05,0x0c,0x33,0x3a,0x21,0x28,0x5f,0x56,0x4d,0x44,0x7b,0x72,0x69,0x60,
61
+      0x0e,0x07,0x1c,0x15,0x2a,0x23,0x38,0x31,0x46,0x4f,0x54,0x5d,0x62,0x6b,0x70,0x79
62
+    };
63
+
64
+    static uint8_t CRC7(const uint8_t* data, uint8_t n) {
65
+      uint8_t crc = 0;
66
+      while ( n > 0 ) {
67
+        crc = pgm_read_byte(&crctab7[ (crc << 1) ^ *data++ ]);
68
+        n--;
69
+      }
70
+      return (crc << 1) | 1;
71
+    }
72
+  #else
73
+    static uint8_t CRC7(const uint8_t* data, uint8_t n) {
74
+      uint8_t crc = 0;
75
+      for (uint8_t i = 0; i < n; i++) {
76
+        uint8_t d = data[i];
77
+        d ^= crc << 1;
78
+        if (d & 0x80) d ^= 9;
79
+        crc = d ^ (crc & 0x78) ^ (crc << 4) ^ ((crc >> 3) & 15);
80
+        crc &= 0x7f;
81
+      }
82
+      crc = (crc << 1) ^ (crc << 4) ^ (crc & 0x70) ^ ((crc >> 3) & 0x0f);
83
+      return crc | 1;
84
+    }
85
+  #endif
86
+#endif
87
+
38 88
 // send command and return error code.  Return zero for OK
39 89
 uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
40 90
   // select card
41
-  chipSelectLow();
91
+  chipSelect();
42 92
 
43 93
   // wait up to 300 ms if busy
44
-  waitNotBusy(300);
94
+  waitNotBusy( SD_WRITE_TIMEOUT );
95
+
96
+  uint8_t *pa = (uint8_t *)(&arg);
45 97
 
98
+#if ENABLED(SD_CHECK_AND_RETRY)
99
+
100
+  // form message
101
+  uint8_t d[6] = {(uint8_t) (cmd | 0x40), pa[3], pa[2], pa[1], pa[0] };
102
+
103
+  // add crc
104
+  d[5] = CRC7(d, 5);
105
+
106
+  // send message
107
+  for (uint8_t k = 0; k < 6; k++ )
108
+    spiSend( d[k] );
109
+
110
+#else
46 111
   // send command
47 112
   spiSend(cmd | 0x40);
48 113
 
49 114
   // send argument
50
-  for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
115
+  for( int8_t i = 3; i >= 0; i-- )
116
+    spiSend( pa[i] );
51 117
 
52
-  // send CRC
53
-  uint8_t crc = 0xFF;
54
-  if (cmd == CMD0) crc = 0x95;  // correct crc for CMD0 with arg 0
55
-  if (cmd == CMD8) crc = 0x87;  // correct crc for CMD8 with arg 0x1AA
56
-  spiSend(crc);
118
+  // send CRC - correct for CMD0 with arg zero or CMD8 with arg 0X1AA
119
+  spiSend( cmd == CMD0 ? 0X95 : 0X87 );
120
+#endif
57 121
 
58 122
   // skip stuff byte for stop read
59 123
   if (cmd == CMD12) spiRec();
@@ -91,14 +155,15 @@ uint32_t Sd2Card::cardSize() {
91 155
   }
92 156
 }
93 157
 
94
-void Sd2Card::chipSelectHigh() {
158
+void Sd2Card::chipDeselect() {
95 159
   digitalWrite(chipSelectPin_, HIGH);
160
+
161
+  // insure MISO goes high impedance
162
+  spiSend( 0xFF );
96 163
 }
97 164
 
98
-void Sd2Card::chipSelectLow() {
99
-  #if DISABLED(SOFTWARE_SPI)
100
-    spiInit(spiRate_);
101
-  #endif  // SOFTWARE_SPI
165
+void Sd2Card::chipSelect() {
166
+  spiInit(spiRate_);
102 167
   digitalWrite(chipSelectPin_, LOW);
103 168
 }
104 169
 
@@ -142,10 +207,10 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
142 207
     error(SD_CARD_ERROR_ERASE_TIMEOUT);
143 208
     goto FAIL;
144 209
   }
145
-  chipSelectHigh();
210
+  chipDeselect();
146 211
   return true;
147 212
   FAIL:
148
-  chipSelectHigh();
213
+  chipDeselect();
149 214
   return false;
150 215
 }
151 216
 
@@ -200,22 +265,36 @@ bool Sd2Card::init(uint8_t sckRateID, pin_t chipSelectPin) {
200 265
       goto FAIL;
201 266
     }
202 267
   }
268
+
269
+#if ENABLED(SD_CHECK_AND_RETRY)
270
+  if (cardCommand( CMD59, 1 ) != R1_IDLE_STATE) {
271
+    error(SD_CARD_ERROR_CMD59);
272
+    goto FAIL;
273
+  }
274
+#endif
275
+
203 276
   // check SD version
204
-  if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
277
+  while (1) {
278
+    if (cardCommand(CMD8, 0x1AA) == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)) {
205 279
     type(SD_CARD_TYPE_SD1);
280
+      break;
206 281
   }
207
-  else {
282
+
208 283
     // only need last byte of r7 response
209 284
     for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
210
-    if (status_ != 0xAA) {
285
+    if (status_ == 0xAA) {
286
+      type(SD_CARD_TYPE_SD2);
287
+      break;
288
+    }
289
+
290
+    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
211 291
       error(SD_CARD_ERROR_CMD8);
212 292
       goto FAIL;
213 293
     }
214
-    type(SD_CARD_TYPE_SD2);
215 294
   }
295
+
216 296
   // initialize card and send host supports SDHC if SD2
217 297
   arg = type() == SD_CARD_TYPE_SD2 ? 0x40000000 : 0;
218
-
219 298
   while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
220 299
     // check for timeout
221 300
     if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
@@ -233,17 +312,12 @@ bool Sd2Card::init(uint8_t sckRateID, pin_t chipSelectPin) {
233 312
     // discard rest of ocr - contains allowed voltage range
234 313
     for (uint8_t i = 0; i < 3; i++) spiRec();
235 314
   }
236
-  chipSelectHigh();
315
+  chipDeselect();
237 316
 
238
-  #if DISABLED(SOFTWARE_SPI)
239
-    return setSckRate(sckRateID);
240
-  #else  // SOFTWARE_SPI
241
-    UNUSED(sckRateID);
242
-    return true;
243
-  #endif  // SOFTWARE_SPI
317
+  return setSckRate(sckRateID);
244 318
 
245 319
   FAIL:
246
-  chipSelectHigh();
320
+  chipDeselect();
247 321
   return false;
248 322
 }
249 323
 
@@ -268,7 +342,7 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
268 342
 
269 343
       if (!--retryCnt) break;
270 344
 
271
-      chipSelectHigh();
345
+      chipDeselect();
272 346
       cardCommand(CMD12, 0); // Try sending a stop command, ignore the result.
273 347
       errorCode_ = 0;
274 348
     }
@@ -279,7 +353,7 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
279 353
       return readData(dst, 512);
280 354
   #endif
281 355
 
282
-  chipSelectHigh();
356
+  chipDeselect();
283 357
   return false;
284 358
 }
285 359
 
@@ -291,12 +365,13 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
291 365
  * \return true for success, false for failure.
292 366
  */
293 367
 bool Sd2Card::readData(uint8_t* dst) {
294
-  chipSelectLow();
368
+  chipSelect();
295 369
   return readData(dst, 512);
296 370
 }
297 371
 
298 372
 #if ENABLED(SD_CHECK_AND_RETRY)
299
-  static const uint16_t crctab[] PROGMEM = {
373
+  #ifdef FAST_CRC
374
+  static const uint16_t crctab16[] PROGMEM = {
300 375
     0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
301 376
     0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
302 377
     0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
@@ -330,13 +405,30 @@ bool Sd2Card::readData(uint8_t* dst) {
330 405
     0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
331 406
     0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
332 407
   };
408
+    // faster CRC-CCITT
409
+    // uses the x^16,x^12,x^5,x^1 polynomial.
333 410
   static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
334 411
     uint16_t crc = 0;
335 412
     for (size_t i = 0; i < n; i++) {
336
-      crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0xFF]) ^ (crc << 8);
413
+      crc = pgm_read_word(&crctab16[(crc >> 8 ^ data[i]) & 0xFF]) ^ (crc << 8);
337 414
     }
338 415
     return crc;
339 416
   }
417
+  #else
418
+    // slower CRC-CCITT
419
+    // uses the x^16,x^12,x^5,x^1 polynomial.
420
+    static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
421
+      uint16_t crc = 0;
422
+      for (size_t i = 0; i < n; i++) {
423
+        crc = (uint8_t)(crc >> 8) | (crc << 8);
424
+        crc ^= data[i];
425
+        crc ^= (uint8_t)(crc & 0xff) >> 4;
426
+        crc ^= crc << 12;
427
+        crc ^= (crc & 0xff) << 5;
428
+      }
429
+      return crc;
430
+    }
431
+  #endif
340 432
 #endif // SD_CHECK_AND_RETRY
341 433
 
342 434
 bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
@@ -357,11 +449,9 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
357 449
 
358 450
 #if ENABLED(SD_CHECK_AND_RETRY)
359 451
   {
360
-    uint16_t calcCrc = CRC_CCITT(dst, count);
361
-    uint16_t recvCrc = spiRec() << 8;
362
-    recvCrc |= spiRec();
363
-    if (calcCrc != recvCrc) {
364
-      error(SD_CARD_ERROR_CRC);
452
+    uint16_t recvCrc = (spiRec() << 8) | spiRec();
453
+    if (recvCrc != CRC_CCITT(dst, count)) {
454
+      error(SD_CARD_ERROR_READ_CRC);
365 455
       goto FAIL;
366 456
     }
367 457
   }
@@ -370,14 +460,10 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
370 460
   spiRec();
371 461
   spiRec();
372 462
 #endif
373
-  chipSelectHigh();
374
-  // Send an additional dummy byte, required by Toshiba Flash Air SD Card
375
-  spiSend(0xFF);
463
+  chipDeselect();
376 464
   return true;
377 465
   FAIL:
378
-  chipSelectHigh();
379
-  // Send an additional dummy byte, required by Toshiba Flash Air SD Card
380
-  spiSend(0xFF);
466
+  chipDeselect();
381 467
   return false;
382 468
 }
383 469
 
@@ -386,7 +472,7 @@ bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
386 472
   uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
387 473
   if (cardCommand(cmd, 0)) {
388 474
     error(SD_CARD_ERROR_READ_REG);
389
-    chipSelectHigh();
475
+    chipDeselect();
390 476
     return false;
391 477
   }
392 478
   return readData(dst, 16);
@@ -406,10 +492,10 @@ bool Sd2Card::readStart(uint32_t blockNumber) {
406 492
   if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
407 493
   if (cardCommand(CMD18, blockNumber)) {
408 494
     error(SD_CARD_ERROR_CMD18);
409
-    chipSelectHigh();
495
+    chipDeselect();
410 496
     return false;
411 497
   }
412
-  chipSelectHigh();
498
+  chipDeselect();
413 499
   return true;
414 500
 }
415 501
 
@@ -419,13 +505,13 @@ bool Sd2Card::readStart(uint32_t blockNumber) {
419 505
  * \return true for success, false for failure.
420 506
  */
421 507
 bool Sd2Card::readStop() {
422
-  chipSelectLow();
508
+  chipSelect();
423 509
   if (cardCommand(CMD12, 0)) {
424 510
     error(SD_CARD_ERROR_CMD12);
425
-    chipSelectHigh();
511
+    chipDeselect();
426 512
     return false;
427 513
   }
428
-  chipSelectHigh();
514
+  chipDeselect();
429 515
   return true;
430 516
 }
431 517
 
@@ -485,10 +571,10 @@ bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
485 571
     error(SD_CARD_ERROR_WRITE_PROGRAMMING);
486 572
     goto FAIL;
487 573
   }
488
-  chipSelectHigh();
574
+  chipDeselect();
489 575
   return true;
490 576
   FAIL:
491
-  chipSelectHigh();
577
+  chipDeselect();
492 578
   return false;
493 579
 }
494 580
 
@@ -498,28 +584,33 @@ bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
498 584
  * \return true for success, false for failure.
499 585
  */
500 586
 bool Sd2Card::writeData(const uint8_t* src) {
501
-  chipSelectLow();
587
+  chipSelect();
502 588
   // wait for previous write to finish
503 589
   if (!waitNotBusy(SD_WRITE_TIMEOUT) || !writeData(WRITE_MULTIPLE_TOKEN, src)) {
504 590
     error(SD_CARD_ERROR_WRITE_MULTIPLE);
505
-    chipSelectHigh();
591
+    chipDeselect();
506 592
     return false;
507 593
   }
508
-  chipSelectHigh();
594
+  chipDeselect();
509 595
   return true;
510 596
 }
511 597
 
512 598
 // send one block of data for write block or write multiple blocks
513 599
 bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
514
-  spiSendBlock(token, src);
515 600
 
516
-  spiSend(0xFF);  // dummy crc
517
-  spiSend(0xFF);  // dummy crc
601
+#if ENABLED(SD_CHECK_AND_RETRY)
602
+  uint16_t crc = CRC_CCITT( src, 512 );
603
+#else  // ENABLED(SD_CHECK_AND_RETRY)
604
+  uint16_t crc = 0xFFFF;
605
+#endif  // ENABLED(SD_CHECK_AND_RETRY)
606
+  spiSendBlock( token, src );
607
+  spiSend( crc >> 8 );
608
+  spiSend( crc & 0XFF );
518 609
 
519 610
   status_ = spiRec();
520 611
   if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
521 612
     error(SD_CARD_ERROR_WRITE);
522
-    chipSelectHigh();
613
+    chipDeselect();
523 614
     return false;
524 615
   }
525 616
   return true;
@@ -548,10 +639,10 @@ bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
548 639
     error(SD_CARD_ERROR_CMD25);
549 640
     goto FAIL;
550 641
   }
551
-  chipSelectHigh();
642
+  chipDeselect();
552 643
   return true;
553 644
   FAIL:
554
-  chipSelectHigh();
645
+  chipDeselect();
555 646
   return false;
556 647
 }
557 648
 
@@ -561,15 +652,15 @@ bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
561 652
  * \return true for success, false for failure.
562 653
  */
563 654
 bool Sd2Card::writeStop() {
564
-  chipSelectLow();
655
+  chipSelect();
565 656
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
566 657
   spiSend(STOP_TRAN_TOKEN);
567 658
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
568
-  chipSelectHigh();
659
+  chipDeselect();
569 660
   return true;
570 661
   FAIL:
571 662
   error(SD_CARD_ERROR_STOP_TRAN);
572
-  chipSelectHigh();
663
+  chipDeselect();
573 664
   return false;
574 665
 }
575 666
 

+ 4
- 3
Marlin/src/sd/Sd2Card.h Целия файл

@@ -71,7 +71,8 @@ uint8_t const SD_CARD_ERROR_CMD0 = 0x01,                // timeout error for com
71 71
               SD_CARD_ERROR_WRITE_TIMEOUT = 0x17,       // timeout occurred during write programming
72 72
               SD_CARD_ERROR_SCK_RATE = 0x18,            // incorrect rate selected
73 73
               SD_CARD_ERROR_INIT_NOT_CALLED = 0x19,     // init() not called
74
-              SD_CARD_ERROR_CRC = 0x20;                 // crc check error
74
+              SD_CARD_ERROR_CMD59 = 0x1A,               // card returned an error for CMD59 (CRC_ON_OFF)
75
+              SD_CARD_ERROR_READ_CRC = 0x1B;            // invalid read CRC
75 76
 
76 77
 // card types
77 78
 uint8_t const SD_CARD_TYPE_SD1  = 1,                    // Standard capacity V1 SD card
@@ -196,8 +197,8 @@ class Sd2Card {
196 197
 
197 198
   bool readData(uint8_t* dst, uint16_t count);
198 199
   bool readRegister(uint8_t cmd, void* buf);
199
-  void chipSelectHigh();
200
-  void chipSelectLow();
200
+  void chipDeselect();
201
+  void chipSelect();
201 202
   void type(uint8_t value) { type_ = value; }
202 203
   bool waitNotBusy(uint16_t timeoutMillis);
203 204
   bool writeData(uint8_t token, const uint8_t* src);

+ 7
- 6
Marlin/src/sd/SdInfo.h Целия файл

@@ -54,12 +54,13 @@ uint8_t const CMD0 = 0x00,    // GO_IDLE_STATE - init card in spi mode if CS low
54 54
               CMD24 = 0x18,   // WRITE_BLOCK - write a single data block to the card
55 55
               CMD25 = 0x19,   // WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION
56 56
               CMD32 = 0x20,   // ERASE_WR_BLK_START - sets the address of the first block to be erased
57
-              CMD33 = 0x21,   // ERASE_WR_BLK_END - sets the address of the last block of the continuous range to be erased*/
58
-              CMD38 = 0x26,   // ERASE - erase all previously selected blocks */
59
-              CMD55 = 0x37,   // APP_CMD - escape for application specific command */
60
-              CMD58 = 0x3A,   // READ_OCR - read the OCR register of a card */
61
-              ACMD23 = 0x17,  // SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be pre-erased before writing */
62
-              ACMD41 = 0x29;  // SD_SEND_OP_COMD - Sends host capacity support information and activates the card's initialization process */
57
+              CMD33 = 0x21,   // ERASE_WR_BLK_END - sets the address of the last block of the continuous range to be erased
58
+              CMD38 = 0x26,   // ERASE - erase all previously selected blocks
59
+              CMD55 = 0x37,   // APP_CMD - escape for application specific command
60
+              CMD58 = 0x3A,   // READ_OCR - read the OCR register of a card
61
+              CMD59 = 0x3B,   // CRC_ON_OFF - enable or disable CRC checking
62
+              ACMD23 = 0x17,  // SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be pre-erased before writing
63
+              ACMD41 = 0x29;  // SD_SEND_OP_COMD - Sends host capacity support information and activates the card's initialization process
63 64
 
64 65
 /** status for card in the ready state */
65 66
 uint8_t const R1_READY_STATE = 0x00;

Loading…
Отказ
Запис