source: rtos_arduino/trunk/arduino_lib/libraries/SD/src/utility/Sd2Card.cpp@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

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