Published 14 Dec 2009, by
Simon Ford

No tags
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 #include "SDFileSystem.h"
00099
00100 #define SD_COMMAND_TIMEOUT 5000
00101
00102 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) :
00103 FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) {
00104 _cs = 1;
00105 }
00106
00107 #define R1_IDLE_STATE (1 << 0)
00108 #define R1_ERASE_RESET (1 << 1)
00109 #define R1_ILLEGAL_COMMAND (1 << 2)
00110 #define R1_COM_CRC_ERROR (1 << 3)
00111 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
00112 #define R1_ADDRESS_ERROR (1 << 5)
00113 #define R1_PARAMETER_ERROR (1 << 6)
00114
00115 int SDFileSystem::disk_initialize() {
00116
00117 _spi.frequency(100000);
00118
00119
00120 _cs = 1;
00121 for(int i=0; i<16; i++) {
00122 _spi.write(0xFF);
00123 }
00124
00125
00126 if(_cmd(0, 0) != R1_IDLE_STATE) {
00127 fprintf(stderr, "No disk, or could not put SD card in to SPI idle state\n");
00128 return 1;
00129 }
00130
00131 int r = _cmd8();
00132 if(r == R1_IDLE_STATE) {
00133 printf("SD version 2.x\n");
00134 } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
00135 printf("SD version 1.x\n");
00136 } else {
00137 error("Unknown SD version\n");
00138 }
00139
00140
00141
00142 for(int i=0;; i++) {
00143 _cmd(55, 0);
00144 int response = _cmd(41, 0);
00145 if(response == 0) {
00146 break;
00147 } else if(i > SD_COMMAND_TIMEOUT) {
00148 fprintf(stderr, "Timeout waiting for card\n");
00149 return 1;
00150 }
00151 }
00152
00153 printf("OK\n");
00154
00155 _sectors = _sd_sectors();
00156
00157
00158 if(_cmd(16, 512) != 0) {
00159 fprintf(stderr, "Set block timeout\n");
00160 return 1;
00161 }
00162
00163 _spi.frequency(1000000);
00164 return 0;
00165 }
00166
00167 int SDFileSystem::disk_write(const char *buffer, int block_number) {
00168
00169 if(_cmd(24, block_number * 512) != 0) {
00170 return 1;
00171 }
00172
00173
00174 _write(buffer, 512);
00175 return 0;
00176 }
00177
00178 int SDFileSystem::disk_read(char *buffer, int block_number) {
00179
00180 if(_cmd(17, block_number * 512) != 0) {
00181 return 1;
00182 }
00183
00184
00185 _read(buffer, 512);
00186 return 0;
00187 }
00188
00189 int SDFileSystem::disk_status() { return 0; }
00190 int SDFileSystem::disk_sync() { return 0; }
00191 int SDFileSystem::disk_sectors() { return _sectors; }
00192
00193
00194
00195 int SDFileSystem::_cmd(int cmd, int arg) {
00196 _cs = 0;
00197
00198
00199 _spi.write(0x40 | cmd);
00200 _spi.write(arg >> 24);
00201 _spi.write(arg >> 16);
00202 _spi.write(arg >> 8);
00203 _spi.write(arg >> 0);
00204 _spi.write(0x95);
00205
00206
00207 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00208 int response = _spi.write(0xFF);
00209 if(!(response & 0x80)) {
00210 _cs = 1;
00211 _spi.write(0xFF);
00212 return response;
00213 }
00214 }
00215 _cs = 1;
00216 _spi.write(0xFF);
00217 return -1;
00218 }
00219
00220 int SDFileSystem::_cmd8() {
00221 _cs = 0;
00222
00223
00224 _spi.write(0x40 | 8);
00225 _spi.write(0x00);
00226 _spi.write(0x00);
00227 _spi.write(0x01);
00228 _spi.write(0xAA);
00229 _spi.write(0x87);
00230
00231
00232 for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
00233 char response[5];
00234 response[0] = _spi.write(0xFF);
00235 if(!(response[0] & 0x80)) {
00236 for(int j=1; j<5; j++) {
00237 response[i] = _spi.write(0xFF);
00238 }
00239 _cs = 1;
00240 _spi.write(0xFF);
00241 return response[0];
00242 }
00243 }
00244 _cs = 1;
00245 _spi.write(0xFF);
00246 return -1;
00247 }
00248
00249 int SDFileSystem::_read(char *buffer, int length) {
00250 _cs = 0;
00251
00252
00253 while(_spi.write(0xFF) != 0xFE);
00254
00255
00256 for(int i=0; i<length; i++) {
00257 buffer[i] = _spi.write(0xFF);
00258 }
00259 _spi.write(0xFF);
00260 _spi.write(0xFF);
00261
00262 _cs = 1;
00263 _spi.write(0xFF);
00264 return 0;
00265 }
00266
00267 int SDFileSystem::_write(const char *buffer, int length) {
00268 _cs = 0;
00269
00270
00271 _spi.write(0xFE);
00272
00273
00274 for(int i=0; i<length; i++) {
00275 _spi.write(buffer[i]);
00276 }
00277
00278
00279 _spi.write(0xFF);
00280 _spi.write(0xFF);
00281
00282
00283 if((_spi.write(0xFF) & 0x1F) != 0x05) {
00284 _cs = 1;
00285 _spi.write(0xFF);
00286 return 1;
00287 }
00288
00289
00290 while(_spi.write(0xFF) == 0);
00291
00292 _cs = 1;
00293 _spi.write(0xFF);
00294 return 0;
00295 }
00296
00297 static int ext_bits(char *data, int msb, int lsb) {
00298 int bits = 0;
00299 int size = 1 + msb - lsb;
00300 for(int i=0; i<size; i++) {
00301 int position = lsb + i;
00302 int byte = 15 - (position >> 3);
00303 int bit = position & 0x7;
00304 int value = (data[byte] >> bit) & 1;
00305 bits |= value << i;
00306 }
00307 return bits;
00308 }
00309
00310 int SDFileSystem::_sd_sectors() {
00311
00312
00313 if(_cmd(9, 0) != 0) {
00314 fprintf(stderr, "Didn't get a response from the disk\n");
00315 return 0;
00316 }
00317
00318 char csd[16];
00319 if(_read(csd, 16) != 0) {
00320 fprintf(stderr, "Couldn't read csd response from disk\n");
00321 return 0;
00322 }
00323
00324
00325
00326
00327
00328
00329 int csd_structure = ext_bits(csd, 127, 126);
00330 int c_size = ext_bits(csd, 73, 62);
00331 int c_size_mult = ext_bits(csd, 49, 47);
00332 int read_bl_len = ext_bits(csd, 83, 80);
00333
00334 if(csd_structure != 0) {
00335 fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures");
00336 return 0;
00337 }
00338
00339 int blocks = (c_size + 1) * (1 << (c_size_mult + 2));
00340 int block_size = 1 << read_bl_len;
00341
00342 if(block_size != 512) {
00343 fprintf(stderr, "This disk tastes funny! I only like 512-byte blocks");
00344 return 0;
00345 }
00346
00347 return blocks;
00348 }