Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 748 lines (685 sloc) 21.589 kb
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
1 /* Arduino Sd2Card Library
2 * Copyright (C) 2009 by William Greiman
3 *
4 * This file is part of the Arduino Sd2Card Library
5 *
6 * This Library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This Library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with the Arduino Sd2Card Library. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
587d4ec Paint Your Dragon Arduino 1.0 compliant
PaintYourDragon authored
20 #if ARDUINO >= 100
21 #include "Arduino.h"
22 #else
23 #include "WProgram.h"
24 #endif
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
25 #include "Sd2Card.h"
26 //------------------------------------------------------------------------------
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
27
28 static int8_t mosiPin_, misoPin_, clockPin_;
29 static volatile uint8_t *mosiport, *clkport, *misoport;
30 static uint8_t mosipinmask, clkpinmask, misopinmask;
31
32 //------------------------------------------------------------------------------
33 /** nop to tune soft SPI timing */
34 #define nop asm volatile ("nop\n\t")
35
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
36 #ifndef SOFTWARE_SPI
37 // functions for hardware SPI
38 /** Send a byte to the card */
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
39 static void spiSend(uint8_t data) {
40 if (clockPin_ == -1) {
41 SPDR = data;
42 while (!(SPSR & (1 << SPIF)));
43 } else {
44 cli();
45 // Fast SPI bitbang swiped from LPD8806 library
46 for (uint8_t i = 0; i < 8; i++) {
47 *clkport &= ~clkpinmask;
48 if (data & 0x80)
49 *mosiport |= mosipinmask;
50 else
51 *mosiport &= ~mosipinmask;
52 *clkport |= clkpinmask;
53 data <<= 1;
54 }
55 nop;nop;nop;nop;
56 *clkport &= ~clkpinmask;
57
58 sei();
59 }
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
60 }
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
61
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
62 /** Receive a byte from the card */
63 static uint8_t spiRec(void) {
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
64 if (clockPin_ == -1) {
65 spiSend(0XFF);
66 return SPDR;
67 } else {
68 uint8_t data = 0;
69 // no interrupts during byte receive - about 8 us
70 cli();
71 // output pin high - like sending 0XFF
72 *mosiport |= mosipinmask;
73
74 for (uint8_t i = 0; i < 8; i++) {
75 *clkport |= clkpinmask;
76 data <<= 1;
77
78 //if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;
79 if ((*misoport) & misopinmask) data |= 1;
80
81 *clkport &= ~clkpinmask;
82
83 // adjust so SCK is nice
84 nop;
85 nop;
86 }
87 // enable interrupts
88 sei();
89 return data;
90 }
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
91 }
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
92
93
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
94 #else // SOFTWARE_SPI
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
95
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
96 //------------------------------------------------------------------------------
97 /** Soft SPI receive */
98 uint8_t spiRec(void) {
99 uint8_t data = 0;
100 // no interrupts during byte receive - about 8 us
101 cli();
102 // output pin high - like sending 0XFF
103 fastDigitalWrite(SPI_MOSI_PIN, HIGH);
104
105 for (uint8_t i = 0; i < 8; i++) {
106 fastDigitalWrite(SPI_SCK_PIN, HIGH);
107
108 // adjust so SCK is nice
109 nop;
110 nop;
111
112 data <<= 1;
113
114 if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;
115
116 fastDigitalWrite(SPI_SCK_PIN, LOW);
117 }
118 // enable interrupts
119 sei();
120 return data;
121 }
122 //------------------------------------------------------------------------------
123 /** Soft SPI send */
124 void spiSend(uint8_t data) {
125 // no interrupts during byte send - about 8 us
126 cli();
127 for (uint8_t i = 0; i < 8; i++) {
128 fastDigitalWrite(SPI_SCK_PIN, LOW);
129
130 fastDigitalWrite(SPI_MOSI_PIN, data & 0X80);
131
132 data <<= 1;
133
134 fastDigitalWrite(SPI_SCK_PIN, HIGH);
135 }
136 // hold SCK high for a few ns
137 nop;
138 nop;
139 nop;
140 nop;
141
142 fastDigitalWrite(SPI_SCK_PIN, LOW);
143 // enable interrupts
144 sei();
145 }
146 #endif // SOFTWARE_SPI
147 //------------------------------------------------------------------------------
148 // send command and return error code. Return zero for OK
149 uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
150 // end read if in partialBlockRead mode
151 readEnd();
152
153 // select card
154 chipSelectLow();
155
156 // wait up to 300 ms if busy
157 waitNotBusy(300);
158
159 // send command
160 spiSend(cmd | 0x40);
161
162 // send argument
163 for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
164
165 // send CRC
166 uint8_t crc = 0XFF;
167 if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0
168 if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA
169 spiSend(crc);
170
171 // wait for response
172 for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++);
173 return status_;
174 }
175 //------------------------------------------------------------------------------
176 /**
177 * Determine the size of an SD flash memory card.
178 *
179 * \return The number of 512 byte data blocks in the card
180 * or zero if an error occurs.
181 */
182 uint32_t Sd2Card::cardSize(void) {
183 csd_t csd;
184 if (!readCSD(&csd)) return 0;
185 if (csd.v1.csd_ver == 0) {
186 uint8_t read_bl_len = csd.v1.read_bl_len;
187 uint16_t c_size = (csd.v1.c_size_high << 10)
188 | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low;
189 uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1)
190 | csd.v1.c_size_mult_low;
191 return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
192 } else if (csd.v2.csd_ver == 1) {
193 uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16)
194 | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low;
195 return (c_size + 1) << 10;
196 } else {
197 error(SD_CARD_ERROR_BAD_CSD);
198 return 0;
199 }
200 }
201 //------------------------------------------------------------------------------
202 void Sd2Card::chipSelectHigh(void) {
203 digitalWrite(chipSelectPin_, HIGH);
204 }
205 //------------------------------------------------------------------------------
206 void Sd2Card::chipSelectLow(void) {
207 digitalWrite(chipSelectPin_, LOW);
208 }
209 //------------------------------------------------------------------------------
210 /** Erase a range of blocks.
211 *
212 * \param[in] firstBlock The address of the first block in the range.
213 * \param[in] lastBlock The address of the last block in the range.
214 *
215 * \note This function requests the SD card to do a flash erase for a
216 * range of blocks. The data on the card after an erase operation is
217 * either 0 or 1, depends on the card vendor. The card must support
218 * single block erase.
219 *
220 * \return The value one, true, is returned for success and
221 * the value zero, false, is returned for failure.
222 */
223 uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
224 if (!eraseSingleBlockEnable()) {
225 error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
226 goto fail;
227 }
228 if (type_ != SD_CARD_TYPE_SDHC) {
229 firstBlock <<= 9;
230 lastBlock <<= 9;
231 }
232 if (cardCommand(CMD32, firstBlock)
233 || cardCommand(CMD33, lastBlock)
234 || cardCommand(CMD38, 0)) {
235 error(SD_CARD_ERROR_ERASE);
236 goto fail;
237 }
238 if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
239 error(SD_CARD_ERROR_ERASE_TIMEOUT);
240 goto fail;
241 }
242 chipSelectHigh();
243 return true;
244
245 fail:
246 chipSelectHigh();
247 return false;
248 }
249 //------------------------------------------------------------------------------
250 /** Determine if card supports single block erase.
251 *
252 * \return The value one, true, is returned if single block erase is supported.
253 * The value zero, false, is returned if single block erase is not supported.
254 */
255 uint8_t Sd2Card::eraseSingleBlockEnable(void) {
256 csd_t csd;
257 return readCSD(&csd) ? csd.v1.erase_blk_en : 0;
258 }
259 //------------------------------------------------------------------------------
260 /**
261 * Initialize an SD flash memory card.
262 *
263 * \param[in] sckRateID SPI clock rate selector. See setSckRate().
264 * \param[in] chipSelectPin SD chip select pin number.
265 *
266 * \return The value one, true, is returned for success and
267 * the value zero, false, is returned for failure. The reason for failure
268 * can be determined by calling errorCode() and errorData().
269 */
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
270 uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin, int8_t mosiPin, int8_t misoPin, int8_t clockPin) {
271
bd7b667 Paint Your Dragon CRC16 calc for Eye-Fi X2 cards
PaintYourDragon authored
272 writeCRC_ = errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
273 chipSelectPin_ = chipSelectPin;
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
274 mosiPin_ = mosiPin;
275 misoPin_ = misoPin;
276 clockPin_ = clockPin;
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
277 // 16-bit init start time allows over a minute
278 uint16_t t0 = (uint16_t)millis();
279 uint32_t arg;
280
281 // set pin modes
282 pinMode(chipSelectPin_, OUTPUT);
283 chipSelectHigh();
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
284
285 if (clockPin != -1) {
286 // use slow bitbang mode
287 pinMode(misoPin_, INPUT);
288 pinMode(mosiPin_, OUTPUT);
289 pinMode(clockPin_, OUTPUT);
290 clkport = portOutputRegister(digitalPinToPort(clockPin_));
291 clkpinmask = digitalPinToBitMask(clockPin_);
292 mosiport = portOutputRegister(digitalPinToPort(mosiPin_));
293 mosipinmask = digitalPinToBitMask(mosiPin_);
294 misoport = portInputRegister(digitalPinToPort(misoPin_));
295 misopinmask = digitalPinToBitMask(misoPin_);
296 } else {
297 pinMode(SPI_MISO_PIN, INPUT);
298 pinMode(SPI_MOSI_PIN, OUTPUT);
299 pinMode(SPI_SCK_PIN, OUTPUT);
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
300
301 #ifndef SOFTWARE_SPI
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
302 // SS must be in output mode even it is not chip select
303 pinMode(SS_PIN, OUTPUT);
304 digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
305 // Enable SPI, Master, clock rate f_osc/128
306 SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
307 // clear double speed
308 SPSR &= ~(1 << SPI2X);
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
309 #endif // SOFTWARE_SPI
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
310 }
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
311
312 // must supply min of 74 clock cycles with CS high.
313 for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
314
315 chipSelectLow();
316
317 // command to go idle in SPI mode
318 while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
319 if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
320 error(SD_CARD_ERROR_CMD0);
321 goto fail;
322 }
323 }
324 // check SD version
325 if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
326 type(SD_CARD_TYPE_SD1);
327 } else {
328 // only need last byte of r7 response
329 for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
330 if (status_ != 0XAA) {
331 error(SD_CARD_ERROR_CMD8);
332 goto fail;
333 }
334 type(SD_CARD_TYPE_SD2);
335 }
336 // initialize card and send host supports SDHC if SD2
337 arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
338
339 while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
340 // check for timeout
341 if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
342 error(SD_CARD_ERROR_ACMD41);
343 goto fail;
344 }
345 }
346 // if SD2 read OCR register to check for SDHC card
347 if (type() == SD_CARD_TYPE_SD2) {
348 if (cardCommand(CMD58, 0)) {
349 error(SD_CARD_ERROR_CMD58);
350 goto fail;
351 }
352 if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
353 // discard rest of ocr - contains allowed voltage range
354 for (uint8_t i = 0; i < 3; i++) spiRec();
355 }
356 chipSelectHigh();
357
358 #ifndef SOFTWARE_SPI
3216c04 Limor "Ladyada" Fried can now select any 4 pins with card.init(), needs testing
ladyada authored
359 if (clockPin_ == -1)
360 return setSckRate(sckRateID);
361 else
362 return true;
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
363 #else // SOFTWARE_SPI
364 return true;
365 #endif // SOFTWARE_SPI
366
367 fail:
368 chipSelectHigh();
369 return false;
370 }
371 //------------------------------------------------------------------------------
372 /**
373 * Enable or disable partial block reads.
374 *
375 * Enabling partial block reads improves performance by allowing a block
376 * to be read over the SPI bus as several sub-blocks. Errors may occur
377 * if the time between reads is too long since the SD card may timeout.
378 * The SPI SS line will be held low until the entire block is read or
379 * readEnd() is called.
380 *
381 * Use this for applications like the Adafruit Wave Shield.
382 *
383 * \param[in] value The value TRUE (non-zero) or FALSE (zero).)
384 */
385 void Sd2Card::partialBlockRead(uint8_t value) {
386 readEnd();
387 partialBlockRead_ = value;
388 }
389 //------------------------------------------------------------------------------
390 /**
391 * Read a 512 byte block from an SD card device.
392 *
393 * \param[in] block Logical block to be read.
394 * \param[out] dst Pointer to the location that will receive the data.
395
396 * \return The value one, true, is returned for success and
397 * the value zero, false, is returned for failure.
398 */
399 uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) {
400 return readData(block, 0, 512, dst);
401 }
402 //------------------------------------------------------------------------------
403 /**
404 * Read part of a 512 byte block from an SD card.
405 *
406 * \param[in] block Logical block to be read.
407 * \param[in] offset Number of bytes to skip at start of block
408 * \param[out] dst Pointer to the location that will receive the data.
409 * \param[in] count Number of bytes to read
410 * \return The value one, true, is returned for success and
411 * the value zero, false, is returned for failure.
412 */
413 uint8_t Sd2Card::readData(uint32_t block,
414 uint16_t offset, uint16_t count, uint8_t* dst) {
415 uint16_t n;
416 if (count == 0) return true;
417 if ((count + offset) > 512) {
418 goto fail;
419 }
420 if (!inBlock_ || block != block_ || offset < offset_) {
421 block_ = block;
422 // use address if not SDHC card
423 if (type()!= SD_CARD_TYPE_SDHC) block <<= 9;
424 if (cardCommand(CMD17, block)) {
425 error(SD_CARD_ERROR_CMD17);
426 goto fail;
427 }
428 if (!waitStartBlock()) {
429 goto fail;
430 }
431 offset_ = 0;
432 inBlock_ = 1;
433 }
434
435 #ifdef OPTIMIZE_HARDWARE_SPI
436 // start first spi transfer
437 SPDR = 0XFF;
438
439 // skip data before offset
440 for (;offset_ < offset; offset_++) {
441 while (!(SPSR & (1 << SPIF)));
442 SPDR = 0XFF;
443 }
444 // transfer data
445 n = count - 1;
446 for (uint16_t i = 0; i < n; i++) {
447 while (!(SPSR & (1 << SPIF)));
448 dst[i] = SPDR;
449 SPDR = 0XFF;
450 }
451 // wait for last byte
452 while (!(SPSR & (1 << SPIF)));
453 dst[n] = SPDR;
454
455 #else // OPTIMIZE_HARDWARE_SPI
456
457 // skip data before offset
458 for (;offset_ < offset; offset_++) {
459 spiRec();
460 }
461 // transfer data
462 for (uint16_t i = 0; i < count; i++) {
463 dst[i] = spiRec();
464 }
465 #endif // OPTIMIZE_HARDWARE_SPI
466
467 offset_ += count;
468 if (!partialBlockRead_ || offset_ >= 512) {
469 // read rest of data, checksum and set chip select high
470 readEnd();
471 }
472 return true;
473
474 fail:
475 chipSelectHigh();
476 return false;
477 }
478 //------------------------------------------------------------------------------
479 /** Skip remaining data in a block when in partial block read mode. */
480 void Sd2Card::readEnd(void) {
481 if (inBlock_) {
482 // skip data and crc
483 #ifdef OPTIMIZE_HARDWARE_SPI
484 // optimize skip for hardware
485 SPDR = 0XFF;
486 while (offset_++ < 513) {
487 while (!(SPSR & (1 << SPIF)));
488 SPDR = 0XFF;
489 }
bd7b667 Paint Your Dragon CRC16 calc for Eye-Fi X2 cards
PaintYourDragon authored
490 // Wait for last CRC byte
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
491 while (!(SPSR & (1 << SPIF)));
492 #else // OPTIMIZE_HARDWARE_SPI
493 while (offset_++ < 514) spiRec();
494 #endif // OPTIMIZE_HARDWARE_SPI
495 chipSelectHigh();
496 inBlock_ = 0;
497 }
498 }
499 //------------------------------------------------------------------------------
500 /** read CID or CSR register */
501 uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) {
502 uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
503 if (cardCommand(cmd, 0)) {
504 error(SD_CARD_ERROR_READ_REG);
505 goto fail;
506 }
507 if (!waitStartBlock()) goto fail;
508 // transfer data
509 for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec();
510 spiRec(); // get first crc byte
511 spiRec(); // get second crc byte
512 chipSelectHigh();
513 return true;
514
515 fail:
516 chipSelectHigh();
517 return false;
518 }
519 //------------------------------------------------------------------------------
520 /**
521 * Set the SPI clock rate.
522 *
523 * \param[in] sckRateID A value in the range [0, 6].
524 *
525 * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum
526 * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128
527 * for \a scsRateID = 6.
528 *
529 * \return The value one, true, is returned for success and the value zero,
530 * false, is returned for an invalid value of \a sckRateID.
531 */
532 uint8_t Sd2Card::setSckRate(uint8_t sckRateID) {
533 if (sckRateID > 6) {
534 error(SD_CARD_ERROR_SCK_RATE);
535 return false;
536 }
537 // see avr processor datasheet for SPI register bit definitions
538 if ((sckRateID & 1) || sckRateID == 6) {
539 SPSR &= ~(1 << SPI2X);
540 } else {
541 SPSR |= (1 << SPI2X);
542 }
543 SPCR &= ~((1 <<SPR1) | (1 << SPR0));
544 SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0)
545 | (sckRateID & 2 ? (1 << SPR0) : 0);
546 return true;
547 }
548 //------------------------------------------------------------------------------
549 // wait for card to go not busy
550 uint8_t Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
551 uint16_t t0 = millis();
552 do {
553 if (spiRec() == 0XFF) return true;
554 }
555 while (((uint16_t)millis() - t0) < timeoutMillis);
556 return false;
557 }
558 //------------------------------------------------------------------------------
559 /** Wait for start block token */
560 uint8_t Sd2Card::waitStartBlock(void) {
561 uint16_t t0 = millis();
562 while ((status_ = spiRec()) == 0XFF) {
563 if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
564 error(SD_CARD_ERROR_READ_TIMEOUT);
565 goto fail;
566 }
567 }
568 if (status_ != DATA_START_BLOCK) {
569 error(SD_CARD_ERROR_READ);
570 goto fail;
571 }
572 return true;
573
574 fail:
575 chipSelectHigh();
576 return false;
577 }
578 //------------------------------------------------------------------------------
579 /**
580 * Writes a 512 byte block to an SD card.
581 *
582 * \param[in] blockNumber Logical block to be written.
583 * \param[in] src Pointer to the location of the data to be written.
584 * \return The value one, true, is returned for success and
585 * the value zero, false, is returned for failure.
586 */
587 uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
588 #if SD_PROTECT_BLOCK_ZERO
589 // don't allow write to first block
590 if (blockNumber == 0) {
591 error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
592 goto fail;
593 }
594 #endif // SD_PROTECT_BLOCK_ZERO
595
596 // use address if not SDHC card
597 if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
598 if (cardCommand(CMD24, blockNumber)) {
599 error(SD_CARD_ERROR_CMD24);
600 goto fail;
601 }
602 if (!writeData(DATA_START_BLOCK, src)) goto fail;
603
604 // wait for flash programming to complete
605 if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
606 error(SD_CARD_ERROR_WRITE_TIMEOUT);
607 goto fail;
608 }
609 // response is r2 so get and check two bytes for nonzero
610 if (cardCommand(CMD13, 0) || spiRec()) {
611 error(SD_CARD_ERROR_WRITE_PROGRAMMING);
612 goto fail;
613 }
614 chipSelectHigh();
615 return true;
616
617 fail:
618 chipSelectHigh();
619 return false;
620 }
621 //------------------------------------------------------------------------------
622 /** Write one data block in a multiple block write sequence */
623 uint8_t Sd2Card::writeData(const uint8_t* src) {
624 // wait for previous write to finish
625 if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
626 error(SD_CARD_ERROR_WRITE_MULTIPLE);
627 chipSelectHigh();
628 return false;
629 }
630 return writeData(WRITE_MULTIPLE_TOKEN, src);
631 }
632 //------------------------------------------------------------------------------
633 // send one block of data for write block or write multiple blocks
634 uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {
bd7b667 Paint Your Dragon CRC16 calc for Eye-Fi X2 cards
PaintYourDragon authored
635
636 // CRC16 checksum is supposed to be ignored in SPI mode (unless
637 // explicitly enabled) and a dummy value is normally written.
638 // A few funny cards (e.g. Eye-Fi X2) expect a valid CRC anyway.
639 // Call setCRC(true) to enable CRC16 checksum on block writes.
640 // This has a noticeable impact on write speed. :(
641 int16_t crc;
642 if(writeCRC_) {
643 int16_t i, x;
644 // CRC16 code via Scott Dattalo www.dattalo.com
645 for(crc=i=0; i<512; i++) {
646 x = ((crc >> 8) ^ src[i]) & 0xff;
647 x ^= x >> 4;
648 crc = (crc << 8) ^ (x << 12) ^ (x << 5) ^ x;
649 }
650 } else {
651 crc = 0xffff; // Dummy CRC value
652 }
653
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
654 #ifdef OPTIMIZE_HARDWARE_SPI
655
656 // send data - optimized loop
657 SPDR = token;
658
659 // send two byte per iteration
660 for (uint16_t i = 0; i < 512; i += 2) {
661 while (!(SPSR & (1 << SPIF)));
662 SPDR = src[i];
663 while (!(SPSR & (1 << SPIF)));
664 SPDR = src[i+1];
665 }
666
667 // wait for last data byte
668 while (!(SPSR & (1 << SPIF)));
669
670 #else // OPTIMIZE_HARDWARE_SPI
671 spiSend(token);
672 for (uint16_t i = 0; i < 512; i++) {
673 spiSend(src[i]);
674 }
675 #endif // OPTIMIZE_HARDWARE_SPI
bd7b667 Paint Your Dragon CRC16 calc for Eye-Fi X2 cards
PaintYourDragon authored
676
677 spiSend(crc >> 8); // Might be dummy value, that's OK
678 spiSend(crc);
b707f7a Limor "Ladyada" Fried added seek() and buffered read()
ladyada authored
679
680 status_ = spiRec();
681 if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
682 error(SD_CARD_ERROR_WRITE);
683 chipSelectHigh();
684 return false;
685 }
686 return true;
687 }
688 //------------------------------------------------------------------------------
689 /** Start a write multiple blocks sequence.
690 *
691 * \param[in] blockNumber Address of first block in sequence.
692 * \param[in] eraseCount The number of blocks to be pre-erased.
693 *
694 * \note This function is used with writeData() and writeStop()
695 * for optimized multiple block writes.
696 *
697 * \return The value one, true, is returned for success and
698 * the value zero, false, is returned for failure.
699 */
700 uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
701 #if SD_PROTECT_BLOCK_ZERO
702 // don't allow write to first block
703 if (blockNumber == 0) {
704 error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
705 goto fail;
706 }
707 #endif // SD_PROTECT_BLOCK_ZERO
708 // send pre-erase count
709 if (cardAcmd(ACMD23, eraseCount)) {
710 error(SD_CARD_ERROR_ACMD23);
711 goto fail;
712 }
713 // use address if not SDHC card
714 if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
715 if (cardCommand(CMD25, blockNumber)) {
716 error(SD_CARD_ERROR_CMD25);
717 goto fail;
718 }
719 return true;
720
721 fail:
722 chipSelectHigh();
723 return false;
724 }
725 //------------------------------------------------------------------------------
726 /** End a write multiple blocks sequence.
727 *
728 * \return The value one, true, is returned for success and
729 * the value zero, false, is returned for failure.
730 */
731 uint8_t Sd2Card::writeStop(void) {
732 if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
733 spiSend(STOP_TRAN_TOKEN);
734 if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
735 chipSelectHigh();
736 return true;
737
738 fail:
739 error(SD_CARD_ERROR_STOP_TRAN);
740 chipSelectHigh();
741 return false;
742 }
bd7b667 Paint Your Dragon CRC16 calc for Eye-Fi X2 cards
PaintYourDragon authored
743
744 void Sd2Card::enableCRC(uint8_t mode) {
745 writeCRC_ = mode;
746 }
747
Something went wrong with that request. Please try again.