[136] | 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
|
---|
| 28 | static SPISettings settings;
|
---|
| 29 | #endif
|
---|
| 30 | #endif
|
---|
| 31 | // functions for hardware SPI
|
---|
| 32 | /** Send a byte to the card */
|
---|
| 33 | static 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 */
|
---|
| 43 | static 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 */
|
---|
| 57 | uint8_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 */
|
---|
| 83 | void 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
|
---|
| 108 | uint8_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 | */
|
---|
| 142 | uint32_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 | //------------------------------------------------------------------------------
|
---|
| 162 | static uint8_t chip_select_asserted = 0;
|
---|
| 163 |
|
---|
| 164 | void 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 | //------------------------------------------------------------------------------
|
---|
| 176 | void 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 | */
|
---|
| 201 | uint8_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 | */
|
---|
| 233 | uint8_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 | */
|
---|
| 248 | uint8_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 | */
|
---|
| 362 | void 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 | */
|
---|
| 376 | uint8_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 | */
|
---|
| 390 | uint8_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. */
|
---|
| 460 | void 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 */
|
---|
| 483 | uint8_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 | */
|
---|
| 514 | uint8_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
|
---|
| 546 | uint8_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 */
|
---|
| 556 | uint8_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 | */
|
---|
| 583 | uint8_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 */
|
---|
| 619 | uint8_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
|
---|
| 630 | uint8_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 | */
|
---|
| 679 | uint8_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 | */
|
---|
| 710 | uint8_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 | }
|
---|