|
- /* Optimized SD Library for Teensy 3.X
- * Copyright (c) 2015, Paul Stoffregen, paul@pjrc.com
- *
- * Development of this SD library was funded by PJRC.COM, LLC by sales of
- * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
- * open source software by purchasing genuine Teensy or other PJRC products.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice, development funding notice, and this permission
- * notice shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
- #if defined(__arm__)
- #include "SD_t3.h"
- #ifdef USE_TEENSY3_OPTIMIZED_CODE
-
- volatile uint8_t * SDClass::csreg;
- uint8_t SDClass::csmask;
- uint8_t SDClass::card_type;
-
-
- #define CMD0_GO_IDLE_STATE 0x4095 // arg=0
- #define CMD1_SEND_OP_COND 0x41FF
- #define CMD8_SEND_IF_COND 0x4887 // arg=0x1AA
- #define CMD55_APP_CMD 0x77FF
- #define ACMD41_SD_SEND_OP_COND 0x69FF
- #define CMD58_READ_OCR 0x7AFF
- #define CMD17_READ_SINGLE_BLOCK 0x51FF
- #define CMD24_WRITE_BLOCK 0x58FF
-
-
- uint8_t SDClass::sd_cmd0()
- {
- send_cmd(CMD0_GO_IDLE_STATE, 0);
- uint8_t r1 = recv_r1();
- end_cmd();
- return r1;
- }
-
- uint32_t SDClass::sd_cmd8()
- {
- send_cmd(CMD8_SEND_IF_COND, 0x1AA);
- uint8_t r1 = recv_r1();
- uint32_t cond = 0x80000000;
- if (r1 == 1) {
- cond = recv_r3_or_r7();
- //Serial.print(cond, HEX);
- }
- end_cmd();
- return cond;
- }
-
- uint8_t SDClass::sd_acmd41(uint32_t hcs)
- {
- //Serial.print("acmd41:");
- send_cmd(CMD55_APP_CMD, 0);
- uint8_t r1 = recv_r1();
- end_cmd();
- send_cmd(ACMD41_SD_SEND_OP_COND, hcs);
- r1 = recv_r1();
- end_cmd();
- return r1;
- }
-
- uint32_t SDClass::sd_cmd58(void)
- {
- send_cmd(CMD58_READ_OCR, 0);
- uint8_t r1 = recv_r1();
- uint32_t ocr = 0;
- if (r1 == 0) ocr = recv_r3_or_r7();
- end_cmd();
- return ocr;
- }
-
- bool SDClass::sd_read(uint32_t addr, void * data)
- {
- //Serial.printf("sd_read %ld\n", addr);
- if (card_type < 2) addr = addr << 9;
- send_cmd(CMD17_READ_SINGLE_BLOCK, addr);
- uint8_t r1 = recv_r1();
- if (r1 != 0) {
- end_cmd();
- //Serial.println(" sd_read fail r1");
- return false;
- }
- while (1) {
- uint8_t token = SPI.transfer(0xFF);
- //Serial.printf("t=%02X.", token);
- if (token == 0xFE) break;
- if (token != 0xFF) {
- end_cmd();
- //Serial.println(" sd_read fail token");
- return false;
- }
- // TODO: timeout
- }
- uint8_t *p = (uint8_t *)data;
- uint8_t *end = p + 510;
- SPI0_PUSHR = 0xFFFF | SPI_PUSHR_CTAS(1);
- SPI0_PUSHR = 0xFFFF | SPI_PUSHR_CTAS(1);
- while (p < end) {
- while (!(SPI0_SR & 0xF0)) ;
- SPI0_PUSHR = 0xFFFF | SPI_PUSHR_CTAS(1);
- uint32_t in = SPI0_POPR;
- *p++ = in >> 8;
- *p++ = in;
- }
- while (!(SPI0_SR & 0xF0)) ;
- uint32_t in = SPI0_POPR;
- *p++ = in >> 8;
- *p++ = in;
- while (!(SPI0_SR & 0xF0)) ;
- SPI0_POPR; // ignore crc
- DIRECT_WRITE_HIGH(csreg, csmask);
- SPI.transfer(0xFF);
- return true;
- // token = 0xFE
- // data, 512 bytes
- // crc, 2 bytes
- }
-
-
- void SDClass::send_cmd(uint16_t cmd, uint32_t arg)
- {
- DIRECT_WRITE_LOW(csreg, csmask);
- SPI.transfer(cmd >> 8);
- SPI.transfer16(arg >> 16);
- SPI.transfer16(arg);
- SPI.transfer(cmd);
- }
-
- uint8_t SDClass::recv_r1(void)
- {
- uint8_t ret, count=0;
- do {
- ret = SPI.transfer(0xFF);
- //Serial.print(ret);
- //Serial.print(".");
- if ((ret & 0x80) == 0) break;
- } while (++count < 9);
- return ret;
- }
-
- uint32_t SDClass::recv_r3_or_r7(void)
- {
- uint32_t r;
- r = SPI.transfer16(0xFFFF) << 16;
- r |= SPI.transfer16(0xFFFF);
- return r;
- }
-
- void SDClass::end_cmd(void)
- {
- DIRECT_WRITE_HIGH(csreg, csmask);
- SPI.transfer(0xFF);
- }
-
- #endif
- #endif
|