Revision 3:68ef62208d4d, committed 2009-12-31
- Comitter:
- simon
- Date:
- Thu Dec 31 15:11:08 2009 +0000
- Parent:
- 2:849162a1207f
- Commit message:
Changed in this revision
--- a/SDFileSystem.cpp Mon Dec 14 22:32:28 2009 +0000
+++ b/SDFileSystem.cpp Thu Dec 31 15:11:08 2009 +0000
@@ -1,7 +1,10 @@
/* mbed Microcontroller Library - SDFileSystem
* Copyright (c) 2008-2009, sford
- *
- * Introduction
+ */
+
+// VERY DRAFT CODE! Needs serious rework/refactoring
+
+/* Introduction
* ------------
* SD and MMC cards support a number of interfaces, but common to them all
* is one based on SPI. This is the one I'm implmenting because it means
@@ -112,11 +115,20 @@
#define R1_ADDRESS_ERROR (1 << 5)
#define R1_PARAMETER_ERROR (1 << 6)
-int SDFileSystem::disk_initialize() {
+// Types
+// - v1.x Standard Capacity
+// - v2.x Standard Capacity
+// - v2.x High Capacity
+// - Not recognised as an SD Card
- _spi.frequency(100000); // Set to 100kHz for initialisation
-
- // Initialise the card by clocking it with cs = 1
+#define SDCARD_FAIL 0
+#define SDCARD_V1 1
+#define SDCARD_V2 2
+#define SDCARD_V2HC 3
+
+int SDFileSystem::initialise_card() {
+ // Set to 100kHz for initialisation, and clock card with cs = 1
+ _spi.frequency(100000);
_cs = 1;
for(int i=0; i<16; i++) {
_spi.write(0xFF);
@@ -125,38 +137,58 @@
// send CMD0, should return with all zeros except IDLE STATE set (bit 0)
if(_cmd(0, 0) != R1_IDLE_STATE) {
fprintf(stderr, "No disk, or could not put SD card in to SPI idle state\n");
- return 1;
+ return SDCARD_FAIL;
}
+ // send CMD8 to determine whther it is ver 2.x
int r = _cmd8();
if(r == R1_IDLE_STATE) {
- printf("SD version 2.x\n");
+ return initialise_card_v2();
} else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
- printf("SD version 1.x\n");
+ return initialise_card_v1();
} else {
- error("Unknown SD version\n");
+ fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?)\n");
+ return SDCARD_FAIL;
}
-
- // ACMD41 to give host capacity support (repeat until not busy)
- // ACMD41 is application specific command, so we send APP_CMD (CMD55) beforehand
- for(int i=0;; i++) {
+}
+
+int SDFileSystem::initialise_card_v1() {
+ for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
_cmd(55, 0);
- int response = _cmd(41, 0);
- if(response == 0) {
- break;
- } else if(i > SD_COMMAND_TIMEOUT) {
- fprintf(stderr, "Timeout waiting for card\n");
- return 1;
- }
+ if(_cmd(41, 0) == 0) {
+ return SDCARD_V1;
+ }
}
- printf("OK\n");
+ fprintf(stderr, "Timeout waiting for v1.x card\n");
+ return SDCARD_FAIL;
+}
+
+int SDFileSystem::initialise_card_v2() {
+
+ for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+ _cmd(55, 0);
+ if(_cmd(41, 0) == 0) {
+ _cmd58();
+ return SDCARD_V2;
+ }
+ }
+
+ fprintf(stderr, "Timeout waiting for v2.x card\n");
+ return SDCARD_FAIL;
+}
+
+int SDFileSystem::disk_initialize() {
+
+ int i = initialise_card();
+// printf("init card = %d\n", i);
+// printf("OK\n");
_sectors = _sd_sectors();
// Set block length to 512 (CMD16)
if(_cmd(16, 512) != 0) {
- fprintf(stderr, "Set block timeout\n");
+ fprintf(stderr, "Set 512-byte block timed out\n");
return 1;
}
@@ -216,6 +248,60 @@
_spi.write(0xFF);
return -1; // timeout
}
+int SDFileSystem::_cmdx(int cmd, int arg) {
+ _cs = 0;
+
+ // send a command
+ _spi.write(0x40 | cmd);
+ _spi.write(arg >> 24);
+ _spi.write(arg >> 16);
+ _spi.write(arg >> 8);
+ _spi.write(arg >> 0);
+ _spi.write(0x95);
+
+ // wait for the repsonse (response[7] == 0)
+ for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+ int response = _spi.write(0xFF);
+ if(!(response & 0x80)) {
+ return response;
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
+
+
+int SDFileSystem::_cmd58() {
+ _cs = 0;
+ int arg = 0;
+
+ // send a command
+ _spi.write(0x40 | 58);
+ _spi.write(arg >> 24);
+ _spi.write(arg >> 16);
+ _spi.write(arg >> 8);
+ _spi.write(arg >> 0);
+ _spi.write(0x95);
+
+ // wait for the repsonse (response[7] == 0)
+ for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+ int response = _spi.write(0xFF);
+ if(!(response & 0x80)) {
+ int ocr = _spi.write(0xFF) << 24;
+ ocr |= _spi.write(0xFF) << 16;
+ ocr |= _spi.write(0xFF) << 8;
+ ocr |= _spi.write(0xFF) << 0;
+// printf("OCR = 0x%08X\n", ocr);
+ _cs = 1;
+ _spi.write(0xFF);
+ return response;
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
int SDFileSystem::_cmd8() {
_cs = 0;
@@ -310,7 +396,7 @@
int SDFileSystem::_sd_sectors() {
// CMD9, Response R2 (R1 byte + 16-byte block read)
- if(_cmd(9, 0) != 0) {
+ if(_cmdx(9, 0) != 0) {
fprintf(stderr, "Didn't get a response from the disk\n");
return 0;
}
@@ -324,25 +410,32 @@
// csd_structure : csd[127:126]
// c_size : csd[73:62]
// c_size_mult : csd[49:47]
- // read_bl_len : csd[83:80]
+ // read_bl_len : csd[83:80] - the *maximum* read block length
int csd_structure = ext_bits(csd, 127, 126);
int c_size = ext_bits(csd, 73, 62);
int c_size_mult = ext_bits(csd, 49, 47);
int read_bl_len = ext_bits(csd, 83, 80);
+
+// printf("CSD_STRUCT = %d\n", csd_structure);
if(csd_structure != 0) {
- fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures");
+ fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures\n");
return 0;
}
+
+ // memory capacity = BLOCKNR * BLOCK_LEN
+ // where
+ // BLOCKNR = (C_SIZE+1) * MULT
+ // MULT = 2^(C_SIZE_MULT+2) (C_SIZE_MULT < 8)
+ // BLOCK_LEN = 2^READ_BL_LEN, (READ_BL_LEN < 12)
- int blocks = (c_size + 1) * (1 << (c_size_mult + 2));
- int block_size = 1 << read_bl_len;
-
- if(block_size != 512) {
- fprintf(stderr, "This disk tastes funny! I only like 512-byte blocks");
- return 0;
- }
-
+ int block_len = 1 << read_bl_len;
+ int mult = 1 << (c_size_mult + 2);
+ int blocknr = (c_size + 1) * mult;
+ int capacity = blocknr * block_len;
+
+ int blocks = capacity / 512;
+
return blocks;
}
--- a/SDFileSystem.h Mon Dec 14 22:32:28 2009 +0000
+++ b/SDFileSystem.h Thu Dec 31 15:11:08 2009 +0000
@@ -1,6 +1,8 @@
/* mbed Microcontroller Library - SDFileSystem
* Copyright (c) 2008-2009, sford
*/
+
+// VERY DRAFT CODE!!!
#ifndef SDFILESYSTEM_H
#define SDFILESYSTEM_H
@@ -44,7 +46,13 @@
protected:
int _cmd(int cmd, int arg);
+ int _cmdx(int cmd, int arg);
int _cmd8();
+ int _cmd58();
+ int initialise_card();
+ int initialise_card_v1();
+ int initialise_card_v2();
+
int _read(char *buffer, int length);
int _write(const char *buffer, int length);
--- a/main.cpp Mon Dec 14 22:32:28 2009 +0000
+++ b/main.cpp Thu Dec 31 15:11:08 2009 +0000
@@ -10,7 +10,7 @@
if(fp == NULL) {
error("Could not open file for write\n");
}
- fprintf(fp, "Hello SD Card World!");
+ fprintf(fp, "Hello fun SD Card World!");
fclose(fp);
printf("Goodbye World!\n");