this will take a image from C328 serial camera and store those images in mbed flash as html and this html page is uploaded into the server at ip:192.168.1.2

Dependencies:   mbed

Committer:
mitesh2patel
Date:
Wed Dec 15 15:01:56 2010 +0000
Revision:
0:e1a0471e5ffb

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mitesh2patel 0:e1a0471e5ffb 1 /* mbed Microcontroller Library - SDFileSystem
mitesh2patel 0:e1a0471e5ffb 2 * Copyright (c) 2008-2009, sford
mitesh2patel 0:e1a0471e5ffb 3 *
mitesh2patel 0:e1a0471e5ffb 4 * Introduction
mitesh2patel 0:e1a0471e5ffb 5 * ------------
mitesh2patel 0:e1a0471e5ffb 6 * SD and MMC cards support a number of interfaces, but common to them all
mitesh2patel 0:e1a0471e5ffb 7 * is one based on SPI. This is the one I'm implmenting because it means
mitesh2patel 0:e1a0471e5ffb 8 * it is much more portable even though not so performant, and we already
mitesh2patel 0:e1a0471e5ffb 9 * have the mbed SPI Interface!
mitesh2patel 0:e1a0471e5ffb 10 *
mitesh2patel 0:e1a0471e5ffb 11 * The main reference I'm using is Chapter 7, "SPI Mode" of:
mitesh2patel 0:e1a0471e5ffb 12 * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
mitesh2patel 0:e1a0471e5ffb 13 *
mitesh2patel 0:e1a0471e5ffb 14 * SPI Startup
mitesh2patel 0:e1a0471e5ffb 15 * -----------
mitesh2patel 0:e1a0471e5ffb 16 * The SD card powers up in SD mode. The SPI interface mode is selected by
mitesh2patel 0:e1a0471e5ffb 17 * asserting CS low and sending the reset command (CMD0). The card will
mitesh2patel 0:e1a0471e5ffb 18 * respond with a (R1) response.
mitesh2patel 0:e1a0471e5ffb 19 *
mitesh2patel 0:e1a0471e5ffb 20 * CMD8 is optionally sent to determine the voltage range supported, and
mitesh2patel 0:e1a0471e5ffb 21 * indirectly determine whether it is a version 1.x SD/non-SD card or
mitesh2patel 0:e1a0471e5ffb 22 * version 2.x. I'll just ignore this for now.
mitesh2patel 0:e1a0471e5ffb 23 *
mitesh2patel 0:e1a0471e5ffb 24 * ACMD41 is repeatedly issued to initialise the card, until "in idle"
mitesh2patel 0:e1a0471e5ffb 25 * (bit 0) of the R1 response goes to '0', indicating it is initialised.
mitesh2patel 0:e1a0471e5ffb 26 *
mitesh2patel 0:e1a0471e5ffb 27 * You should also indicate whether the host supports High Capicity cards,
mitesh2patel 0:e1a0471e5ffb 28 * and check whether the card is high capacity - i'll also ignore this
mitesh2patel 0:e1a0471e5ffb 29 *
mitesh2patel 0:e1a0471e5ffb 30 * SPI Protocol
mitesh2patel 0:e1a0471e5ffb 31 * ------------
mitesh2patel 0:e1a0471e5ffb 32 * The SD SPI protocol is based on transactions made up of 8-bit words, with
mitesh2patel 0:e1a0471e5ffb 33 * the host starting every bus transaction by asserting the CS signal low. The
mitesh2patel 0:e1a0471e5ffb 34 * card always responds to commands, data blocks and errors.
mitesh2patel 0:e1a0471e5ffb 35 *
mitesh2patel 0:e1a0471e5ffb 36 * The protocol supports a CRC, but by default it is off (except for the
mitesh2patel 0:e1a0471e5ffb 37 * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
mitesh2patel 0:e1a0471e5ffb 38 * I'll leave the CRC off I think!
mitesh2patel 0:e1a0471e5ffb 39 *
mitesh2patel 0:e1a0471e5ffb 40 * Standard capacity cards have variable data block sizes, whereas High
mitesh2patel 0:e1a0471e5ffb 41 * Capacity cards fix the size of data block to 512 bytes. I'll therefore
mitesh2patel 0:e1a0471e5ffb 42 * just always use the Standard Capacity cards with a block size of 512 bytes.
mitesh2patel 0:e1a0471e5ffb 43 * This is set with CMD16.
mitesh2patel 0:e1a0471e5ffb 44 *
mitesh2patel 0:e1a0471e5ffb 45 * You can read and write single blocks (CMD17, CMD25) or multiple blocks
mitesh2patel 0:e1a0471e5ffb 46 * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
mitesh2patel 0:e1a0471e5ffb 47 * the card gets a read command, it responds with a response token, and then
mitesh2patel 0:e1a0471e5ffb 48 * a data token or an error.
mitesh2patel 0:e1a0471e5ffb 49 *
mitesh2patel 0:e1a0471e5ffb 50 * SPI Command Format
mitesh2patel 0:e1a0471e5ffb 51 * ------------------
mitesh2patel 0:e1a0471e5ffb 52 * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
mitesh2patel 0:e1a0471e5ffb 53 *
mitesh2patel 0:e1a0471e5ffb 54 * +---------------+------------+------------+-----------+----------+--------------+
mitesh2patel 0:e1a0471e5ffb 55 * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
mitesh2patel 0:e1a0471e5ffb 56 * +---------------+------------+------------+-----------+----------+--------------+
mitesh2patel 0:e1a0471e5ffb 57 *
mitesh2patel 0:e1a0471e5ffb 58 * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
mitesh2patel 0:e1a0471e5ffb 59 *
mitesh2patel 0:e1a0471e5ffb 60 * All Application Specific commands shall be preceded with APP_CMD (CMD55).
mitesh2patel 0:e1a0471e5ffb 61 *
mitesh2patel 0:e1a0471e5ffb 62 * SPI Response Format
mitesh2patel 0:e1a0471e5ffb 63 * -------------------
mitesh2patel 0:e1a0471e5ffb 64 * The main response format (R1) is a status byte (normally zero). Key flags:
mitesh2patel 0:e1a0471e5ffb 65 * idle - 1 if the card is in an idle state/initialising
mitesh2patel 0:e1a0471e5ffb 66 * cmd - 1 if an illegal command code was detected
mitesh2patel 0:e1a0471e5ffb 67 *
mitesh2patel 0:e1a0471e5ffb 68 * +-------------------------------------------------+
mitesh2patel 0:e1a0471e5ffb 69 * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
mitesh2patel 0:e1a0471e5ffb 70 * +-------------------------------------------------+
mitesh2patel 0:e1a0471e5ffb 71 *
mitesh2patel 0:e1a0471e5ffb 72 * R1b is the same, except it is followed by a busy signal (zeros) until
mitesh2patel 0:e1a0471e5ffb 73 * the first non-zero byte when it is ready again.
mitesh2patel 0:e1a0471e5ffb 74 *
mitesh2patel 0:e1a0471e5ffb 75 * Data Response Token
mitesh2patel 0:e1a0471e5ffb 76 * -------------------
mitesh2patel 0:e1a0471e5ffb 77 * Every data block written to the card is acknowledged by a byte
mitesh2patel 0:e1a0471e5ffb 78 * response token
mitesh2patel 0:e1a0471e5ffb 79 *
mitesh2patel 0:e1a0471e5ffb 80 * +----------------------+
mitesh2patel 0:e1a0471e5ffb 81 * | xxx | 0 | status | 1 |
mitesh2patel 0:e1a0471e5ffb 82 * +----------------------+
mitesh2patel 0:e1a0471e5ffb 83 * 010 - OK!
mitesh2patel 0:e1a0471e5ffb 84 * 101 - CRC Error
mitesh2patel 0:e1a0471e5ffb 85 * 110 - Write Error
mitesh2patel 0:e1a0471e5ffb 86 *
mitesh2patel 0:e1a0471e5ffb 87 * Single Block Read and Write
mitesh2patel 0:e1a0471e5ffb 88 * ---------------------------
mitesh2patel 0:e1a0471e5ffb 89 *
mitesh2patel 0:e1a0471e5ffb 90 * Block transfers have a byte header, followed by the data, followed
mitesh2patel 0:e1a0471e5ffb 91 * by a 16-bit CRC. In our case, the data will always be 512 bytes.
mitesh2patel 0:e1a0471e5ffb 92 *
mitesh2patel 0:e1a0471e5ffb 93 * +------+---------+---------+- - - -+---------+-----------+----------+
mitesh2patel 0:e1a0471e5ffb 94 * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] |
mitesh2patel 0:e1a0471e5ffb 95 * +------+---------+---------+- - - -+---------+-----------+----------+
mitesh2patel 0:e1a0471e5ffb 96 */
mitesh2patel 0:e1a0471e5ffb 97
mitesh2patel 0:e1a0471e5ffb 98 #include "SDFileSystem.h"
mitesh2patel 0:e1a0471e5ffb 99
mitesh2patel 0:e1a0471e5ffb 100 #define SD_COMMAND_TIMEOUT 5000
mitesh2patel 0:e1a0471e5ffb 101
mitesh2patel 0:e1a0471e5ffb 102 //#define CR "\n"
mitesh2patel 0:e1a0471e5ffb 103 #define CR "\r\n"
mitesh2patel 0:e1a0471e5ffb 104
mitesh2patel 0:e1a0471e5ffb 105 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) :
mitesh2patel 0:e1a0471e5ffb 106 FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) {
mitesh2patel 0:e1a0471e5ffb 107 _cs = 1;
mitesh2patel 0:e1a0471e5ffb 108 }
mitesh2patel 0:e1a0471e5ffb 109
mitesh2patel 0:e1a0471e5ffb 110 #define R1_IDLE_STATE (1 << 0)
mitesh2patel 0:e1a0471e5ffb 111 #define R1_ERASE_RESET (1 << 1)
mitesh2patel 0:e1a0471e5ffb 112 #define R1_ILLEGAL_COMMAND (1 << 2)
mitesh2patel 0:e1a0471e5ffb 113 #define R1_COM_CRC_ERROR (1 << 3)
mitesh2patel 0:e1a0471e5ffb 114 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
mitesh2patel 0:e1a0471e5ffb 115 #define R1_ADDRESS_ERROR (1 << 5)
mitesh2patel 0:e1a0471e5ffb 116 #define R1_PARAMETER_ERROR (1 << 6)
mitesh2patel 0:e1a0471e5ffb 117
mitesh2patel 0:e1a0471e5ffb 118 int SDFileSystem::disk_initialize() {
mitesh2patel 0:e1a0471e5ffb 119
mitesh2patel 0:e1a0471e5ffb 120 _spi.frequency(100000); // Set to 100kHz for initialisation
mitesh2patel 0:e1a0471e5ffb 121
mitesh2patel 0:e1a0471e5ffb 122 // Initialise the card by clocking it a bit (cs = 1)
mitesh2patel 0:e1a0471e5ffb 123 _cs = 1;
mitesh2patel 0:e1a0471e5ffb 124 for(int i=0; i<16; i++) {
mitesh2patel 0:e1a0471e5ffb 125 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 126 }
mitesh2patel 0:e1a0471e5ffb 127
mitesh2patel 0:e1a0471e5ffb 128 // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
mitesh2patel 0:e1a0471e5ffb 129 if(_cmd(0, 0) != R1_IDLE_STATE) {
mitesh2patel 0:e1a0471e5ffb 130 fprintf(stderr, "No disk, or could not put SD card into SPI idle state" CR);
mitesh2patel 0:e1a0471e5ffb 131 return 1;
mitesh2patel 0:e1a0471e5ffb 132 }
mitesh2patel 0:e1a0471e5ffb 133
mitesh2patel 0:e1a0471e5ffb 134 int r = _cmd8();
mitesh2patel 0:e1a0471e5ffb 135 if(r == R1_IDLE_STATE) {
mitesh2patel 0:e1a0471e5ffb 136 printf("SD version 2.x" CR);
mitesh2patel 0:e1a0471e5ffb 137 } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
mitesh2patel 0:e1a0471e5ffb 138 printf("SD version 1.x" CR);
mitesh2patel 0:e1a0471e5ffb 139 } else {
mitesh2patel 0:e1a0471e5ffb 140 error("Unknown SD version" CR);
mitesh2patel 0:e1a0471e5ffb 141 }
mitesh2patel 0:e1a0471e5ffb 142
mitesh2patel 0:e1a0471e5ffb 143 // ACMD41 to give host capacity support (repeat until not busy)
mitesh2patel 0:e1a0471e5ffb 144 // ACMD41 is application specific command, so we send APP_CMD (CMD55) beforehand
mitesh2patel 0:e1a0471e5ffb 145 for(int i=0;; i++) {
mitesh2patel 0:e1a0471e5ffb 146 _cmd(55, 0);
mitesh2patel 0:e1a0471e5ffb 147 int response = _cmd(41, 0);
mitesh2patel 0:e1a0471e5ffb 148 if(response == 0) {
mitesh2patel 0:e1a0471e5ffb 149 break;
mitesh2patel 0:e1a0471e5ffb 150 } else if(i > SD_COMMAND_TIMEOUT) {
mitesh2patel 0:e1a0471e5ffb 151 fprintf(stderr, "Timeout waiting for card" CR);
mitesh2patel 0:e1a0471e5ffb 152 return 1;
mitesh2patel 0:e1a0471e5ffb 153 }
mitesh2patel 0:e1a0471e5ffb 154 }
mitesh2patel 0:e1a0471e5ffb 155
mitesh2patel 0:e1a0471e5ffb 156 // printf("OK" CR);
mitesh2patel 0:e1a0471e5ffb 157
mitesh2patel 0:e1a0471e5ffb 158 _sectors = _sd_sectors();
mitesh2patel 0:e1a0471e5ffb 159
mitesh2patel 0:e1a0471e5ffb 160 // Set block length to 512 (CMD16)
mitesh2patel 0:e1a0471e5ffb 161 if(_cmd(16, 512) != 0) {
mitesh2patel 0:e1a0471e5ffb 162 fprintf(stderr, "Set block timeout" CR);
mitesh2patel 0:e1a0471e5ffb 163 return 1;
mitesh2patel 0:e1a0471e5ffb 164 }
mitesh2patel 0:e1a0471e5ffb 165
mitesh2patel 0:e1a0471e5ffb 166 _spi.frequency(1000000); // Set to 1MHz for data transfer
mitesh2patel 0:e1a0471e5ffb 167 return 0;
mitesh2patel 0:e1a0471e5ffb 168 }
mitesh2patel 0:e1a0471e5ffb 169
mitesh2patel 0:e1a0471e5ffb 170 int SDFileSystem::disk_write(const char *buffer, int block_number) {
mitesh2patel 0:e1a0471e5ffb 171 // set write address for single block (CMD24)
mitesh2patel 0:e1a0471e5ffb 172 if(_cmd(24, block_number * 512) != 0) {
mitesh2patel 0:e1a0471e5ffb 173 return 1;
mitesh2patel 0:e1a0471e5ffb 174 }
mitesh2patel 0:e1a0471e5ffb 175
mitesh2patel 0:e1a0471e5ffb 176 // send the data block
mitesh2patel 0:e1a0471e5ffb 177 _write(buffer, 512);
mitesh2patel 0:e1a0471e5ffb 178 return 0;
mitesh2patel 0:e1a0471e5ffb 179 }
mitesh2patel 0:e1a0471e5ffb 180
mitesh2patel 0:e1a0471e5ffb 181 int SDFileSystem::disk_read(char *buffer, int block_number) {
mitesh2patel 0:e1a0471e5ffb 182 // set read address for single block (CMD17)
mitesh2patel 0:e1a0471e5ffb 183 if(_cmd(17, block_number * 512) != 0) {
mitesh2patel 0:e1a0471e5ffb 184 return 1;
mitesh2patel 0:e1a0471e5ffb 185 }
mitesh2patel 0:e1a0471e5ffb 186
mitesh2patel 0:e1a0471e5ffb 187 // receive the data
mitesh2patel 0:e1a0471e5ffb 188 _read(buffer, 512);
mitesh2patel 0:e1a0471e5ffb 189 return 0;
mitesh2patel 0:e1a0471e5ffb 190 }
mitesh2patel 0:e1a0471e5ffb 191
mitesh2patel 0:e1a0471e5ffb 192 int SDFileSystem::disk_status() { return 0; }
mitesh2patel 0:e1a0471e5ffb 193 int SDFileSystem::disk_sync() { return 0; }
mitesh2patel 0:e1a0471e5ffb 194 int SDFileSystem::disk_sectors() { return _sectors; }
mitesh2patel 0:e1a0471e5ffb 195
mitesh2patel 0:e1a0471e5ffb 196 // PRIVATE FUNCTIONS
mitesh2patel 0:e1a0471e5ffb 197
mitesh2patel 0:e1a0471e5ffb 198 int SDFileSystem::_cmd(int cmd, int arg) {
mitesh2patel 0:e1a0471e5ffb 199 _cs = 0;
mitesh2patel 0:e1a0471e5ffb 200
mitesh2patel 0:e1a0471e5ffb 201 // send a command
mitesh2patel 0:e1a0471e5ffb 202 _spi.write(0x40 | cmd);
mitesh2patel 0:e1a0471e5ffb 203 _spi.write(arg >> 24);
mitesh2patel 0:e1a0471e5ffb 204 _spi.write(arg >> 16);
mitesh2patel 0:e1a0471e5ffb 205 _spi.write(arg >> 8);
mitesh2patel 0:e1a0471e5ffb 206 _spi.write(arg >> 0);
mitesh2patel 0:e1a0471e5ffb 207 _spi.write(0x95);
mitesh2patel 0:e1a0471e5ffb 208
mitesh2patel 0:e1a0471e5ffb 209 // wait for the repsonse (response[7] == 0)
mitesh2patel 0:e1a0471e5ffb 210 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
mitesh2patel 0:e1a0471e5ffb 211 int response = _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 212 if(!(response & 0x80)) {
mitesh2patel 0:e1a0471e5ffb 213 _cs = 1;
mitesh2patel 0:e1a0471e5ffb 214 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 215 return response;
mitesh2patel 0:e1a0471e5ffb 216 }
mitesh2patel 0:e1a0471e5ffb 217 }
mitesh2patel 0:e1a0471e5ffb 218 _cs = 1;
mitesh2patel 0:e1a0471e5ffb 219 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 220 return -1; // timeout
mitesh2patel 0:e1a0471e5ffb 221 }
mitesh2patel 0:e1a0471e5ffb 222
mitesh2patel 0:e1a0471e5ffb 223 int SDFileSystem::_cmd8() {
mitesh2patel 0:e1a0471e5ffb 224 _cs = 0;
mitesh2patel 0:e1a0471e5ffb 225
mitesh2patel 0:e1a0471e5ffb 226 // send a command
mitesh2patel 0:e1a0471e5ffb 227 _spi.write(0x40 | 8); // CMD8
mitesh2patel 0:e1a0471e5ffb 228 _spi.write(0x00); // reserved
mitesh2patel 0:e1a0471e5ffb 229 _spi.write(0x00); // reserved
mitesh2patel 0:e1a0471e5ffb 230 _spi.write(0x01); // 3.3v
mitesh2patel 0:e1a0471e5ffb 231 _spi.write(0xAA); // check pattern
mitesh2patel 0:e1a0471e5ffb 232 _spi.write(0x87); // crc
mitesh2patel 0:e1a0471e5ffb 233
mitesh2patel 0:e1a0471e5ffb 234 // wait for the repsonse (response[7] == 0)
mitesh2patel 0:e1a0471e5ffb 235 for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
mitesh2patel 0:e1a0471e5ffb 236 char response[5];
mitesh2patel 0:e1a0471e5ffb 237 response[0] = _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 238 if(!(response[0] & 0x80)) {
mitesh2patel 0:e1a0471e5ffb 239 for(int j=1; j<5; j++) {
mitesh2patel 0:e1a0471e5ffb 240 response[i] = _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 241 }
mitesh2patel 0:e1a0471e5ffb 242 _cs = 1;
mitesh2patel 0:e1a0471e5ffb 243 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 244 return response[0];
mitesh2patel 0:e1a0471e5ffb 245 }
mitesh2patel 0:e1a0471e5ffb 246 }
mitesh2patel 0:e1a0471e5ffb 247 _cs = 1;
mitesh2patel 0:e1a0471e5ffb 248 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 249 return -1; // timeout
mitesh2patel 0:e1a0471e5ffb 250 }
mitesh2patel 0:e1a0471e5ffb 251
mitesh2patel 0:e1a0471e5ffb 252 int SDFileSystem::_read(char *buffer, int length) {
mitesh2patel 0:e1a0471e5ffb 253 _cs = 0;
mitesh2patel 0:e1a0471e5ffb 254
mitesh2patel 0:e1a0471e5ffb 255 // read until start byte (0xFF)
mitesh2patel 0:e1a0471e5ffb 256 while(_spi.write(0xFF) != 0xFE);
mitesh2patel 0:e1a0471e5ffb 257
mitesh2patel 0:e1a0471e5ffb 258 // read data
mitesh2patel 0:e1a0471e5ffb 259 for(int i=0; i<length; i++) {
mitesh2patel 0:e1a0471e5ffb 260 buffer[i] = _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 261 }
mitesh2patel 0:e1a0471e5ffb 262 _spi.write(0xFF); // checksum
mitesh2patel 0:e1a0471e5ffb 263 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 264
mitesh2patel 0:e1a0471e5ffb 265 _cs = 1;
mitesh2patel 0:e1a0471e5ffb 266 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 267 return 0;
mitesh2patel 0:e1a0471e5ffb 268 }
mitesh2patel 0:e1a0471e5ffb 269
mitesh2patel 0:e1a0471e5ffb 270 int SDFileSystem::_write(const char *buffer, int length) {
mitesh2patel 0:e1a0471e5ffb 271 _cs = 0;
mitesh2patel 0:e1a0471e5ffb 272
mitesh2patel 0:e1a0471e5ffb 273 // indicate start of block
mitesh2patel 0:e1a0471e5ffb 274 _spi.write(0xFE);
mitesh2patel 0:e1a0471e5ffb 275
mitesh2patel 0:e1a0471e5ffb 276 // write the data
mitesh2patel 0:e1a0471e5ffb 277 for(int i=0; i<length; i++) {
mitesh2patel 0:e1a0471e5ffb 278 _spi.write(buffer[i]);
mitesh2patel 0:e1a0471e5ffb 279 }
mitesh2patel 0:e1a0471e5ffb 280
mitesh2patel 0:e1a0471e5ffb 281 // write the checksum
mitesh2patel 0:e1a0471e5ffb 282 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 283 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 284
mitesh2patel 0:e1a0471e5ffb 285 // check the repsonse token
mitesh2patel 0:e1a0471e5ffb 286 if((_spi.write(0xFF) & 0x1F) != 0x05) {
mitesh2patel 0:e1a0471e5ffb 287 _cs = 1;
mitesh2patel 0:e1a0471e5ffb 288 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 289 return 1;
mitesh2patel 0:e1a0471e5ffb 290 }
mitesh2patel 0:e1a0471e5ffb 291
mitesh2patel 0:e1a0471e5ffb 292 // wait for write to finish
mitesh2patel 0:e1a0471e5ffb 293 while(_spi.write(0xFF) == 0);
mitesh2patel 0:e1a0471e5ffb 294
mitesh2patel 0:e1a0471e5ffb 295 _cs = 1;
mitesh2patel 0:e1a0471e5ffb 296 _spi.write(0xFF);
mitesh2patel 0:e1a0471e5ffb 297 return 0;
mitesh2patel 0:e1a0471e5ffb 298 }
mitesh2patel 0:e1a0471e5ffb 299
mitesh2patel 0:e1a0471e5ffb 300 static int ext_bits(char *data, int msb, int lsb) {
mitesh2patel 0:e1a0471e5ffb 301 int bits = 0;
mitesh2patel 0:e1a0471e5ffb 302 int size = 1 + msb - lsb;
mitesh2patel 0:e1a0471e5ffb 303 for(int i=0; i<size; i++) {
mitesh2patel 0:e1a0471e5ffb 304 int position = lsb + i;
mitesh2patel 0:e1a0471e5ffb 305 int byte = 15 - (position >> 3);
mitesh2patel 0:e1a0471e5ffb 306 int bit = position & 0x7;
mitesh2patel 0:e1a0471e5ffb 307 int value = (data[byte] >> bit) & 1;
mitesh2patel 0:e1a0471e5ffb 308 bits |= value << i;
mitesh2patel 0:e1a0471e5ffb 309 }
mitesh2patel 0:e1a0471e5ffb 310 return bits;
mitesh2patel 0:e1a0471e5ffb 311 }
mitesh2patel 0:e1a0471e5ffb 312
mitesh2patel 0:e1a0471e5ffb 313 int SDFileSystem::_sd_sectors() {
mitesh2patel 0:e1a0471e5ffb 314
mitesh2patel 0:e1a0471e5ffb 315 // CMD9, Response R2 (R1 byte + 16-byte block read)
mitesh2patel 0:e1a0471e5ffb 316 if(_cmd(9, 0) != 0) {
mitesh2patel 0:e1a0471e5ffb 317 fprintf(stderr, "Didn't get a response from the disk" CR);
mitesh2patel 0:e1a0471e5ffb 318 return 0;
mitesh2patel 0:e1a0471e5ffb 319 }
mitesh2patel 0:e1a0471e5ffb 320
mitesh2patel 0:e1a0471e5ffb 321 char csd[16];
mitesh2patel 0:e1a0471e5ffb 322 if(_read(csd, 16) != 0) {
mitesh2patel 0:e1a0471e5ffb 323 fprintf(stderr, "Couldn't read csd response from disk" CR);
mitesh2patel 0:e1a0471e5ffb 324 return 0;
mitesh2patel 0:e1a0471e5ffb 325 }
mitesh2patel 0:e1a0471e5ffb 326
mitesh2patel 0:e1a0471e5ffb 327 // csd_structure : csd[127:126]
mitesh2patel 0:e1a0471e5ffb 328 // c_size : csd[73:62]
mitesh2patel 0:e1a0471e5ffb 329 // c_size_mult : csd[49:47]
mitesh2patel 0:e1a0471e5ffb 330 // read_bl_len : csd[83:80]
mitesh2patel 0:e1a0471e5ffb 331
mitesh2patel 0:e1a0471e5ffb 332 int csd_structure = ext_bits(csd, 127, 126);
mitesh2patel 0:e1a0471e5ffb 333 int c_size = ext_bits(csd, 73, 62);
mitesh2patel 0:e1a0471e5ffb 334 int c_size_mult = ext_bits(csd, 49, 47);
mitesh2patel 0:e1a0471e5ffb 335 int read_bl_len = ext_bits(csd, 83, 80);
mitesh2patel 0:e1a0471e5ffb 336
mitesh2patel 0:e1a0471e5ffb 337 if(csd_structure != 0) {
mitesh2patel 0:e1a0471e5ffb 338 fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures" CR);
mitesh2patel 0:e1a0471e5ffb 339 // Non-zero is SDHC.
mitesh2patel 0:e1a0471e5ffb 340 return 0;
mitesh2patel 0:e1a0471e5ffb 341 }
mitesh2patel 0:e1a0471e5ffb 342
mitesh2patel 0:e1a0471e5ffb 343 int blocks = (c_size + 1) * (1 << (c_size_mult + 2));
mitesh2patel 0:e1a0471e5ffb 344 int block_size = 1 << read_bl_len;
mitesh2patel 0:e1a0471e5ffb 345
mitesh2patel 0:e1a0471e5ffb 346 if (block_size != 512 && block_size != 1024) {
mitesh2patel 0:e1a0471e5ffb 347 fprintf(stderr, "This disk tastes funny! %d byte block. I only like 512 or 1024 -byte blocks" CR, block_size);
mitesh2patel 0:e1a0471e5ffb 348 return 0;
mitesh2patel 0:e1a0471e5ffb 349 }
mitesh2patel 0:e1a0471e5ffb 350
mitesh2patel 0:e1a0471e5ffb 351 return blocks;
mitesh2patel 0:e1a0471e5ffb 352 }