hw

Dependencies:   FATFileSystem

Dependents:   wave_player_mp3

Fork of SDFileSystem by mbed official

Committer:
zchen311
Date:
Sun Jul 14 20:29:53 2013 +0000
Revision:
4:0046f1b576ec
done

Who changed what in which revision?

UserRevisionLine numberNew contents of line
zchen311 4:0046f1b576ec 1 /* mbed Microcontroller Library
zchen311 4:0046f1b576ec 2 * Copyright (c) 2006-2012 ARM Limited
zchen311 4:0046f1b576ec 3 *
zchen311 4:0046f1b576ec 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
zchen311 4:0046f1b576ec 5 * of this software and associated documentation files (the "Software"), to deal
zchen311 4:0046f1b576ec 6 * in the Software without restriction, including without limitation the rights
zchen311 4:0046f1b576ec 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
zchen311 4:0046f1b576ec 8 * copies of the Software, and to permit persons to whom the Software is
zchen311 4:0046f1b576ec 9 * furnished to do so, subject to the following conditions:
zchen311 4:0046f1b576ec 10 *
zchen311 4:0046f1b576ec 11 * The above copyright notice and this permission notice shall be included in
zchen311 4:0046f1b576ec 12 * all copies or substantial portions of the Software.
zchen311 4:0046f1b576ec 13 *
zchen311 4:0046f1b576ec 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
zchen311 4:0046f1b576ec 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
zchen311 4:0046f1b576ec 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
zchen311 4:0046f1b576ec 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
zchen311 4:0046f1b576ec 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
zchen311 4:0046f1b576ec 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
zchen311 4:0046f1b576ec 20 * SOFTWARE.
zchen311 4:0046f1b576ec 21 */
zchen311 4:0046f1b576ec 22 /* Introduction
zchen311 4:0046f1b576ec 23 * ------------
zchen311 4:0046f1b576ec 24 * SD and MMC cards support a number of interfaces, but common to them all
zchen311 4:0046f1b576ec 25 * is one based on SPI. This is the one I'm implmenting because it means
zchen311 4:0046f1b576ec 26 * it is much more portable even though not so performant, and we already
zchen311 4:0046f1b576ec 27 * have the mbed SPI Interface!
zchen311 4:0046f1b576ec 28 *
zchen311 4:0046f1b576ec 29 * The main reference I'm using is Chapter 7, "SPI Mode" of:
zchen311 4:0046f1b576ec 30 * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
zchen311 4:0046f1b576ec 31 *
zchen311 4:0046f1b576ec 32 * SPI Startup
zchen311 4:0046f1b576ec 33 * -----------
zchen311 4:0046f1b576ec 34 * The SD card powers up in SD mode. The SPI interface mode is selected by
zchen311 4:0046f1b576ec 35 * asserting CS low and sending the reset command (CMD0). The card will
zchen311 4:0046f1b576ec 36 * respond with a (R1) response.
zchen311 4:0046f1b576ec 37 *
zchen311 4:0046f1b576ec 38 * CMD8 is optionally sent to determine the voltage range supported, and
zchen311 4:0046f1b576ec 39 * indirectly determine whether it is a version 1.x SD/non-SD card or
zchen311 4:0046f1b576ec 40 * version 2.x. I'll just ignore this for now.
zchen311 4:0046f1b576ec 41 *
zchen311 4:0046f1b576ec 42 * ACMD41 is repeatedly issued to initialise the card, until "in idle"
zchen311 4:0046f1b576ec 43 * (bit 0) of the R1 response goes to '0', indicating it is initialised.
zchen311 4:0046f1b576ec 44 *
zchen311 4:0046f1b576ec 45 * You should also indicate whether the host supports High Capicity cards,
zchen311 4:0046f1b576ec 46 * and check whether the card is high capacity - i'll also ignore this
zchen311 4:0046f1b576ec 47 *
zchen311 4:0046f1b576ec 48 * SPI Protocol
zchen311 4:0046f1b576ec 49 * ------------
zchen311 4:0046f1b576ec 50 * The SD SPI protocol is based on transactions made up of 8-bit words, with
zchen311 4:0046f1b576ec 51 * the host starting every bus transaction by asserting the CS signal low. The
zchen311 4:0046f1b576ec 52 * card always responds to commands, data blocks and errors.
zchen311 4:0046f1b576ec 53 *
zchen311 4:0046f1b576ec 54 * The protocol supports a CRC, but by default it is off (except for the
zchen311 4:0046f1b576ec 55 * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
zchen311 4:0046f1b576ec 56 * I'll leave the CRC off I think!
zchen311 4:0046f1b576ec 57 *
zchen311 4:0046f1b576ec 58 * Standard capacity cards have variable data block sizes, whereas High
zchen311 4:0046f1b576ec 59 * Capacity cards fix the size of data block to 512 bytes. I'll therefore
zchen311 4:0046f1b576ec 60 * just always use the Standard Capacity cards with a block size of 512 bytes.
zchen311 4:0046f1b576ec 61 * This is set with CMD16.
zchen311 4:0046f1b576ec 62 *
zchen311 4:0046f1b576ec 63 * You can read and write single blocks (CMD17, CMD25) or multiple blocks
zchen311 4:0046f1b576ec 64 * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
zchen311 4:0046f1b576ec 65 * the card gets a read command, it responds with a response token, and then
zchen311 4:0046f1b576ec 66 * a data token or an error.
zchen311 4:0046f1b576ec 67 *
zchen311 4:0046f1b576ec 68 * SPI Command Format
zchen311 4:0046f1b576ec 69 * ------------------
zchen311 4:0046f1b576ec 70 * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
zchen311 4:0046f1b576ec 71 *
zchen311 4:0046f1b576ec 72 * +---------------+------------+------------+-----------+----------+--------------+
zchen311 4:0046f1b576ec 73 * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
zchen311 4:0046f1b576ec 74 * +---------------+------------+------------+-----------+----------+--------------+
zchen311 4:0046f1b576ec 75 *
zchen311 4:0046f1b576ec 76 * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
zchen311 4:0046f1b576ec 77 *
zchen311 4:0046f1b576ec 78 * All Application Specific commands shall be preceded with APP_CMD (CMD55).
zchen311 4:0046f1b576ec 79 *
zchen311 4:0046f1b576ec 80 * SPI Response Format
zchen311 4:0046f1b576ec 81 * -------------------
zchen311 4:0046f1b576ec 82 * The main response format (R1) is a status byte (normally zero). Key flags:
zchen311 4:0046f1b576ec 83 * idle - 1 if the card is in an idle state/initialising
zchen311 4:0046f1b576ec 84 * cmd - 1 if an illegal command code was detected
zchen311 4:0046f1b576ec 85 *
zchen311 4:0046f1b576ec 86 * +-------------------------------------------------+
zchen311 4:0046f1b576ec 87 * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
zchen311 4:0046f1b576ec 88 * +-------------------------------------------------+
zchen311 4:0046f1b576ec 89 *
zchen311 4:0046f1b576ec 90 * R1b is the same, except it is followed by a busy signal (zeros) until
zchen311 4:0046f1b576ec 91 * the first non-zero byte when it is ready again.
zchen311 4:0046f1b576ec 92 *
zchen311 4:0046f1b576ec 93 * Data Response Token
zchen311 4:0046f1b576ec 94 * -------------------
zchen311 4:0046f1b576ec 95 * Every data block written to the card is acknowledged by a byte
zchen311 4:0046f1b576ec 96 * response token
zchen311 4:0046f1b576ec 97 *
zchen311 4:0046f1b576ec 98 * +----------------------+
zchen311 4:0046f1b576ec 99 * | xxx | 0 | status | 1 |
zchen311 4:0046f1b576ec 100 * +----------------------+
zchen311 4:0046f1b576ec 101 * 010 - OK!
zchen311 4:0046f1b576ec 102 * 101 - CRC Error
zchen311 4:0046f1b576ec 103 * 110 - Write Error
zchen311 4:0046f1b576ec 104 *
zchen311 4:0046f1b576ec 105 * Single Block Read and Write
zchen311 4:0046f1b576ec 106 * ---------------------------
zchen311 4:0046f1b576ec 107 *
zchen311 4:0046f1b576ec 108 * Block transfers have a byte header, followed by the data, followed
zchen311 4:0046f1b576ec 109 * by a 16-bit CRC. In our case, the data will always be 512 bytes.
zchen311 4:0046f1b576ec 110 *
zchen311 4:0046f1b576ec 111 * +------+---------+---------+- - - -+---------+-----------+----------+
zchen311 4:0046f1b576ec 112 * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] |
zchen311 4:0046f1b576ec 113 * +------+---------+---------+- - - -+---------+-----------+----------+
zchen311 4:0046f1b576ec 114 */
zchen311 4:0046f1b576ec 115 #include "SDFileSystem.h"
zchen311 4:0046f1b576ec 116 #include "mbed_debug.h"
zchen311 4:0046f1b576ec 117
zchen311 4:0046f1b576ec 118 #define SD_COMMAND_TIMEOUT 5000
zchen311 4:0046f1b576ec 119
zchen311 4:0046f1b576ec 120 #define SD_DBG 0
zchen311 4:0046f1b576ec 121
zchen311 4:0046f1b576ec 122 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs,PinName cd, const char* name) :
zchen311 4:0046f1b576ec 123 FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs),_cd(cd) {
zchen311 4:0046f1b576ec 124 _cs = 1;
zchen311 4:0046f1b576ec 125
zchen311 4:0046f1b576ec 126 }
zchen311 4:0046f1b576ec 127
zchen311 4:0046f1b576ec 128 #define R1_IDLE_STATE (1 << 0)
zchen311 4:0046f1b576ec 129 #define R1_ERASE_RESET (1 << 1)
zchen311 4:0046f1b576ec 130 #define R1_ILLEGAL_COMMAND (1 << 2)
zchen311 4:0046f1b576ec 131 #define R1_COM_CRC_ERROR (1 << 3)
zchen311 4:0046f1b576ec 132 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
zchen311 4:0046f1b576ec 133 #define R1_ADDRESS_ERROR (1 << 5)
zchen311 4:0046f1b576ec 134 #define R1_PARAMETER_ERROR (1 << 6)
zchen311 4:0046f1b576ec 135
zchen311 4:0046f1b576ec 136 // Types
zchen311 4:0046f1b576ec 137 // - v1.x Standard Capacity
zchen311 4:0046f1b576ec 138 // - v2.x Standard Capacity
zchen311 4:0046f1b576ec 139 // - v2.x High Capacity
zchen311 4:0046f1b576ec 140 // - Not recognised as an SD Card
zchen311 4:0046f1b576ec 141 #define SDCARD_FAIL 0
zchen311 4:0046f1b576ec 142 #define SDCARD_V1 1
zchen311 4:0046f1b576ec 143 #define SDCARD_V2 2
zchen311 4:0046f1b576ec 144 #define SDCARD_V2HC 3
zchen311 4:0046f1b576ec 145
zchen311 4:0046f1b576ec 146 int SDFileSystem::initialise_card() {
zchen311 4:0046f1b576ec 147
zchen311 4:0046f1b576ec 148 while(_cmd(0,0) !=R1_IDLE_STATE)
zchen311 4:0046f1b576ec 149 { wait(0.0001);}//I have no idea!!
zchen311 4:0046f1b576ec 150
zchen311 4:0046f1b576ec 151 // Set to 100kHz for initialisation, and clock card with cs = 1
zchen311 4:0046f1b576ec 152 _spi.frequency(100000);
zchen311 4:0046f1b576ec 153 _cs = 1;
zchen311 4:0046f1b576ec 154 for (int i = 0; i < 16; i++) {
zchen311 4:0046f1b576ec 155 _spi.write(0xFF);
zchen311 4:0046f1b576ec 156 }
zchen311 4:0046f1b576ec 157
zchen311 4:0046f1b576ec 158 // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
zchen311 4:0046f1b576ec 159 if (_cmd(0, 0) != R1_IDLE_STATE) {
zchen311 4:0046f1b576ec 160 debug("No disk, or could not put SD card in to SPI idle state\n");
zchen311 4:0046f1b576ec 161 return SDCARD_FAIL;
zchen311 4:0046f1b576ec 162 }
zchen311 4:0046f1b576ec 163
zchen311 4:0046f1b576ec 164 // send CMD8 to determine whther it is ver 2.x
zchen311 4:0046f1b576ec 165 int r = _cmd8();
zchen311 4:0046f1b576ec 166 if (r == R1_IDLE_STATE) {
zchen311 4:0046f1b576ec 167 return initialise_card_v2();
zchen311 4:0046f1b576ec 168 } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
zchen311 4:0046f1b576ec 169 return initialise_card_v1();
zchen311 4:0046f1b576ec 170 } else {
zchen311 4:0046f1b576ec 171 debug("Not in idle state after sending CMD8 (not an SD card?)\n");
zchen311 4:0046f1b576ec 172 return SDCARD_FAIL;
zchen311 4:0046f1b576ec 173 }
zchen311 4:0046f1b576ec 174 }
zchen311 4:0046f1b576ec 175
zchen311 4:0046f1b576ec 176 int SDFileSystem::initialise_card_v1() {
zchen311 4:0046f1b576ec 177 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
zchen311 4:0046f1b576ec 178 _cmd(55, 0);
zchen311 4:0046f1b576ec 179 if (_cmd(41, 0) == 0) {
zchen311 4:0046f1b576ec 180 cdv = 512;
zchen311 4:0046f1b576ec 181 debug_if(SD_DBG, "\n\rInit: SEDCARD_V1\n\r");
zchen311 4:0046f1b576ec 182 return SDCARD_V1;
zchen311 4:0046f1b576ec 183 }
zchen311 4:0046f1b576ec 184 }
zchen311 4:0046f1b576ec 185
zchen311 4:0046f1b576ec 186 debug("Timeout waiting for v1.x card\n");
zchen311 4:0046f1b576ec 187 return SDCARD_FAIL;
zchen311 4:0046f1b576ec 188 }
zchen311 4:0046f1b576ec 189
zchen311 4:0046f1b576ec 190 int SDFileSystem::initialise_card_v2() {
zchen311 4:0046f1b576ec 191 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
zchen311 4:0046f1b576ec 192 wait_ms(50);
zchen311 4:0046f1b576ec 193 _cmd58();
zchen311 4:0046f1b576ec 194 _cmd(55, 0);
zchen311 4:0046f1b576ec 195 if (_cmd(41, 0x40000000) == 0) {
zchen311 4:0046f1b576ec 196 _cmd58();
zchen311 4:0046f1b576ec 197 debug_if(SD_DBG, "\n\rInit: SDCARD_V2\n\r");
zchen311 4:0046f1b576ec 198 cdv = 1;
zchen311 4:0046f1b576ec 199 return SDCARD_V2;
zchen311 4:0046f1b576ec 200 }
zchen311 4:0046f1b576ec 201 }
zchen311 4:0046f1b576ec 202
zchen311 4:0046f1b576ec 203 debug("Timeout waiting for v2.x card\n");
zchen311 4:0046f1b576ec 204 return SDCARD_FAIL;
zchen311 4:0046f1b576ec 205 }
zchen311 4:0046f1b576ec 206
zchen311 4:0046f1b576ec 207 int SDFileSystem::disk_initialize() {
zchen311 4:0046f1b576ec 208 int i = initialise_card();
zchen311 4:0046f1b576ec 209 debug_if(SD_DBG, "init card = %d\n", i);
zchen311 4:0046f1b576ec 210 _sectors = _sd_sectors();
zchen311 4:0046f1b576ec 211
zchen311 4:0046f1b576ec 212 // Set block length to 512 (CMD16)
zchen311 4:0046f1b576ec 213 if (_cmd(16, 512) != 0) {
zchen311 4:0046f1b576ec 214 debug("Set 512-byte block timed out\n");
zchen311 4:0046f1b576ec 215 return 1;
zchen311 4:0046f1b576ec 216 }
zchen311 4:0046f1b576ec 217
zchen311 4:0046f1b576ec 218 _spi.frequency(1000000); // Set to 1MHz for data transfer
zchen311 4:0046f1b576ec 219 return 0;
zchen311 4:0046f1b576ec 220 }
zchen311 4:0046f1b576ec 221
zchen311 4:0046f1b576ec 222 int SDFileSystem::disk_write(const uint8_t *buffer, uint64_t block_number) {
zchen311 4:0046f1b576ec 223 // set write address for single block (CMD24)
zchen311 4:0046f1b576ec 224 if (_cmd(24, block_number * cdv) != 0) {
zchen311 4:0046f1b576ec 225 return 1;
zchen311 4:0046f1b576ec 226 }
zchen311 4:0046f1b576ec 227
zchen311 4:0046f1b576ec 228 // send the data block
zchen311 4:0046f1b576ec 229 _write(buffer, 512);
zchen311 4:0046f1b576ec 230 return 0;
zchen311 4:0046f1b576ec 231 }
zchen311 4:0046f1b576ec 232
zchen311 4:0046f1b576ec 233 int SDFileSystem::disk_read(uint8_t *buffer, uint64_t block_number) {
zchen311 4:0046f1b576ec 234 // set read address for single block (CMD17)
zchen311 4:0046f1b576ec 235 if (_cmd(17, block_number * cdv) != 0) {
zchen311 4:0046f1b576ec 236 return 1;
zchen311 4:0046f1b576ec 237 }
zchen311 4:0046f1b576ec 238
zchen311 4:0046f1b576ec 239 // receive the data
zchen311 4:0046f1b576ec 240 _read(buffer, 512);
zchen311 4:0046f1b576ec 241 return 0;
zchen311 4:0046f1b576ec 242 }
zchen311 4:0046f1b576ec 243 bool SDFileSystem::sd_inserted()
zchen311 4:0046f1b576ec 244 { DigitalIn SDcard_detect(p9);
zchen311 4:0046f1b576ec 245 SDcard_detect.mode(PullUp);
zchen311 4:0046f1b576ec 246 wait(0.1);
zchen311 4:0046f1b576ec 247 if(SDcard_detect==1)
zchen311 4:0046f1b576ec 248 {
zchen311 4:0046f1b576ec 249 return true;// there is sd card
zchen311 4:0046f1b576ec 250 }
zchen311 4:0046f1b576ec 251 else
zchen311 4:0046f1b576ec 252 return false;// ther is no sd card
zchen311 4:0046f1b576ec 253 }
zchen311 4:0046f1b576ec 254 int SDFileSystem::disk_status() { return 0; }
zchen311 4:0046f1b576ec 255 int SDFileSystem::disk_sync() { return 0; }
zchen311 4:0046f1b576ec 256 uint64_t SDFileSystem::disk_sectors() { return _sectors; }
zchen311 4:0046f1b576ec 257
zchen311 4:0046f1b576ec 258
zchen311 4:0046f1b576ec 259 // PRIVATE FUNCTIONS
zchen311 4:0046f1b576ec 260 int SDFileSystem::_cmd(int cmd, int arg) {
zchen311 4:0046f1b576ec 261 _cs = 0;
zchen311 4:0046f1b576ec 262
zchen311 4:0046f1b576ec 263 // send a command
zchen311 4:0046f1b576ec 264 _spi.write(0x40 | cmd);
zchen311 4:0046f1b576ec 265 _spi.write(arg >> 24);
zchen311 4:0046f1b576ec 266 _spi.write(arg >> 16);
zchen311 4:0046f1b576ec 267 _spi.write(arg >> 8);
zchen311 4:0046f1b576ec 268 _spi.write(arg >> 0);
zchen311 4:0046f1b576ec 269 _spi.write(0x95);
zchen311 4:0046f1b576ec 270
zchen311 4:0046f1b576ec 271 // wait for the repsonse (response[7] == 0)
zchen311 4:0046f1b576ec 272 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
zchen311 4:0046f1b576ec 273 int response = _spi.write(0xFF);
zchen311 4:0046f1b576ec 274 if (!(response & 0x80)) {
zchen311 4:0046f1b576ec 275 _cs = 1;
zchen311 4:0046f1b576ec 276 _spi.write(0xFF);
zchen311 4:0046f1b576ec 277 return response;
zchen311 4:0046f1b576ec 278 }
zchen311 4:0046f1b576ec 279 }
zchen311 4:0046f1b576ec 280 _cs = 1;
zchen311 4:0046f1b576ec 281 _spi.write(0xFF);
zchen311 4:0046f1b576ec 282 return -1; // timeout
zchen311 4:0046f1b576ec 283 }
zchen311 4:0046f1b576ec 284 int SDFileSystem::_cmdx(int cmd, int arg) {
zchen311 4:0046f1b576ec 285 _cs = 0;
zchen311 4:0046f1b576ec 286
zchen311 4:0046f1b576ec 287 // send a command
zchen311 4:0046f1b576ec 288 _spi.write(0x40 | cmd);
zchen311 4:0046f1b576ec 289 _spi.write(arg >> 24);
zchen311 4:0046f1b576ec 290 _spi.write(arg >> 16);
zchen311 4:0046f1b576ec 291 _spi.write(arg >> 8);
zchen311 4:0046f1b576ec 292 _spi.write(arg >> 0);
zchen311 4:0046f1b576ec 293 _spi.write(0x95);
zchen311 4:0046f1b576ec 294
zchen311 4:0046f1b576ec 295 // wait for the repsonse (response[7] == 0)
zchen311 4:0046f1b576ec 296 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
zchen311 4:0046f1b576ec 297 int response = _spi.write(0xFF);
zchen311 4:0046f1b576ec 298 if (!(response & 0x80)) {
zchen311 4:0046f1b576ec 299 return response;
zchen311 4:0046f1b576ec 300 }
zchen311 4:0046f1b576ec 301 }
zchen311 4:0046f1b576ec 302 _cs = 1;
zchen311 4:0046f1b576ec 303 _spi.write(0xFF);
zchen311 4:0046f1b576ec 304 return -1; // timeout
zchen311 4:0046f1b576ec 305 }
zchen311 4:0046f1b576ec 306
zchen311 4:0046f1b576ec 307
zchen311 4:0046f1b576ec 308 int SDFileSystem::_cmd58() {
zchen311 4:0046f1b576ec 309 _cs = 0;
zchen311 4:0046f1b576ec 310 int arg = 0;
zchen311 4:0046f1b576ec 311
zchen311 4:0046f1b576ec 312 // send a command
zchen311 4:0046f1b576ec 313 _spi.write(0x40 | 58);
zchen311 4:0046f1b576ec 314 _spi.write(arg >> 24);
zchen311 4:0046f1b576ec 315 _spi.write(arg >> 16);
zchen311 4:0046f1b576ec 316 _spi.write(arg >> 8);
zchen311 4:0046f1b576ec 317 _spi.write(arg >> 0);
zchen311 4:0046f1b576ec 318 _spi.write(0x95);
zchen311 4:0046f1b576ec 319
zchen311 4:0046f1b576ec 320 // wait for the repsonse (response[7] == 0)
zchen311 4:0046f1b576ec 321 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
zchen311 4:0046f1b576ec 322 int response = _spi.write(0xFF);
zchen311 4:0046f1b576ec 323 if (!(response & 0x80)) {
zchen311 4:0046f1b576ec 324 int ocr = _spi.write(0xFF) << 24;
zchen311 4:0046f1b576ec 325 ocr |= _spi.write(0xFF) << 16;
zchen311 4:0046f1b576ec 326 ocr |= _spi.write(0xFF) << 8;
zchen311 4:0046f1b576ec 327 ocr |= _spi.write(0xFF) << 0;
zchen311 4:0046f1b576ec 328 _cs = 1;
zchen311 4:0046f1b576ec 329 _spi.write(0xFF);
zchen311 4:0046f1b576ec 330 return response;
zchen311 4:0046f1b576ec 331 }
zchen311 4:0046f1b576ec 332 }
zchen311 4:0046f1b576ec 333 _cs = 1;
zchen311 4:0046f1b576ec 334 _spi.write(0xFF);
zchen311 4:0046f1b576ec 335 return -1; // timeout
zchen311 4:0046f1b576ec 336 }
zchen311 4:0046f1b576ec 337
zchen311 4:0046f1b576ec 338 int SDFileSystem::_cmd8() {
zchen311 4:0046f1b576ec 339 _cs = 0;
zchen311 4:0046f1b576ec 340
zchen311 4:0046f1b576ec 341 // send a command
zchen311 4:0046f1b576ec 342 _spi.write(0x40 | 8); // CMD8
zchen311 4:0046f1b576ec 343 _spi.write(0x00); // reserved
zchen311 4:0046f1b576ec 344 _spi.write(0x00); // reserved
zchen311 4:0046f1b576ec 345 _spi.write(0x01); // 3.3v
zchen311 4:0046f1b576ec 346 _spi.write(0xAA); // check pattern
zchen311 4:0046f1b576ec 347 _spi.write(0x87); // crc
zchen311 4:0046f1b576ec 348
zchen311 4:0046f1b576ec 349 // wait for the repsonse (response[7] == 0)
zchen311 4:0046f1b576ec 350 for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) {
zchen311 4:0046f1b576ec 351 char response[5];
zchen311 4:0046f1b576ec 352 response[0] = _spi.write(0xFF);
zchen311 4:0046f1b576ec 353 if (!(response[0] & 0x80)) {
zchen311 4:0046f1b576ec 354 for (int j = 1; j < 5; j++) {
zchen311 4:0046f1b576ec 355 response[i] = _spi.write(0xFF);
zchen311 4:0046f1b576ec 356 }
zchen311 4:0046f1b576ec 357 _cs = 1;
zchen311 4:0046f1b576ec 358 _spi.write(0xFF);
zchen311 4:0046f1b576ec 359 return response[0];
zchen311 4:0046f1b576ec 360 }
zchen311 4:0046f1b576ec 361 }
zchen311 4:0046f1b576ec 362 _cs = 1;
zchen311 4:0046f1b576ec 363 _spi.write(0xFF);
zchen311 4:0046f1b576ec 364 return -1; // timeout
zchen311 4:0046f1b576ec 365 }
zchen311 4:0046f1b576ec 366
zchen311 4:0046f1b576ec 367 int SDFileSystem::_read(uint8_t *buffer, uint32_t length) {
zchen311 4:0046f1b576ec 368 _cs = 0;
zchen311 4:0046f1b576ec 369
zchen311 4:0046f1b576ec 370 // read until start byte (0xFF)
zchen311 4:0046f1b576ec 371 while (_spi.write(0xFF) != 0xFE);
zchen311 4:0046f1b576ec 372
zchen311 4:0046f1b576ec 373 // read data
zchen311 4:0046f1b576ec 374 for (int i = 0; i < length; i++) {
zchen311 4:0046f1b576ec 375 buffer[i] = _spi.write(0xFF);
zchen311 4:0046f1b576ec 376 }
zchen311 4:0046f1b576ec 377 _spi.write(0xFF); // checksum
zchen311 4:0046f1b576ec 378 _spi.write(0xFF);
zchen311 4:0046f1b576ec 379
zchen311 4:0046f1b576ec 380 _cs = 1;
zchen311 4:0046f1b576ec 381 _spi.write(0xFF);
zchen311 4:0046f1b576ec 382 return 0;
zchen311 4:0046f1b576ec 383 }
zchen311 4:0046f1b576ec 384
zchen311 4:0046f1b576ec 385 int SDFileSystem::_write(const uint8_t*buffer, uint32_t length) {
zchen311 4:0046f1b576ec 386 _cs = 0;
zchen311 4:0046f1b576ec 387
zchen311 4:0046f1b576ec 388 // indicate start of block
zchen311 4:0046f1b576ec 389 _spi.write(0xFE);
zchen311 4:0046f1b576ec 390
zchen311 4:0046f1b576ec 391 // write the data
zchen311 4:0046f1b576ec 392 for (int i = 0; i < length; i++) {
zchen311 4:0046f1b576ec 393 _spi.write(buffer[i]);
zchen311 4:0046f1b576ec 394 }
zchen311 4:0046f1b576ec 395
zchen311 4:0046f1b576ec 396 // write the checksum
zchen311 4:0046f1b576ec 397 _spi.write(0xFF);
zchen311 4:0046f1b576ec 398 _spi.write(0xFF);
zchen311 4:0046f1b576ec 399
zchen311 4:0046f1b576ec 400 // check the response token
zchen311 4:0046f1b576ec 401 if ((_spi.write(0xFF) & 0x1F) != 0x05) {
zchen311 4:0046f1b576ec 402 _cs = 1;
zchen311 4:0046f1b576ec 403 _spi.write(0xFF);
zchen311 4:0046f1b576ec 404 return 1;
zchen311 4:0046f1b576ec 405 }
zchen311 4:0046f1b576ec 406
zchen311 4:0046f1b576ec 407 // wait for write to finish
zchen311 4:0046f1b576ec 408 while (_spi.write(0xFF) == 0);
zchen311 4:0046f1b576ec 409
zchen311 4:0046f1b576ec 410 _cs = 1;
zchen311 4:0046f1b576ec 411 _spi.write(0xFF);
zchen311 4:0046f1b576ec 412 return 0;
zchen311 4:0046f1b576ec 413 }
zchen311 4:0046f1b576ec 414
zchen311 4:0046f1b576ec 415 static uint32_t ext_bits(unsigned char *data, int msb, int lsb) {
zchen311 4:0046f1b576ec 416 uint32_t bits = 0;
zchen311 4:0046f1b576ec 417 uint32_t size = 1 + msb - lsb;
zchen311 4:0046f1b576ec 418 for (int i = 0; i < size; i++) {
zchen311 4:0046f1b576ec 419 uint32_t position = lsb + i;
zchen311 4:0046f1b576ec 420 uint32_t byte = 15 - (position >> 3);
zchen311 4:0046f1b576ec 421 uint32_t bit = position & 0x7;
zchen311 4:0046f1b576ec 422 uint32_t value = (data[byte] >> bit) & 1;
zchen311 4:0046f1b576ec 423 bits |= value << i;
zchen311 4:0046f1b576ec 424 }
zchen311 4:0046f1b576ec 425 return bits;
zchen311 4:0046f1b576ec 426 }
zchen311 4:0046f1b576ec 427
zchen311 4:0046f1b576ec 428 uint64_t SDFileSystem::_sd_sectors() {
zchen311 4:0046f1b576ec 429 uint32_t c_size, c_size_mult, read_bl_len;
zchen311 4:0046f1b576ec 430 uint32_t block_len, mult, blocknr, capacity;
zchen311 4:0046f1b576ec 431 uint32_t hc_c_size;
zchen311 4:0046f1b576ec 432 uint64_t blocks;
zchen311 4:0046f1b576ec 433
zchen311 4:0046f1b576ec 434 // CMD9, Response R2 (R1 byte + 16-byte block read)
zchen311 4:0046f1b576ec 435 if (_cmdx(9, 0) != 0) {
zchen311 4:0046f1b576ec 436 debug("Didn't get a response from the disk\n");
zchen311 4:0046f1b576ec 437 return 0;
zchen311 4:0046f1b576ec 438 }
zchen311 4:0046f1b576ec 439
zchen311 4:0046f1b576ec 440 uint8_t csd[16];
zchen311 4:0046f1b576ec 441 if (_read(csd, 16) != 0) {
zchen311 4:0046f1b576ec 442 debug("Couldn't read csd response from disk\n");
zchen311 4:0046f1b576ec 443 return 0;
zchen311 4:0046f1b576ec 444 }
zchen311 4:0046f1b576ec 445
zchen311 4:0046f1b576ec 446 // csd_structure : csd[127:126]
zchen311 4:0046f1b576ec 447 // c_size : csd[73:62]
zchen311 4:0046f1b576ec 448 // c_size_mult : csd[49:47]
zchen311 4:0046f1b576ec 449 // read_bl_len : csd[83:80] - the *maximum* read block length
zchen311 4:0046f1b576ec 450
zchen311 4:0046f1b576ec 451 int csd_structure = ext_bits(csd, 127, 126);
zchen311 4:0046f1b576ec 452
zchen311 4:0046f1b576ec 453 switch (csd_structure) {
zchen311 4:0046f1b576ec 454 case 0:
zchen311 4:0046f1b576ec 455 cdv = 512;
zchen311 4:0046f1b576ec 456 c_size = ext_bits(csd, 73, 62);
zchen311 4:0046f1b576ec 457 c_size_mult = ext_bits(csd, 49, 47);
zchen311 4:0046f1b576ec 458 read_bl_len = ext_bits(csd, 83, 80);
zchen311 4:0046f1b576ec 459
zchen311 4:0046f1b576ec 460 block_len = 1 << read_bl_len;
zchen311 4:0046f1b576ec 461 mult = 1 << (c_size_mult + 2);
zchen311 4:0046f1b576ec 462 blocknr = (c_size + 1) * mult;
zchen311 4:0046f1b576ec 463 capacity = blocknr * block_len;
zchen311 4:0046f1b576ec 464 blocks = capacity / 512;
zchen311 4:0046f1b576ec 465 debug_if(SD_DBG, "\n\rSDCard\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks);
zchen311 4:0046f1b576ec 466 break;
zchen311 4:0046f1b576ec 467
zchen311 4:0046f1b576ec 468 case 1:
zchen311 4:0046f1b576ec 469 cdv = 1;
zchen311 4:0046f1b576ec 470 hc_c_size = ext_bits(csd, 63, 48);
zchen311 4:0046f1b576ec 471 blocks = (hc_c_size+1)*1024;
zchen311 4:0046f1b576ec 472 debug_if(SD_DBG, "\n\rSDHC Card \n\rhc_c_size: %d\n\rcapacity: %lld \n\rsectors: %lld\n\r", hc_c_size, blocks*512, blocks);
zchen311 4:0046f1b576ec 473 break;
zchen311 4:0046f1b576ec 474
zchen311 4:0046f1b576ec 475 default:
zchen311 4:0046f1b576ec 476 debug("CSD struct unsupported\r\n");
zchen311 4:0046f1b576ec 477 return 0;
zchen311 4:0046f1b576ec 478 };
zchen311 4:0046f1b576ec 479 return blocks;
zchen311 4:0046f1b576ec 480 }