AWS IoT demonstration using the Avnet Shield (AT&T LTE) and the FRDM-K64F target board.

Dependencies:   K64F_FATFileSystem

Fork of mbed-os-example-tls-tls-client by mbed-os-examples

Committer:
ampembeng
Date:
Tue Dec 06 22:31:15 2016 +0000
Revision:
18:6370da1de572
Added code to support SD card access.  The key/cert and MQTT information required for the demo can now be pulled from the SD card file system.

Who changed what in which revision?

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