Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
simon
Date:
Thu Dec 31 15:11:08 2009 +0000
Parent:
2:849162a1207f
Commit message:

Changed in this revision

SDFileSystem.cpp Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 849162a1207f -r 68ef62208d4d SDFileSystem.cpp
--- 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;
 }
diff -r 849162a1207f -r 68ef62208d4d SDFileSystem.h
--- 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);
diff -r 849162a1207f -r 68ef62208d4d main.cpp
--- 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");