|
@@ -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
|
|