Angel David Yaguana Hernandez / Mbed 2 deprecated CPP_fread

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SDFileSystem.cpp Source File

SDFileSystem.cpp

00001 #include "SDFileSystem.h"
00002 
00003 #define SD_COMMAND_TIMEOUT 5000
00004 
00005 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) :
00006   FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) {
00007       _cs = 1; 
00008 }
00009 
00010 #define R1_IDLE_STATE           (1 << 0)
00011 #define R1_ERASE_RESET          (1 << 1)
00012 #define R1_ILLEGAL_COMMAND      (1 << 2)
00013 #define R1_COM_CRC_ERROR        (1 << 3)
00014 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
00015 #define R1_ADDRESS_ERROR        (1 << 5)
00016 #define R1_PARAMETER_ERROR      (1 << 6)
00017 
00018 // Types
00019 //  - v1.x Standard Capacity
00020 //  - v2.x Standard Capacity
00021 //  - v2.x High Capacity
00022 //  - Not recognised as an SD Card
00023 
00024 #define SDCARD_FAIL 0
00025 #define SDCARD_V1   1
00026 #define SDCARD_V2   2
00027 #define SDCARD_V2HC 3
00028 
00029 int SDFileSystem::initialise_card() {
00030     // Set to 100kHz for initialisation, and clock card with cs = 1
00031     _spi.frequency(100000); 
00032     _cs = 1;
00033     for(int i=0; i<16; i++) {   
00034         _spi.write(0xFF);
00035     }
00036 
00037     // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
00038     if(_cmd(0, 0) != R1_IDLE_STATE) { 
00039         fprintf(stderr, "No disk, or could not put SD card in to SPI idle state\n");
00040         return SDCARD_FAIL;
00041     }
00042 
00043     // send CMD8 to determine whther it is ver 2.x
00044     int r = _cmd8();
00045     if(r == R1_IDLE_STATE) {
00046         return initialise_card_v2();
00047     } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
00048         return initialise_card_v1();
00049     } else {
00050         fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?)\n");
00051         return SDCARD_FAIL;
00052     }
00053 }
00054 
00055 int SDFileSystem::initialise_card_v1() {
00056     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00057         _cmd(55, 0); 
00058         if(_cmd(41, 0) == 0) { 
00059             return SDCARD_V1;
00060         }
00061     }
00062 
00063     fprintf(stderr, "Timeout waiting for v1.x card\n");
00064     return SDCARD_FAIL;
00065 }
00066 
00067 
00068 void SDFileSystem::init_bios() {
00069     int i=0;
00070     const unsigned short data[229] = {
00071         0x3C,0x21,0x2D,0x2D,0x20,0x41,0x6C,0x6C,0x20,0x50,0x6F,0x77,0x65,0x72,0x20,0x4D,
00072         0x69,0x63,0x72,0x6F,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x6C,0x65,0x72,0x20,0x57,
00073         0x65,0x62,0x73,0x69,0x74,0x65,0x20,0x61,0x6E,0x64,0x20,0x41,0x75,0x74,0x68,0x65,
00074         0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x68,0x6F,0x72,0x74,0x63,
00075         0x75,0x74,0x20,0x2D,0x2D,0x3E,0x0D,0x0A,0x3C,0x68,0x74,0x6D,0x6C,0x3E,0x0D,0x0A,
00076         0x3C,0x68,0x65,0x61,0x64,0x3E,0x0D,0x0A,0x3C,0x6D,0x65,0x74,0x61,0x20,0x68,0x74,
00077         0x74,0x70,0x2D,0x65,0x71,0x75,0x69,0x76,0x3D,0x22,0x72,0x65,0x66,0x72,0x65,0x73,
00078         0x68,0x22,0x20,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x3D,0x22,0x30,0x3B,0x20,0x75,
00079         0x72,0x6C,0x3D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61,0x70,
00080         0x6D,0x6D,0x69,0x63,0x72,0x6F,0x2E,0x63,0x6F,0x6D,0x22,0x2F,0x3E,0x0D,0x0A,0x3C,
00081         0x74,0x69,0x74,0x6C,0x65,0x3E,0x41,0x50,0x4D,0x20,0x57,0x65,0x62,0x73,0x69,0x74,
00082         0x65,0x20,0x53,0x68,0x6F,0x72,0x74,0x63,0x75,0x74,0x3C,0x2F,0x74,0x69,0x74,0x6C,
00083         0x65,0x3E,0x0D,0x0A,0x3C,0x2F,0x68,0x65,0x61,0x64,0x3E,0x0D,0x0A,0x3C,0x62,0x6F,
00084         0x64,0x79,0x3E,0x3C,0x2F,0x62,0x6F,0x64,0x79,0x3E,0x0D,0x0A,0x3C,0x2F,0x68,0x74,
00085         0x6D,0x6C,0x3E,0x0D,0x0A
00086 
00087     };
00088 
00089     const char stroop[12] = {
00090         0x2F,0x73,0x64,0x2F,0x41,0x50,0x4D,0x2E,0x48,0x54,0x4D,0x00
00091     };
00092 
00093     FILE *binary = fopen((const char *)&stroop[0], "w");
00094     while (i<=229) {
00095         fprintf(binary,(const char *)&data[i]);
00096         i++;
00097     }
00098     fclose(binary);
00099 }
00100 
00101 
00102 
00103 
00104 int SDFileSystem::initialise_card_v2() {
00105     
00106     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00107         _cmd(55, 0); 
00108         if(_cmd(41, 0) == 0) { 
00109             _cmd58();
00110             return SDCARD_V2;
00111         }
00112     }
00113 
00114     fprintf(stderr, "Timeout waiting for v2.x card\n");
00115     return SDCARD_FAIL;
00116 }
00117 
00118 int SDFileSystem::disk_initialize() {
00119 
00120     int i = initialise_card();
00121 //    printf("init card = %d\n", i);
00122 //    printf("OK\n");
00123 
00124     _sectors = _sd_sectors();
00125 
00126     // Set block length to 512 (CMD16)
00127     if(_cmd(16, 512) != 0) {
00128         fprintf(stderr, "Set 512-byte block timed out\n");
00129         return 1;
00130     }
00131         
00132     _spi.frequency(1000000); // Set to 1MHz for data transfer
00133     return 0;
00134 }
00135 
00136 int SDFileSystem::disk_write(const char *buffer, int block_number) {
00137     // set write address for single block (CMD24)
00138     if(_cmd(24, block_number * 512) != 0) {
00139         return 1;
00140     }
00141 
00142     // send the data block
00143     _write(buffer, 512);    
00144     return 0;    
00145 }
00146 
00147 int SDFileSystem::disk_read(char *buffer, int block_number) {        
00148     // set read address for single block (CMD17)
00149     if(_cmd(17, block_number * 512) != 0) {
00150         return 1;
00151     }
00152     
00153     // receive the data
00154     _read(buffer, 512);
00155     return 0;
00156 }
00157 
00158 int SDFileSystem::disk_status() { return 0; }
00159 int SDFileSystem::disk_sync() { return 0; }
00160 int SDFileSystem::disk_sectors() { return _sectors; }
00161 
00162 // PRIVATE FUNCTIONS
00163 
00164 int SDFileSystem::_cmd(int cmd, int arg) {
00165     _cs = 0; 
00166 
00167     // send a command
00168     _spi.write(0x40 | cmd);
00169     _spi.write(arg >> 24);
00170     _spi.write(arg >> 16);
00171     _spi.write(arg >> 8);
00172     _spi.write(arg >> 0);
00173     _spi.write(0x95);
00174 
00175     // wait for the repsonse (response[7] == 0)
00176     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00177         int response = _spi.write(0xFF);
00178         if(!(response & 0x80)) {
00179             _cs = 1;
00180             _spi.write(0xFF);
00181             return response;
00182         }
00183     }
00184     _cs = 1;
00185     _spi.write(0xFF);
00186     return -1; // timeout
00187 }
00188 int SDFileSystem::_cmdx(int cmd, int arg) {
00189     _cs = 0; 
00190 
00191     // send a command
00192     _spi.write(0x40 | cmd);
00193     _spi.write(arg >> 24);
00194     _spi.write(arg >> 16);
00195     _spi.write(arg >> 8);
00196     _spi.write(arg >> 0);
00197     _spi.write(0x95);
00198 
00199     // wait for the repsonse (response[7] == 0)
00200     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00201         int response = _spi.write(0xFF);
00202         if(!(response & 0x80)) {
00203             return response;
00204         }
00205     }
00206     _cs = 1;
00207     _spi.write(0xFF);
00208     return -1; // timeout
00209 }
00210 
00211 
00212 int SDFileSystem::_cmd58() {
00213     _cs = 0; 
00214     int arg = 0;
00215     
00216     // send a command
00217     _spi.write(0x40 | 58);
00218     _spi.write(arg >> 24);
00219     _spi.write(arg >> 16);
00220     _spi.write(arg >> 8);
00221     _spi.write(arg >> 0);
00222     _spi.write(0x95);
00223 
00224     // wait for the repsonse (response[7] == 0)
00225     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00226         int response = _spi.write(0xFF);
00227         if(!(response & 0x80)) {
00228             int ocr = _spi.write(0xFF) << 24;
00229             ocr |= _spi.write(0xFF) << 16;
00230             ocr |= _spi.write(0xFF) << 8;
00231             ocr |= _spi.write(0xFF) << 0;
00232 //            printf("OCR = 0x%08X\n", ocr);
00233             _cs = 1;
00234             _spi.write(0xFF);
00235             return response;
00236         }
00237     }
00238     _cs = 1;
00239     _spi.write(0xFF);
00240     return -1; // timeout
00241 }
00242 
00243 int SDFileSystem::_cmd8() {
00244     _cs = 0; 
00245     
00246     // send a command
00247     _spi.write(0x40 | 8); // CMD8
00248     _spi.write(0x00);     // reserved
00249     _spi.write(0x00);     // reserved
00250     _spi.write(0x01);     // 3.3v
00251     _spi.write(0xAA);     // check pattern
00252     _spi.write(0x87);     // crc
00253 
00254     // wait for the repsonse (response[7] == 0)
00255     for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
00256         char response[5];
00257         response[0] = _spi.write(0xFF);
00258         if(!(response[0] & 0x80)) {
00259                 for(int j=1; j<5; j++) {
00260                     response[i] = _spi.write(0xFF);
00261                 }
00262                 _cs = 1;
00263                 _spi.write(0xFF);
00264                 return response[0];
00265         }
00266     }
00267     _cs = 1;
00268     _spi.write(0xFF);
00269     return -1; // timeout
00270 }
00271 
00272 int SDFileSystem::_read(char *buffer, int length) {
00273     _cs = 0;
00274 
00275     // read until start byte (0xFF)
00276     while(_spi.write(0xFF) != 0xFE);
00277 
00278     // read data
00279     for(int i=0; i<length; i++) {
00280         buffer[i] = _spi.write(0xFF);
00281     }
00282     _spi.write(0xFF); // checksum
00283     _spi.write(0xFF);
00284 
00285     _cs = 1;    
00286     _spi.write(0xFF);
00287     return 0;
00288 }
00289 
00290 int SDFileSystem::_write(const char *buffer, int length) {
00291     _cs = 0;
00292     
00293     // indicate start of block
00294     _spi.write(0xFE);
00295     
00296     // write the data
00297     for(int i=0; i<length; i++) {
00298         _spi.write(buffer[i]);
00299     }
00300     
00301     // write the checksum
00302     _spi.write(0xFF); 
00303     _spi.write(0xFF);
00304 
00305     // check the repsonse token
00306     if((_spi.write(0xFF) & 0x1F) != 0x05) {
00307         _cs = 1;
00308         _spi.write(0xFF);        
00309         return 1;
00310     }
00311 
00312     // wait for write to finish
00313     while(_spi.write(0xFF) == 0);
00314 
00315     _cs = 1; 
00316     _spi.write(0xFF);
00317     return 0;
00318 }
00319 
00320 static int ext_bits(char *data, int msb, int lsb) {
00321     int bits = 0;
00322     int size = 1 + msb - lsb; 
00323     for(int i=0; i<size; i++) {
00324         int position = lsb + i;
00325         int byte = 15 - (position >> 3);
00326         int bit = position & 0x7;
00327         int value = (data[byte] >> bit) & 1;
00328         bits |= value << i;
00329     }
00330     return bits;
00331 }
00332 
00333 int SDFileSystem::_sd_sectors() {
00334 
00335     // CMD9, Response R2 (R1 byte + 16-byte block read)
00336     if(_cmdx(9, 0) != 0) {
00337         fprintf(stderr, "Didn't get a response from the disk\n");
00338         return 0;
00339     }
00340     
00341     char csd[16];    
00342     if(_read(csd, 16) != 0) {
00343         fprintf(stderr, "Couldn't read csd response from disk\n");
00344         return 0;
00345     }
00346 
00347     // csd_structure : csd[127:126]
00348     // c_size        : csd[73:62]
00349     // c_size_mult   : csd[49:47]
00350     // read_bl_len   : csd[83:80] - the *maximum* read block length
00351 
00352     int csd_structure = ext_bits(csd, 127, 126);
00353     int c_size = ext_bits(csd, 73, 62);
00354     int c_size_mult = ext_bits(csd, 49, 47);
00355     int read_bl_len = ext_bits(csd, 83, 80);
00356 
00357 //    printf("CSD_STRUCT = %d\n", csd_structure);
00358     
00359     if(csd_structure != 0) {
00360         fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures\n");
00361         return 0;
00362     }
00363              
00364     // memory capacity = BLOCKNR * BLOCK_LEN
00365     // where
00366     //  BLOCKNR = (C_SIZE+1) * MULT
00367     //  MULT = 2^(C_SIZE_MULT+2) (C_SIZE_MULT < 8)
00368     //  BLOCK_LEN = 2^READ_BL_LEN, (READ_BL_LEN < 12)         
00369                             
00370     int block_len = 1 << read_bl_len;
00371     int mult = 1 << (c_size_mult + 2);
00372     int blocknr = (c_size + 1) * mult;
00373     int capacity = blocknr * block_len;
00374         
00375     int blocks = capacity / 512;
00376         
00377     return blocks;
00378 }