Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Wed Jul 13 2022 11:37:04 by
1.7.2