00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <WProgram.h>
00021 #include "Sd2Card.h"
00022
00023 #ifndef SOFTWARE_SPI
00024
00026 static void spiSend(uint8_t b) {
00027 SPDR = b;
00028 while (!(SPSR & (1 << SPIF)));
00029 }
00031 static uint8_t spiRec(void) {
00032 spiSend(0XFF);
00033 return SPDR;
00034 }
00035 #else // SOFTWARE_SPI
00036
00038 #define nop asm volatile ("nop\n\t")
00039
00041 uint8_t spiRec(void) {
00042 uint8_t data = 0;
00043
00044 cli();
00045
00046 fastDigitalWrite(SPI_MOSI_PIN, HIGH);
00047
00048 for (uint8_t i = 0; i < 8; i++) {
00049 fastDigitalWrite(SPI_SCK_PIN, HIGH);
00050
00051
00052 nop;
00053 nop;
00054
00055 data <<= 1;
00056
00057 if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;
00058
00059 fastDigitalWrite(SPI_SCK_PIN, LOW);
00060 }
00061
00062 sei();
00063 return data;
00064 }
00065
00067 void spiSend(uint8_t data) {
00068
00069 cli();
00070 for (uint8_t i = 0; i < 8; i++) {
00071 fastDigitalWrite(SPI_SCK_PIN, LOW);
00072
00073 fastDigitalWrite(SPI_MOSI_PIN, data & 0X80);
00074
00075 data <<= 1;
00076
00077 fastDigitalWrite(SPI_SCK_PIN, HIGH);
00078 }
00079
00080 nop;
00081 nop;
00082 nop;
00083 nop;
00084
00085 fastDigitalWrite(SPI_SCK_PIN, LOW);
00086
00087 sei();
00088 }
00089 #endif // SOFTWARE_SPI
00090
00091
00092 uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
00093
00094 readEnd();
00095
00096
00097 chipSelectLow();
00098
00099
00100 waitNotBusy(300);
00101
00102
00103 spiSend(cmd | 0x40);
00104
00105
00106 for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
00107
00108
00109 uint8_t crc = 0XFF;
00110 if (cmd == CMD0) crc = 0X95;
00111 if (cmd == CMD8) crc = 0X87;
00112 spiSend(crc);
00113
00114
00115 for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++);
00116 return status_;
00117 }
00118
00125 uint32_t Sd2Card::cardSize(void) {
00126 csd_t csd;
00127 if (!readCSD(&csd)) return 0;
00128 if (csd.v1.csd_ver == 0) {
00129 uint8_t read_bl_len = csd.v1.read_bl_len;
00130 uint16_t c_size = (csd.v1.c_size_high << 10)
00131 | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low;
00132 uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1)
00133 | csd.v1.c_size_mult_low;
00134 return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
00135 } else if (csd.v2.csd_ver == 1) {
00136 uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16)
00137 | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low;
00138 return (c_size + 1) << 10;
00139 } else {
00140 error(SD_CARD_ERROR_BAD_CSD);
00141 return 0;
00142 }
00143 }
00144
00145 void Sd2Card::chipSelectHigh(void) {
00146 digitalWrite(chipSelectPin_, HIGH);
00147 }
00148
00149 void Sd2Card::chipSelectLow(void) {
00150 digitalWrite(chipSelectPin_, LOW);
00151 }
00152
00166 uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
00167 if (!eraseSingleBlockEnable()) {
00168 error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
00169 goto fail;
00170 }
00171 if (type_ != SD_CARD_TYPE_SDHC) {
00172 firstBlock <<= 9;
00173 lastBlock <<= 9;
00174 }
00175 if (cardCommand(CMD32, firstBlock)
00176 || cardCommand(CMD33, lastBlock)
00177 || cardCommand(CMD38, 0)) {
00178 error(SD_CARD_ERROR_ERASE);
00179 goto fail;
00180 }
00181 if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
00182 error(SD_CARD_ERROR_ERASE_TIMEOUT);
00183 goto fail;
00184 }
00185 chipSelectHigh();
00186 return true;
00187
00188 fail:
00189 chipSelectHigh();
00190 return false;
00191 }
00192
00198 uint8_t Sd2Card::eraseSingleBlockEnable(void) {
00199 csd_t csd;
00200 return readCSD(&csd) ? csd.v1.erase_blk_en : 0;
00201 }
00202
00213 uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
00214 errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
00215 chipSelectPin_ = chipSelectPin;
00216
00217 uint16_t t0 = (uint16_t)millis();
00218 uint32_t arg;
00219
00220
00221 pinMode(chipSelectPin_, OUTPUT);
00222 chipSelectHigh();
00223 pinMode(SPI_MISO_PIN, INPUT);
00224 pinMode(SPI_MOSI_PIN, OUTPUT);
00225 pinMode(SPI_SCK_PIN, OUTPUT);
00226
00227 #ifndef SOFTWARE_SPI
00228
00229 pinMode(SS_PIN, OUTPUT);
00230 digitalWrite(SS_PIN, HIGH);
00231
00232 SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
00233
00234 SPSR &= ~(1 << SPI2X);
00235 #endif // SOFTWARE_SPI
00236
00237
00238 for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
00239
00240 chipSelectLow();
00241
00242
00243 while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
00244 if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
00245 error(SD_CARD_ERROR_CMD0);
00246 goto fail;
00247 }
00248 }
00249
00250 if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
00251 type(SD_CARD_TYPE_SD1);
00252 } else {
00253
00254 for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
00255 if (status_ != 0XAA) {
00256 error(SD_CARD_ERROR_CMD8);
00257 goto fail;
00258 }
00259 type(SD_CARD_TYPE_SD2);
00260 }
00261
00262 arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
00263
00264 while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
00265
00266 if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
00267 error(SD_CARD_ERROR_ACMD41);
00268 goto fail;
00269 }
00270 }
00271
00272 if (type() == SD_CARD_TYPE_SD2) {
00273 if (cardCommand(CMD58, 0)) {
00274 error(SD_CARD_ERROR_CMD58);
00275 goto fail;
00276 }
00277 if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
00278
00279 for (uint8_t i = 0; i < 3; i++) spiRec();
00280 }
00281 chipSelectHigh();
00282
00283 #ifndef SOFTWARE_SPI
00284 return setSckRate(sckRateID);
00285 #else // SOFTWARE_SPI
00286 return true;
00287 #endif // SOFTWARE_SPI
00288
00289 fail:
00290 chipSelectHigh();
00291 return false;
00292 }
00293
00307 void Sd2Card::partialBlockRead(uint8_t value) {
00308 readEnd();
00309 partialBlockRead_ = value;
00310 }
00311
00321 uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) {
00322 return readData(block, 0, 512, dst);
00323 }
00324
00335 uint8_t Sd2Card::readData(uint32_t block,
00336 uint16_t offset, uint16_t count, uint8_t* dst) {
00337 uint16_t n;
00338 if (count == 0) return true;
00339 if ((count + offset) > 512) {
00340 goto fail;
00341 }
00342 if (!inBlock_ || block != block_ || offset < offset_) {
00343 block_ = block;
00344
00345 if (type()!= SD_CARD_TYPE_SDHC) block <<= 9;
00346 if (cardCommand(CMD17, block)) {
00347 error(SD_CARD_ERROR_CMD17);
00348 goto fail;
00349 }
00350 if (!waitStartBlock()) {
00351 goto fail;
00352 }
00353 offset_ = 0;
00354 inBlock_ = 1;
00355 }
00356
00357 #ifdef OPTIMIZE_HARDWARE_SPI
00358
00359 SPDR = 0XFF;
00360
00361
00362 for (;offset_ < offset; offset_++) {
00363 while (!(SPSR & (1 << SPIF)));
00364 SPDR = 0XFF;
00365 }
00366
00367 n = count - 1;
00368 for (uint16_t i = 0; i < n; i++) {
00369 while (!(SPSR & (1 << SPIF)));
00370 dst[i] = SPDR;
00371 SPDR = 0XFF;
00372 }
00373
00374 while (!(SPSR & (1 << SPIF)));
00375 dst[n] = SPDR;
00376
00377 #else // OPTIMIZE_HARDWARE_SPI
00378
00379
00380 for (;offset_ < offset; offset_++) {
00381 spiRec();
00382 }
00383
00384 for (uint16_t i = 0; i < count; i++) {
00385 dst[i] = spiRec();
00386 }
00387 #endif // OPTIMIZE_HARDWARE_SPI
00388
00389 offset_ += count;
00390 if (!partialBlockRead_ || offset_ >= 512) {
00391
00392 readEnd();
00393 }
00394 return true;
00395
00396 fail:
00397 chipSelectHigh();
00398 return false;
00399 }
00400
00402 void Sd2Card::readEnd(void) {
00403 if (inBlock_) {
00404
00405 #ifdef OPTIMIZE_HARDWARE_SPI
00406
00407 SPDR = 0XFF;
00408 while (offset_++ < 513) {
00409 while (!(SPSR & (1 << SPIF)));
00410 SPDR = 0XFF;
00411 }
00412
00413 while (!(SPSR & (1 << SPIF)));
00414 #else // OPTIMIZE_HARDWARE_SPI
00415 while (offset_++ < 514) spiRec();
00416 #endif // OPTIMIZE_HARDWARE_SPI
00417 chipSelectHigh();
00418 inBlock_ = 0;
00419 }
00420 }
00421
00423 uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) {
00424 uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
00425 if (cardCommand(cmd, 0)) {
00426 error(SD_CARD_ERROR_READ_REG);
00427 goto fail;
00428 }
00429 if (!waitStartBlock()) goto fail;
00430
00431 for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec();
00432 spiRec();
00433 spiRec();
00434 chipSelectHigh();
00435 return true;
00436
00437 fail:
00438 chipSelectHigh();
00439 return false;
00440 }
00441
00454 uint8_t Sd2Card::setSckRate(uint8_t sckRateID) {
00455 if (sckRateID > 6) {
00456 error(SD_CARD_ERROR_SCK_RATE);
00457 return false;
00458 }
00459
00460 if ((sckRateID & 1) || sckRateID == 6) {
00461 SPSR &= ~(1 << SPI2X);
00462 } else {
00463 SPSR |= (1 << SPI2X);
00464 }
00465 SPCR &= ~((1 <<SPR1) | (1 << SPR0));
00466 SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0)
00467 | (sckRateID & 2 ? (1 << SPR0) : 0);
00468 return true;
00469 }
00470
00471
00472 uint8_t Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
00473 uint16_t t0 = millis();
00474 do {
00475 if (spiRec() == 0XFF) return true;
00476 }
00477 while (((uint16_t)millis() - t0) < timeoutMillis);
00478 return false;
00479 }
00480
00482 uint8_t Sd2Card::waitStartBlock(void) {
00483 uint16_t t0 = millis();
00484 while ((status_ = spiRec()) == 0XFF) {
00485 if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
00486 error(SD_CARD_ERROR_READ_TIMEOUT);
00487 goto fail;
00488 }
00489 }
00490 if (status_ != DATA_START_BLOCK) {
00491 error(SD_CARD_ERROR_READ);
00492 goto fail;
00493 }
00494 return true;
00495
00496 fail:
00497 chipSelectHigh();
00498 return false;
00499 }
00500
00509 uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
00510 #if SD_PROTECT_BLOCK_ZERO
00511
00512 if (blockNumber == 0) {
00513 error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
00514 goto fail;
00515 }
00516 #endif // SD_PROTECT_BLOCK_ZERO
00517
00518
00519 if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
00520 if (cardCommand(CMD24, blockNumber)) {
00521 error(SD_CARD_ERROR_CMD24);
00522 goto fail;
00523 }
00524 if (!writeData(DATA_START_BLOCK, src)) goto fail;
00525
00526
00527 if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
00528 error(SD_CARD_ERROR_WRITE_TIMEOUT);
00529 goto fail;
00530 }
00531
00532 if (cardCommand(CMD13, 0) || spiRec()) {
00533 error(SD_CARD_ERROR_WRITE_PROGRAMMING);
00534 goto fail;
00535 }
00536 chipSelectHigh();
00537 return true;
00538
00539 fail:
00540 chipSelectHigh();
00541 return false;
00542 }
00543
00545 uint8_t Sd2Card::writeData(const uint8_t* src) {
00546
00547 if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
00548 error(SD_CARD_ERROR_WRITE_MULTIPLE);
00549 chipSelectHigh();
00550 return false;
00551 }
00552 return writeData(WRITE_MULTIPLE_TOKEN, src);
00553 }
00554
00555
00556 uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {
00557 #ifdef OPTIMIZE_HARDWARE_SPI
00558
00559
00560 SPDR = token;
00561
00562
00563 for (uint16_t i = 0; i < 512; i += 2) {
00564 while (!(SPSR & (1 << SPIF)));
00565 SPDR = src[i];
00566 while (!(SPSR & (1 << SPIF)));
00567 SPDR = src[i+1];
00568 }
00569
00570
00571 while (!(SPSR & (1 << SPIF)));
00572
00573 #else // OPTIMIZE_HARDWARE_SPI
00574 spiSend(token);
00575 for (uint16_t i = 0; i < 512; i++) {
00576 spiSend(src[i]);
00577 }
00578 #endif // OPTIMIZE_HARDWARE_SPI
00579 spiSend(0xff);
00580 spiSend(0xff);
00581
00582 status_ = spiRec();
00583 if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
00584 error(SD_CARD_ERROR_WRITE);
00585 chipSelectHigh();
00586 return false;
00587 }
00588 return true;
00589 }
00590
00602 uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
00603 #if SD_PROTECT_BLOCK_ZERO
00604
00605 if (blockNumber == 0) {
00606 error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
00607 goto fail;
00608 }
00609 #endif // SD_PROTECT_BLOCK_ZERO
00610
00611 if (cardAcmd(ACMD23, eraseCount)) {
00612 error(SD_CARD_ERROR_ACMD23);
00613 goto fail;
00614 }
00615
00616 if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
00617 if (cardCommand(CMD25, blockNumber)) {
00618 error(SD_CARD_ERROR_CMD25);
00619 goto fail;
00620 }
00621 return true;
00622
00623 fail:
00624 chipSelectHigh();
00625 return false;
00626 }
00627
00633 uint8_t Sd2Card::writeStop(void) {
00634 if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
00635 spiSend(STOP_TRAN_TOKEN);
00636 if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
00637 chipSelectHigh();
00638 return true;
00639
00640 fail:
00641 error(SD_CARD_ERROR_STOP_TRAN);
00642 chipSelectHigh();
00643 return false;
00644 }