ferney alberto beltran molina
/
00_LAB_SD_INITIAL
prueba sd card
Diff: main.cpp
- Revision:
- 0:9b6d6fa5c401
diff -r 000000000000 -r 9b6d6fa5c401 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Apr 17 23:34:09 2018 +0000 @@ -0,0 +1,232 @@ +#include "mbed.h" + /* SPI Command Format + * ------------------ + * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC. + * + * +---------------+------------+------------+-----------+----------+--------------+ + * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 | + * +---------------+------------+------------+-----------+----------+--------------+ + * + * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95) + * + * All Application Specific commands shall be preceded with APP_CMD (CMD55). + * + * SPI Response Format + * ------------------- + * The main response format (R1) is a status byte (normally zero). Key flags: + * idle - 1 if the card is in an idle state/initialising + * cmd - 1 if an illegal command code was detected + * + * +-------------------------------------------------+ + * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle | + * +-------------------------------------------------+ + * + * R1b is the same, except it is followed by a busy signal (zeros) until + * the first non-zero byte when it is ready again. + * + * Data Response Token + * ------------------- + * Every data block written to the card is acknowledged by a byte + * response token + * + * +----------------------+ + * | xxx | 0 | status | 1 | + * +----------------------+ + * 010 - OK! + * 101 - CRC Error + * 110 - Write Error + * + * Single Block Read and Write + * --------------------------- + * + * Block transfers have a byte header, followed by the data, followed + * by a 16-bit CRC. In our case, the data will always be 512 bytes. + * + * +------+---------+---------+- - - -+---------+-----------+----------+ + * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] | + * +------+---------+---------+- - - -+---------+-----------+----------+ + */ + + +#define SD_COMMAND_TIMEOUT 5000 + +#define R1_IDLE_STATE (1 << 0) +#define R1_ERASE_RESET (1 << 1) +#define R1_ILLEGAL_COMMAND (1 << 2) +#define R1_COM_CRC_ERROR (1 << 3) +#define R1_ERASE_SEQUENCE_ERROR (1 << 4) +#define R1_ADDRESS_ERROR (1 << 5) +#define R1_PARAMETER_ERROR (1 << 6) + +#define SDCARD_FAIL 0 +#define SDCARD_V1 1 +#define SDCARD_V2 2 +#define SDCARD_V2HC 3 +#define SD_DBG 0 + +SPI sd(PB_15, PB_14, PB_13); //miso,mosi, sclk +DigitalOut ssel (PB_12); + +int cmd(int cmd, int arg); +int cmd8(); +int cmd58(); +int initialise_card(); +int cdv; + + +void main () +{ + spi.format(16, 0); + sd.frequency(2); + while(1) + sd.write(0xAA); + + initialise_card(); + +} + + +int cmd(int cmd, int arg) { + ssel = 0; + + // send a command + sd.write(0x40 | cmd); + sd.write(arg >> 24); + sd.write(arg >> 16); + sd.write(arg >> 8); + sd.write(arg >> 0); + sd.write(0x95); + + // wait for the repsonse (response[7] == 0) + for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { + int response = sd.write(0xFF); + if (!(response & 0x80)) { + ssel= 1; + sd.write(0xFF); + return response; + } + } + ssel = 1; + sd.write(0xFF); + return -1; // timeout +} + + +int initialise_card_v1() { + for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { + cmd(55, 0); + if (cmd(41, 0) == 0) { + cdv = 512; + debug_if(SD_DBG, "\n\rInit: SEDCARD_V1\n\r"); + return SDCARD_V1; + } + } + + debug("Timeout waiting for v1.x card\n"); + return SDCARD_FAIL; +} + +int initialise_card_v2() { + for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { + wait_ms(50); + cmd58(); + cmd(55, 0); + if (cmd(41, 0x40000000) == 0) { + cmd58(); + debug_if(SD_DBG, "\n\rInit: SDCARD_V2\n\r"); + cdv = 1; + return SDCARD_V2; + } + } + + debug("Timeout waiting for v2.x card\n"); + return SDCARD_FAIL; +} + + +int initialise_card() { + // Set to SCK for initialisation, and clock card with cs = 1 + sd.frequency(100000); + ssel = 1; + for (int i = 0; i < 16; i++) { + sd.write(0xFF); + } + + // send CMD0, should return with all zeros except IDLE STATE set (bit 0) + if (cmd(0, 0) != R1_IDLE_STATE) { + debug("No disk, or could not put SD card in to SPI idle state\n"); + return SDCARD_FAIL; + } + + // send CMD8 to determine whther it is ver 2.x + int r = cmd8(); + if (r == R1_IDLE_STATE) { + return initialise_card_v2(); + } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) { + return initialise_card_v1(); + } else { + debug("Not in idle state after sending CMD8 (not an SD card?)\n"); + return SDCARD_FAIL; + } +} + + +int cmd8() { + ssel = 0; + + // send a command + sd.write(0x40 | 8); // CMD8 + sd.write(0x00); // reserved + sd.write(0x00); // reserved + sd.write(0x01); // 3.3v + sd.write(0xAA); // check pattern + sd.write(0x87); // crc + + // wait for the repsonse (response[7] == 0) + for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) { + char response[5]; + response[0] = sd.write(0xFF); + if (!(response[0] & 0x80)) { + for (int j = 1; j < 5; j++) { + response[i] = sd.write(0xFF); + } + ssel = 1; + sd.write(0xFF); + return response[0]; + } + } + ssel = 1; + sd.write(0xFF); + return -1; // timeout +} + + +int cmd58() { + ssel = 0; + int arg = 0; + + // send a command + sd.write(0x40 | 58); + sd.write(arg >> 24); + sd.write(arg >> 16); + sd.write(arg >> 8); + sd.write(arg >> 0); + sd.write(0x95); + + // wait for the repsonse (response[7] == 0) + for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { + int response = sd.write(0xFF); + if (!(response & 0x80)) { + int ocr = sd.write(0xFF) << 24; + ocr |= sd.write(0xFF) << 16; + ocr |= sd.write(0xFF) << 8; + ocr |= sd.write(0xFF) << 0; + ssel = 1; + sd.write(0xFF); + return response; + } + } + ssel = 1; + sd.write(0xFF); + return -1; // timeout +} \ No newline at end of file