ferney alberto beltran molina
/
00_LAB_SD_INITIAL
prueba sd card
main.cpp@0:9b6d6fa5c401, 2018-04-17 (annotated)
- Committer:
- fabeltranm
- Date:
- Tue Apr 17 23:34:09 2018 +0000
- Revision:
- 0:9b6d6fa5c401
sdcard
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
fabeltranm | 0:9b6d6fa5c401 | 1 | #include "mbed.h" |
fabeltranm | 0:9b6d6fa5c401 | 2 | /* SPI Command Format |
fabeltranm | 0:9b6d6fa5c401 | 3 | * ------------------ |
fabeltranm | 0:9b6d6fa5c401 | 4 | * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC. |
fabeltranm | 0:9b6d6fa5c401 | 5 | * |
fabeltranm | 0:9b6d6fa5c401 | 6 | * +---------------+------------+------------+-----------+----------+--------------+ |
fabeltranm | 0:9b6d6fa5c401 | 7 | * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 | |
fabeltranm | 0:9b6d6fa5c401 | 8 | * +---------------+------------+------------+-----------+----------+--------------+ |
fabeltranm | 0:9b6d6fa5c401 | 9 | * |
fabeltranm | 0:9b6d6fa5c401 | 10 | * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95) |
fabeltranm | 0:9b6d6fa5c401 | 11 | * |
fabeltranm | 0:9b6d6fa5c401 | 12 | * All Application Specific commands shall be preceded with APP_CMD (CMD55). |
fabeltranm | 0:9b6d6fa5c401 | 13 | * |
fabeltranm | 0:9b6d6fa5c401 | 14 | * SPI Response Format |
fabeltranm | 0:9b6d6fa5c401 | 15 | * ------------------- |
fabeltranm | 0:9b6d6fa5c401 | 16 | * The main response format (R1) is a status byte (normally zero). Key flags: |
fabeltranm | 0:9b6d6fa5c401 | 17 | * idle - 1 if the card is in an idle state/initialising |
fabeltranm | 0:9b6d6fa5c401 | 18 | * cmd - 1 if an illegal command code was detected |
fabeltranm | 0:9b6d6fa5c401 | 19 | * |
fabeltranm | 0:9b6d6fa5c401 | 20 | * +-------------------------------------------------+ |
fabeltranm | 0:9b6d6fa5c401 | 21 | * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle | |
fabeltranm | 0:9b6d6fa5c401 | 22 | * +-------------------------------------------------+ |
fabeltranm | 0:9b6d6fa5c401 | 23 | * |
fabeltranm | 0:9b6d6fa5c401 | 24 | * R1b is the same, except it is followed by a busy signal (zeros) until |
fabeltranm | 0:9b6d6fa5c401 | 25 | * the first non-zero byte when it is ready again. |
fabeltranm | 0:9b6d6fa5c401 | 26 | * |
fabeltranm | 0:9b6d6fa5c401 | 27 | * Data Response Token |
fabeltranm | 0:9b6d6fa5c401 | 28 | * ------------------- |
fabeltranm | 0:9b6d6fa5c401 | 29 | * Every data block written to the card is acknowledged by a byte |
fabeltranm | 0:9b6d6fa5c401 | 30 | * response token |
fabeltranm | 0:9b6d6fa5c401 | 31 | * |
fabeltranm | 0:9b6d6fa5c401 | 32 | * +----------------------+ |
fabeltranm | 0:9b6d6fa5c401 | 33 | * | xxx | 0 | status | 1 | |
fabeltranm | 0:9b6d6fa5c401 | 34 | * +----------------------+ |
fabeltranm | 0:9b6d6fa5c401 | 35 | * 010 - OK! |
fabeltranm | 0:9b6d6fa5c401 | 36 | * 101 - CRC Error |
fabeltranm | 0:9b6d6fa5c401 | 37 | * 110 - Write Error |
fabeltranm | 0:9b6d6fa5c401 | 38 | * |
fabeltranm | 0:9b6d6fa5c401 | 39 | * Single Block Read and Write |
fabeltranm | 0:9b6d6fa5c401 | 40 | * --------------------------- |
fabeltranm | 0:9b6d6fa5c401 | 41 | * |
fabeltranm | 0:9b6d6fa5c401 | 42 | * Block transfers have a byte header, followed by the data, followed |
fabeltranm | 0:9b6d6fa5c401 | 43 | * by a 16-bit CRC. In our case, the data will always be 512 bytes. |
fabeltranm | 0:9b6d6fa5c401 | 44 | * |
fabeltranm | 0:9b6d6fa5c401 | 45 | * +------+---------+---------+- - - -+---------+-----------+----------+ |
fabeltranm | 0:9b6d6fa5c401 | 46 | * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] | |
fabeltranm | 0:9b6d6fa5c401 | 47 | * +------+---------+---------+- - - -+---------+-----------+----------+ |
fabeltranm | 0:9b6d6fa5c401 | 48 | */ |
fabeltranm | 0:9b6d6fa5c401 | 49 | |
fabeltranm | 0:9b6d6fa5c401 | 50 | |
fabeltranm | 0:9b6d6fa5c401 | 51 | #define SD_COMMAND_TIMEOUT 5000 |
fabeltranm | 0:9b6d6fa5c401 | 52 | |
fabeltranm | 0:9b6d6fa5c401 | 53 | #define R1_IDLE_STATE (1 << 0) |
fabeltranm | 0:9b6d6fa5c401 | 54 | #define R1_ERASE_RESET (1 << 1) |
fabeltranm | 0:9b6d6fa5c401 | 55 | #define R1_ILLEGAL_COMMAND (1 << 2) |
fabeltranm | 0:9b6d6fa5c401 | 56 | #define R1_COM_CRC_ERROR (1 << 3) |
fabeltranm | 0:9b6d6fa5c401 | 57 | #define R1_ERASE_SEQUENCE_ERROR (1 << 4) |
fabeltranm | 0:9b6d6fa5c401 | 58 | #define R1_ADDRESS_ERROR (1 << 5) |
fabeltranm | 0:9b6d6fa5c401 | 59 | #define R1_PARAMETER_ERROR (1 << 6) |
fabeltranm | 0:9b6d6fa5c401 | 60 | |
fabeltranm | 0:9b6d6fa5c401 | 61 | #define SDCARD_FAIL 0 |
fabeltranm | 0:9b6d6fa5c401 | 62 | #define SDCARD_V1 1 |
fabeltranm | 0:9b6d6fa5c401 | 63 | #define SDCARD_V2 2 |
fabeltranm | 0:9b6d6fa5c401 | 64 | #define SDCARD_V2HC 3 |
fabeltranm | 0:9b6d6fa5c401 | 65 | #define SD_DBG 0 |
fabeltranm | 0:9b6d6fa5c401 | 66 | |
fabeltranm | 0:9b6d6fa5c401 | 67 | SPI sd(PB_15, PB_14, PB_13); //miso,mosi, sclk |
fabeltranm | 0:9b6d6fa5c401 | 68 | DigitalOut ssel (PB_12); |
fabeltranm | 0:9b6d6fa5c401 | 69 | |
fabeltranm | 0:9b6d6fa5c401 | 70 | int cmd(int cmd, int arg); |
fabeltranm | 0:9b6d6fa5c401 | 71 | int cmd8(); |
fabeltranm | 0:9b6d6fa5c401 | 72 | int cmd58(); |
fabeltranm | 0:9b6d6fa5c401 | 73 | int initialise_card(); |
fabeltranm | 0:9b6d6fa5c401 | 74 | int cdv; |
fabeltranm | 0:9b6d6fa5c401 | 75 | |
fabeltranm | 0:9b6d6fa5c401 | 76 | |
fabeltranm | 0:9b6d6fa5c401 | 77 | void main () |
fabeltranm | 0:9b6d6fa5c401 | 78 | { |
fabeltranm | 0:9b6d6fa5c401 | 79 | spi.format(16, 0); |
fabeltranm | 0:9b6d6fa5c401 | 80 | sd.frequency(2); |
fabeltranm | 0:9b6d6fa5c401 | 81 | while(1) |
fabeltranm | 0:9b6d6fa5c401 | 82 | sd.write(0xAA); |
fabeltranm | 0:9b6d6fa5c401 | 83 | |
fabeltranm | 0:9b6d6fa5c401 | 84 | initialise_card(); |
fabeltranm | 0:9b6d6fa5c401 | 85 | |
fabeltranm | 0:9b6d6fa5c401 | 86 | } |
fabeltranm | 0:9b6d6fa5c401 | 87 | |
fabeltranm | 0:9b6d6fa5c401 | 88 | |
fabeltranm | 0:9b6d6fa5c401 | 89 | int cmd(int cmd, int arg) { |
fabeltranm | 0:9b6d6fa5c401 | 90 | ssel = 0; |
fabeltranm | 0:9b6d6fa5c401 | 91 | |
fabeltranm | 0:9b6d6fa5c401 | 92 | // send a command |
fabeltranm | 0:9b6d6fa5c401 | 93 | sd.write(0x40 | cmd); |
fabeltranm | 0:9b6d6fa5c401 | 94 | sd.write(arg >> 24); |
fabeltranm | 0:9b6d6fa5c401 | 95 | sd.write(arg >> 16); |
fabeltranm | 0:9b6d6fa5c401 | 96 | sd.write(arg >> 8); |
fabeltranm | 0:9b6d6fa5c401 | 97 | sd.write(arg >> 0); |
fabeltranm | 0:9b6d6fa5c401 | 98 | sd.write(0x95); |
fabeltranm | 0:9b6d6fa5c401 | 99 | |
fabeltranm | 0:9b6d6fa5c401 | 100 | // wait for the repsonse (response[7] == 0) |
fabeltranm | 0:9b6d6fa5c401 | 101 | for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { |
fabeltranm | 0:9b6d6fa5c401 | 102 | int response = sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 103 | if (!(response & 0x80)) { |
fabeltranm | 0:9b6d6fa5c401 | 104 | ssel= 1; |
fabeltranm | 0:9b6d6fa5c401 | 105 | sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 106 | return response; |
fabeltranm | 0:9b6d6fa5c401 | 107 | } |
fabeltranm | 0:9b6d6fa5c401 | 108 | } |
fabeltranm | 0:9b6d6fa5c401 | 109 | ssel = 1; |
fabeltranm | 0:9b6d6fa5c401 | 110 | sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 111 | return -1; // timeout |
fabeltranm | 0:9b6d6fa5c401 | 112 | } |
fabeltranm | 0:9b6d6fa5c401 | 113 | |
fabeltranm | 0:9b6d6fa5c401 | 114 | |
fabeltranm | 0:9b6d6fa5c401 | 115 | int initialise_card_v1() { |
fabeltranm | 0:9b6d6fa5c401 | 116 | for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { |
fabeltranm | 0:9b6d6fa5c401 | 117 | cmd(55, 0); |
fabeltranm | 0:9b6d6fa5c401 | 118 | if (cmd(41, 0) == 0) { |
fabeltranm | 0:9b6d6fa5c401 | 119 | cdv = 512; |
fabeltranm | 0:9b6d6fa5c401 | 120 | debug_if(SD_DBG, "\n\rInit: SEDCARD_V1\n\r"); |
fabeltranm | 0:9b6d6fa5c401 | 121 | return SDCARD_V1; |
fabeltranm | 0:9b6d6fa5c401 | 122 | } |
fabeltranm | 0:9b6d6fa5c401 | 123 | } |
fabeltranm | 0:9b6d6fa5c401 | 124 | |
fabeltranm | 0:9b6d6fa5c401 | 125 | debug("Timeout waiting for v1.x card\n"); |
fabeltranm | 0:9b6d6fa5c401 | 126 | return SDCARD_FAIL; |
fabeltranm | 0:9b6d6fa5c401 | 127 | } |
fabeltranm | 0:9b6d6fa5c401 | 128 | |
fabeltranm | 0:9b6d6fa5c401 | 129 | int initialise_card_v2() { |
fabeltranm | 0:9b6d6fa5c401 | 130 | for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { |
fabeltranm | 0:9b6d6fa5c401 | 131 | wait_ms(50); |
fabeltranm | 0:9b6d6fa5c401 | 132 | cmd58(); |
fabeltranm | 0:9b6d6fa5c401 | 133 | cmd(55, 0); |
fabeltranm | 0:9b6d6fa5c401 | 134 | if (cmd(41, 0x40000000) == 0) { |
fabeltranm | 0:9b6d6fa5c401 | 135 | cmd58(); |
fabeltranm | 0:9b6d6fa5c401 | 136 | debug_if(SD_DBG, "\n\rInit: SDCARD_V2\n\r"); |
fabeltranm | 0:9b6d6fa5c401 | 137 | cdv = 1; |
fabeltranm | 0:9b6d6fa5c401 | 138 | return SDCARD_V2; |
fabeltranm | 0:9b6d6fa5c401 | 139 | } |
fabeltranm | 0:9b6d6fa5c401 | 140 | } |
fabeltranm | 0:9b6d6fa5c401 | 141 | |
fabeltranm | 0:9b6d6fa5c401 | 142 | debug("Timeout waiting for v2.x card\n"); |
fabeltranm | 0:9b6d6fa5c401 | 143 | return SDCARD_FAIL; |
fabeltranm | 0:9b6d6fa5c401 | 144 | } |
fabeltranm | 0:9b6d6fa5c401 | 145 | |
fabeltranm | 0:9b6d6fa5c401 | 146 | |
fabeltranm | 0:9b6d6fa5c401 | 147 | int initialise_card() { |
fabeltranm | 0:9b6d6fa5c401 | 148 | // Set to SCK for initialisation, and clock card with cs = 1 |
fabeltranm | 0:9b6d6fa5c401 | 149 | sd.frequency(100000); |
fabeltranm | 0:9b6d6fa5c401 | 150 | ssel = 1; |
fabeltranm | 0:9b6d6fa5c401 | 151 | for (int i = 0; i < 16; i++) { |
fabeltranm | 0:9b6d6fa5c401 | 152 | sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 153 | } |
fabeltranm | 0:9b6d6fa5c401 | 154 | |
fabeltranm | 0:9b6d6fa5c401 | 155 | // send CMD0, should return with all zeros except IDLE STATE set (bit 0) |
fabeltranm | 0:9b6d6fa5c401 | 156 | if (cmd(0, 0) != R1_IDLE_STATE) { |
fabeltranm | 0:9b6d6fa5c401 | 157 | debug("No disk, or could not put SD card in to SPI idle state\n"); |
fabeltranm | 0:9b6d6fa5c401 | 158 | return SDCARD_FAIL; |
fabeltranm | 0:9b6d6fa5c401 | 159 | } |
fabeltranm | 0:9b6d6fa5c401 | 160 | |
fabeltranm | 0:9b6d6fa5c401 | 161 | // send CMD8 to determine whther it is ver 2.x |
fabeltranm | 0:9b6d6fa5c401 | 162 | int r = cmd8(); |
fabeltranm | 0:9b6d6fa5c401 | 163 | if (r == R1_IDLE_STATE) { |
fabeltranm | 0:9b6d6fa5c401 | 164 | return initialise_card_v2(); |
fabeltranm | 0:9b6d6fa5c401 | 165 | } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) { |
fabeltranm | 0:9b6d6fa5c401 | 166 | return initialise_card_v1(); |
fabeltranm | 0:9b6d6fa5c401 | 167 | } else { |
fabeltranm | 0:9b6d6fa5c401 | 168 | debug("Not in idle state after sending CMD8 (not an SD card?)\n"); |
fabeltranm | 0:9b6d6fa5c401 | 169 | return SDCARD_FAIL; |
fabeltranm | 0:9b6d6fa5c401 | 170 | } |
fabeltranm | 0:9b6d6fa5c401 | 171 | } |
fabeltranm | 0:9b6d6fa5c401 | 172 | |
fabeltranm | 0:9b6d6fa5c401 | 173 | |
fabeltranm | 0:9b6d6fa5c401 | 174 | int cmd8() { |
fabeltranm | 0:9b6d6fa5c401 | 175 | ssel = 0; |
fabeltranm | 0:9b6d6fa5c401 | 176 | |
fabeltranm | 0:9b6d6fa5c401 | 177 | // send a command |
fabeltranm | 0:9b6d6fa5c401 | 178 | sd.write(0x40 | 8); // CMD8 |
fabeltranm | 0:9b6d6fa5c401 | 179 | sd.write(0x00); // reserved |
fabeltranm | 0:9b6d6fa5c401 | 180 | sd.write(0x00); // reserved |
fabeltranm | 0:9b6d6fa5c401 | 181 | sd.write(0x01); // 3.3v |
fabeltranm | 0:9b6d6fa5c401 | 182 | sd.write(0xAA); // check pattern |
fabeltranm | 0:9b6d6fa5c401 | 183 | sd.write(0x87); // crc |
fabeltranm | 0:9b6d6fa5c401 | 184 | |
fabeltranm | 0:9b6d6fa5c401 | 185 | // wait for the repsonse (response[7] == 0) |
fabeltranm | 0:9b6d6fa5c401 | 186 | for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) { |
fabeltranm | 0:9b6d6fa5c401 | 187 | char response[5]; |
fabeltranm | 0:9b6d6fa5c401 | 188 | response[0] = sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 189 | if (!(response[0] & 0x80)) { |
fabeltranm | 0:9b6d6fa5c401 | 190 | for (int j = 1; j < 5; j++) { |
fabeltranm | 0:9b6d6fa5c401 | 191 | response[i] = sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 192 | } |
fabeltranm | 0:9b6d6fa5c401 | 193 | ssel = 1; |
fabeltranm | 0:9b6d6fa5c401 | 194 | sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 195 | return response[0]; |
fabeltranm | 0:9b6d6fa5c401 | 196 | } |
fabeltranm | 0:9b6d6fa5c401 | 197 | } |
fabeltranm | 0:9b6d6fa5c401 | 198 | ssel = 1; |
fabeltranm | 0:9b6d6fa5c401 | 199 | sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 200 | return -1; // timeout |
fabeltranm | 0:9b6d6fa5c401 | 201 | } |
fabeltranm | 0:9b6d6fa5c401 | 202 | |
fabeltranm | 0:9b6d6fa5c401 | 203 | |
fabeltranm | 0:9b6d6fa5c401 | 204 | int cmd58() { |
fabeltranm | 0:9b6d6fa5c401 | 205 | ssel = 0; |
fabeltranm | 0:9b6d6fa5c401 | 206 | int arg = 0; |
fabeltranm | 0:9b6d6fa5c401 | 207 | |
fabeltranm | 0:9b6d6fa5c401 | 208 | // send a command |
fabeltranm | 0:9b6d6fa5c401 | 209 | sd.write(0x40 | 58); |
fabeltranm | 0:9b6d6fa5c401 | 210 | sd.write(arg >> 24); |
fabeltranm | 0:9b6d6fa5c401 | 211 | sd.write(arg >> 16); |
fabeltranm | 0:9b6d6fa5c401 | 212 | sd.write(arg >> 8); |
fabeltranm | 0:9b6d6fa5c401 | 213 | sd.write(arg >> 0); |
fabeltranm | 0:9b6d6fa5c401 | 214 | sd.write(0x95); |
fabeltranm | 0:9b6d6fa5c401 | 215 | |
fabeltranm | 0:9b6d6fa5c401 | 216 | // wait for the repsonse (response[7] == 0) |
fabeltranm | 0:9b6d6fa5c401 | 217 | for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { |
fabeltranm | 0:9b6d6fa5c401 | 218 | int response = sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 219 | if (!(response & 0x80)) { |
fabeltranm | 0:9b6d6fa5c401 | 220 | int ocr = sd.write(0xFF) << 24; |
fabeltranm | 0:9b6d6fa5c401 | 221 | ocr |= sd.write(0xFF) << 16; |
fabeltranm | 0:9b6d6fa5c401 | 222 | ocr |= sd.write(0xFF) << 8; |
fabeltranm | 0:9b6d6fa5c401 | 223 | ocr |= sd.write(0xFF) << 0; |
fabeltranm | 0:9b6d6fa5c401 | 224 | ssel = 1; |
fabeltranm | 0:9b6d6fa5c401 | 225 | sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 226 | return response; |
fabeltranm | 0:9b6d6fa5c401 | 227 | } |
fabeltranm | 0:9b6d6fa5c401 | 228 | } |
fabeltranm | 0:9b6d6fa5c401 | 229 | ssel = 1; |
fabeltranm | 0:9b6d6fa5c401 | 230 | sd.write(0xFF); |
fabeltranm | 0:9b6d6fa5c401 | 231 | return -1; // timeout |
fabeltranm | 0:9b6d6fa5c401 | 232 | } |