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.
Fork of chan_fatfs by
diskio.cpp
00001 /*-----------------------------------------------------------------------*/ 00002 /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */ 00003 /*-----------------------------------------------------------------------*/ 00004 /* This is a stub disk I/O module that acts as front end of the existing */ 00005 /* disk I/O modules and attach it to FatFs module with common interface. */ 00006 /*-----------------------------------------------------------------------*/ 00007 00008 #include "diskio.h" 00009 #include "mbed.h" 00010 #include "mbed_debug.h" 00011 00012 00013 //****************************************************************************************************************** 00014 // MBED SPI/CS Select functions.... Modify for your layout. 00015 //************************************************************************************** 00016 00017 SPI _spi(p5, p6, p7); // mosi, miso, sclk 00018 DigitalOut _cs(p8); 00019 00020 //****************************************************************************************************************** 00021 // Low Level Sector Access Function Prototypes('C' Castrated versions of Simon Ford's C++ MBED SDFileSystem class 00022 //****************************************************************************************************************** 00023 int _cmd(int cmd, int arg); 00024 int _read(BYTE *buffer, int length); 00025 int _write(BYTE *buffer, int length); 00026 uint32_t ext_bits(BYTE *data, int msb, int lsb); 00027 int _sd_sectors(); 00028 int _sectors; 00029 int _cmd(int cmd, int arg); 00030 int _cmdx(int cmd, int arg); 00031 int _cmd8(); 00032 int _cmd58(); 00033 int cdv; 00034 00035 #define SD_COMMAND_TIMEOUT 5000 00036 00037 #define R1_IDLE_STATE (1 << 0) 00038 #define R1_ERASE_RESET (1 << 1) 00039 #define R1_ILLEGAL_COMMAND (1 << 2) 00040 #define R1_COM_CRC_ERROR (1 << 3) 00041 #define R1_ERASE_SEQUENCE_ERROR (1 << 4) 00042 #define R1_ADDRESS_ERROR (1 << 5) 00043 #define R1_PARAMETER_ERROR (1 << 6) 00044 00045 00046 //****************************************************************************************************************** 00047 // Sector Access functions for CHAN FatFs 00048 //****************************************************************************************************************** 00049 00050 DRESULT disk_ioctl ( 00051 BYTE drv, /* Physical drive nmuber (0..) */ 00052 BYTE ctrl, /* Control code */ 00053 void *buff /* Buffer to send/receive control data */ 00054 ) 00055 { 00056 DRESULT res; 00057 00058 switch(ctrl) { 00059 case CTRL_SYNC: 00060 res = RES_OK; 00061 break; 00062 00063 case GET_SECTOR_SIZE: 00064 res = RES_OK; 00065 *(WORD *)buff = 512; 00066 break; 00067 00068 case GET_SECTOR_COUNT: 00069 res = RES_OK; 00070 *(DWORD *)buff = (WORD)_sd_sectors(); 00071 break; 00072 00073 case GET_BLOCK_SIZE: 00074 res = RES_OK; 00075 *(DWORD *)buff = 1; 00076 break; 00077 00078 default: 00079 res = RES_OK; 00080 break; 00081 } 00082 return res; 00083 } 00084 00085 DSTATUS card_initialize(BYTE Drive) 00086 { 00087 // Set to 100kHz for initialisation, and clock card with cs = 1 00088 _spi.frequency(100000); 00089 _cs = 1; 00090 for (int i = 0; i < 16; i++) { 00091 _spi.write(0xFF); 00092 } 00093 00094 // send CMD0, should return with all zeros except IDLE STATE set (bit 0) 00095 if (_cmd(0, 0) != R1_IDLE_STATE) { 00096 debug("No disk, or could not put SD card in to SPI idle state\n"); 00097 return STA_NOINIT; 00098 } 00099 00100 // send CMD8 to determine whther it is ver 2.x 00101 int r = _cmd8(); 00102 if (r == R1_IDLE_STATE) { 00103 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { 00104 wait_ms(50); 00105 _cmd58(); 00106 _cmd(55, 0); 00107 if (_cmd(41, 0x40000000) == 0) { 00108 _cmd58(); 00109 //debug_if(SD_DBG, "\n\rInit: SDCARD_V2\n\r"); 00110 cdv = 1; 00111 return 0; 00112 } 00113 } 00114 debug("Timeout waiting for v2.x card\n"); 00115 return STA_NOINIT; 00116 00117 } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) { 00118 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { 00119 _cmd(55, 0); 00120 if (_cmd(41, 0) == 0) { 00121 cdv = 512; 00122 //debug_if(SD_DBG, "\n\rInit: SEDCARD_V1\n\r"); 00123 return 0; 00124 } 00125 } 00126 debug("Timeout waiting for v1.x card\n"); 00127 return STA_NOINIT; 00128 00129 } else { 00130 debug("Not in idle state after sending CMD8 (not an SD card?)\n"); 00131 return STA_NOINIT; 00132 } 00133 } 00134 00135 DSTATUS disk_initialize(BYTE Drive) 00136 { 00137 DSTATUS ret = card_initialize(Drive); 00138 00139 _sectors = _sd_sectors(); 00140 00141 // Set block length to 512 (CMD16) 00142 if (_cmd(16, 512) != 0) { 00143 debug("Set 512-byte block timed out\n"); 00144 return STA_NOINIT; 00145 } 00146 00147 _spi.frequency(10000000); // Set to 10MHz for data transfer 00148 return ret; 00149 } 00150 00151 DRESULT disk_write(BYTE Drive,const BYTE * Buffer, DWORD SectorNumber, BYTE SectorCount) 00152 { 00153 BYTE i; 00154 00155 BYTE * MyBufOut = (BYTE *)Buffer; 00156 00157 for(i=0; i<SectorCount; i++) { 00158 // set write address for single block (CMD24) 00159 if(_cmd(24, (SectorNumber + i) * 512 ) != 0) { 00160 return RES_ERROR; 00161 } 00162 00163 // send the data block 00164 _write(MyBufOut, 512); 00165 00166 MyBufOut+=512; 00167 } 00168 return RES_OK; 00169 } 00170 00171 DRESULT disk_read(BYTE Drive, BYTE * Buffer,DWORD SectorNumber, BYTE SectorCount) 00172 { 00173 BYTE i; 00174 for(i=0; i<SectorCount; i++) { 00175 // set read address for single block (CMD17) 00176 if(_cmd(17, (SectorNumber+i) * 512) != 0) { 00177 return RES_ERROR; 00178 } 00179 // receive the data 00180 _read(Buffer, 512); 00181 00182 Buffer+=512; 00183 } 00184 return RES_OK; 00185 } 00186 00187 00188 DWORD get_fattime(void) 00189 { 00190 time_t CurrentTimeStamp; 00191 tm *CurrentLocalTime; 00192 DWORD FATFSTimeCode; 00193 00194 CurrentTimeStamp = time(NULL); 00195 CurrentLocalTime = localtime(&CurrentTimeStamp); 00196 00197 //Map the tm struct time into the FatFs time code 00198 FATFSTimeCode = ((CurrentLocalTime->tm_year-80)<<25) | 00199 ((CurrentLocalTime->tm_mon+1)<<21) | 00200 ((CurrentLocalTime->tm_mday)<<16) | 00201 ((CurrentLocalTime->tm_hour)<<11) | 00202 ((CurrentLocalTime->tm_min)<<5) | 00203 ((CurrentLocalTime->tm_sec)); 00204 00205 return FATFSTimeCode; 00206 } 00207 00208 DSTATUS disk_status(BYTE Drive) 00209 { 00210 return 0; 00211 } 00212 00213 //************************************************************************************** 00214 // Low Level Sector Access Functions (Castrated versions of Simon Fords C++ MBED class 00215 //************************************************************************************** 00216 00217 int _cmd(int cmd, int arg) 00218 { 00219 _cs = 0; 00220 00221 // send a command 00222 _spi.write(0x40 | cmd); 00223 _spi.write(arg >> 24); 00224 _spi.write(arg >> 16); 00225 _spi.write(arg >> 8); 00226 _spi.write(arg >> 0); 00227 _spi.write(0x95); 00228 00229 // wait for the repsonse (response[7] == 0) 00230 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { 00231 int response = _spi.write(0xFF); 00232 if (!(response & 0x80)) { 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 int _cmdx(int cmd, int arg) 00243 { 00244 _cs = 0; 00245 00246 // send a command 00247 _spi.write(0x40 | cmd); 00248 _spi.write(arg >> 24); 00249 _spi.write(arg >> 16); 00250 _spi.write(arg >> 8); 00251 _spi.write(arg >> 0); 00252 _spi.write(0x95); 00253 00254 // wait for the repsonse (response[7] == 0) 00255 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { 00256 int response = _spi.write(0xFF); 00257 if (!(response & 0x80)) { 00258 return response; 00259 } 00260 } 00261 _cs = 1; 00262 _spi.write(0xFF); 00263 return -1; // timeout 00264 } 00265 00266 00267 int _cmd58() 00268 { 00269 _cs = 0; 00270 int arg = 0; 00271 00272 // send a command 00273 _spi.write(0x40 | 58); 00274 _spi.write(arg >> 24); 00275 _spi.write(arg >> 16); 00276 _spi.write(arg >> 8); 00277 _spi.write(arg >> 0); 00278 _spi.write(0x95); 00279 00280 // wait for the repsonse (response[7] == 0) 00281 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { 00282 int response = _spi.write(0xFF); 00283 if (!(response & 0x80)) { 00284 int ocr = _spi.write(0xFF) << 24; 00285 ocr |= _spi.write(0xFF) << 16; 00286 ocr |= _spi.write(0xFF) << 8; 00287 ocr |= _spi.write(0xFF) << 0; 00288 _cs = 1; 00289 _spi.write(0xFF); 00290 return response; 00291 } 00292 } 00293 _cs = 1; 00294 _spi.write(0xFF); 00295 return -1; // timeout 00296 } 00297 00298 int _cmd8() 00299 { 00300 _cs = 0; 00301 00302 // send a command 00303 _spi.write(0x40 | 8); // CMD8 00304 _spi.write(0x00); // reserved 00305 _spi.write(0x00); // reserved 00306 _spi.write(0x01); // 3.3v 00307 _spi.write(0xAA); // check pattern 00308 _spi.write(0x87); // crc 00309 00310 // wait for the repsonse (response[7] == 0) 00311 for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) { 00312 char response[5]; 00313 response[0] = _spi.write(0xFF); 00314 if (!(response[0] & 0x80)) { 00315 for (int j = 1; j < 5; j++) { 00316 response[i] = _spi.write(0xFF); 00317 } 00318 _cs = 1; 00319 _spi.write(0xFF); 00320 return response[0]; 00321 } 00322 } 00323 _cs = 1; 00324 _spi.write(0xFF); 00325 return -1; // timeout 00326 } 00327 int _read(BYTE *buffer, int length) 00328 { 00329 _cs = 0; 00330 00331 // read until start byte (0xFF) 00332 while (_spi.write(0xFF) != 0xFE); 00333 00334 // read data 00335 for (int i = 0; i < length; i++) { 00336 buffer[i] = _spi.write(0xFF); 00337 } 00338 _spi.write(0xFF); // checksum 00339 _spi.write(0xFF); 00340 00341 _cs = 1; 00342 _spi.write(0xFF); 00343 return 0; 00344 } 00345 00346 00347 int _write(BYTE *buffer, int length) 00348 { 00349 _cs = 0; 00350 00351 // indicate start of block 00352 _spi.write(0xFE); 00353 00354 // write the data 00355 for (int i = 0; i < length; i++) { 00356 _spi.write(buffer[i]); 00357 } 00358 00359 // write the checksum 00360 _spi.write(0xFF); 00361 _spi.write(0xFF); 00362 00363 // check the response token 00364 if ((_spi.write(0xFF) & 0x1F) != 0x05) { 00365 _cs = 1; 00366 _spi.write(0xFF); 00367 return 1; 00368 } 00369 00370 // wait for write to finish 00371 while (_spi.write(0xFF) == 0); 00372 00373 _cs = 1; 00374 _spi.write(0xFF); 00375 return 0; 00376 } 00377 00378 static uint32_t ext_bits(unsigned char *data, int msb, int lsb) 00379 { 00380 uint32_t bits = 0; 00381 uint32_t size = 1 + msb - lsb; 00382 for (int i = 0; i < size; i++) { 00383 uint32_t position = lsb + i; 00384 uint32_t byte = 15 - (position >> 3); 00385 uint32_t bit = position & 0x7; 00386 uint32_t value = (data[byte] >> bit) & 1; 00387 bits |= value << i; 00388 } 00389 return bits; 00390 } 00391 00392 int _sd_sectors() 00393 { 00394 uint32_t c_size, c_size_mult, read_bl_len; 00395 uint32_t block_len, mult, blocknr, capacity; 00396 uint32_t hc_c_size; 00397 uint64_t blocks; 00398 00399 // CMD9, Response R2 (R1 byte + 16-byte block read) 00400 if (_cmdx(9, 0) != 0) { 00401 debug("Didn't get a response from the disk\n"); 00402 return 0; 00403 } 00404 00405 uint8_t csd[16]; 00406 if (_read(csd, 16) != 0) { 00407 debug("Couldn't read csd response from disk\n"); 00408 return 0; 00409 } 00410 00411 // csd_structure : csd[127:126] 00412 // c_size : csd[73:62] 00413 // c_size_mult : csd[49:47] 00414 // read_bl_len : csd[83:80] - the *maximum* read block length 00415 00416 int csd_structure = ext_bits(csd, 127, 126); 00417 00418 switch (csd_structure) { 00419 case 0: 00420 cdv = 512; 00421 c_size = ext_bits(csd, 73, 62); 00422 c_size_mult = ext_bits(csd, 49, 47); 00423 read_bl_len = ext_bits(csd, 83, 80); 00424 00425 block_len = 1 << read_bl_len; 00426 mult = 1 << (c_size_mult + 2); 00427 blocknr = (c_size + 1) * mult; 00428 capacity = blocknr * block_len; 00429 blocks = capacity / 512; 00430 //debug_if(SD_DBG, "\n\rSDCard\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks); 00431 break; 00432 00433 case 1: 00434 cdv = 1; 00435 hc_c_size = ext_bits(csd, 63, 48); 00436 blocks = (hc_c_size+1)*1024; 00437 //debug_if(SD_DBG, "\n\rSDHC Card \n\rhc_c_size: %d\n\rcapacity: %lld \n\rsectors: %lld\n\r", hc_c_size, blocks*512, blocks); 00438 break; 00439 00440 default: 00441 debug("CSD struct unsupported\r\n"); 00442 return 0; 00443 }; 00444 return blocks; 00445 }
Generated on Fri Jul 15 2022 14:19:29 by
1.7.2
