Only Yesterday 制御プログラム

Dependencies:   mbed FATFileSystem

Fork of OnlyYestaerday by Junichi Katsu

Committer:
jksoft
Date:
Wed Apr 02 01:43:55 2014 +0000
Revision:
0:5975af170e43
1st Prototype

Who changed what in which revision?

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