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.
diskio.c
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 00011 00012 //****************************************************************************************************************** 00013 // MBED SPI/CS Select functions.... Modify for your layout. 00014 //************************************************************************************** 00015 00016 SPI _spi(p5, p6, p7); // mosi, miso, sclk 00017 DigitalOut _cs(p8); 00018 00019 //****************************************************************************************************************** 00020 // Low Level Sector Access Function Prototypes('C' Castrated versions of Simon Ford's C++ MBED SDFileSystem class 00021 //****************************************************************************************************************** 00022 int _cmd(int cmd, int arg); 00023 int _read(BYTE *buffer, int length); 00024 int _write(BYTE *buffer, int length); 00025 int ext_bits(BYTE *data, int msb, int lsb); 00026 int _sd_sectors(); 00027 int _sectors; 00028 00029 #define SD_COMMAND_TIMEOUT 5000 00030 00031 00032 //****************************************************************************************************************** 00033 // Sector Access functions for CHAN FatFs 00034 //****************************************************************************************************************** 00035 00036 DRESULT disk_ioctl ( 00037 BYTE drv, /* Physical drive nmuber (0..) */ 00038 BYTE ctrl, /* Control code */ 00039 void *buff /* Buffer to send/receive control data */ 00040 ) 00041 { 00042 DRESULT res; 00043 00044 switch(ctrl) 00045 { 00046 case CTRL_SYNC: 00047 res = RES_OK; 00048 break; 00049 00050 case GET_SECTOR_SIZE: 00051 res = RES_OK; 00052 *(WORD *)buff = 512; 00053 break; 00054 00055 case GET_SECTOR_COUNT: 00056 res = RES_OK; 00057 *(DWORD *)buff = (WORD)_sd_sectors(); 00058 break; 00059 00060 case GET_BLOCK_SIZE: 00061 res = RES_OK; 00062 *(DWORD *)buff = 1; 00063 break; 00064 00065 default: 00066 res = RES_OK; 00067 break; 00068 } 00069 return res; 00070 } 00071 00072 DSTATUS disk_initialize(BYTE Drive) { 00073 00074 _spi.frequency(100000); // Set to 100kHz for initialisation 00075 00076 // Initialise the card by clocking it a bit (cs = 1) 00077 for(int i=0; i<16; i++) { 00078 _spi.write(0xFF); 00079 } 00080 00081 // send CMD0, should return with all zeros except IDLE STATE set (bit 0) 00082 if(_cmd(0, 0) != 0x01) { 00083 fprintf(stderr, "Not in idle state\n"); 00084 return STA_NOINIT; 00085 } 00086 00087 // ACMD41 to give host capacity support (repeat until not busy) 00088 // ACMD41 is application specific command, so we send APP_CMD (CMD55) beforehand 00089 for(int i=0;; i++) { 00090 _cmd(55, 0); 00091 int response = _cmd(41, 0); 00092 if(response == 0) { 00093 break; 00094 } else if(i > SD_COMMAND_TIMEOUT) { 00095 fprintf(stderr, "Timeout waiting for card\n"); 00096 return STA_NOINIT; 00097 } 00098 } 00099 00100 _sectors = _sd_sectors(); 00101 00102 // Set block length to 512 (CMD16) 00103 if(_cmd(16, 512) != 0) { 00104 fprintf(stderr, "Set block timeout\n"); 00105 return STA_NOINIT; 00106 } 00107 00108 _spi.frequency(10000000); // Set to 10MHz for data transfer 00109 return 0; 00110 } 00111 00112 DRESULT disk_write(BYTE Drive,const BYTE * Buffer, DWORD SectorNumber, BYTE SectorCount) 00113 { 00114 BYTE i; 00115 00116 BYTE * MyBufOut = (BYTE *)Buffer; 00117 00118 for(i=0;i<SectorCount;i++) 00119 { 00120 // set write address for single block (CMD24) 00121 if(_cmd(24, (SectorNumber + i) * 512 ) != 0) { 00122 return RES_ERROR; 00123 } 00124 00125 // send the data block 00126 _write(MyBufOut, 512); 00127 00128 MyBufOut+=512; 00129 } 00130 return RES_OK; 00131 } 00132 00133 DRESULT disk_read(BYTE Drive, BYTE * Buffer,DWORD SectorNumber, BYTE SectorCount) 00134 { 00135 BYTE i; 00136 for(i=0;i<SectorCount;i++) 00137 { 00138 // set read address for single block (CMD17) 00139 if(_cmd(17, (SectorNumber+i) * 512) != 0) 00140 { 00141 return RES_ERROR; 00142 } 00143 // receive the data 00144 _read(Buffer, 512); 00145 00146 Buffer+=512; 00147 } 00148 return RES_OK; 00149 } 00150 00151 00152 DWORD get_fattime(void) 00153 { 00154 time_t CurrentTimeStamp; 00155 tm *CurrentLocalTime; 00156 DWORD FATFSTimeCode; 00157 00158 CurrentTimeStamp = time(NULL); 00159 CurrentLocalTime = localtime(&CurrentTimeStamp); 00160 00161 //Map the tm struct time into the FatFs time code 00162 FATFSTimeCode = ((CurrentLocalTime->tm_year-80)<<25) | 00163 ((CurrentLocalTime->tm_mon+1)<<21) | 00164 ((CurrentLocalTime->tm_mday)<<16) | 00165 ((CurrentLocalTime->tm_hour)<<11) | 00166 ((CurrentLocalTime->tm_min)<<5) | 00167 ((CurrentLocalTime->tm_sec)); 00168 00169 return FATFSTimeCode; 00170 } 00171 00172 DSTATUS disk_status(BYTE Drive) 00173 { 00174 return 0; 00175 } 00176 00177 //************************************************************************************** 00178 // Low Level Sector Access Functions (Castrated versions of Simon Fords C++ MBED class 00179 //************************************************************************************** 00180 00181 int _cmd(int cmd, int arg) { 00182 _cs = 0; 00183 00184 // send a command 00185 _spi.write(0x40 | cmd); 00186 _spi.write(arg >> 24); 00187 _spi.write(arg >> 16); 00188 _spi.write(arg >> 8); 00189 _spi.write(arg >> 0); 00190 _spi.write(0x95); 00191 00192 // wait for the repsonse (response[7] == 0) 00193 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { 00194 int response = _spi.write(0xFF); 00195 if(!(response & 0x80)) { 00196 _cs = 1; 00197 return response; 00198 } 00199 } 00200 _cs = 1; 00201 return -1; // timeout 00202 } 00203 00204 int _read(BYTE *buffer, int length) { 00205 _cs = 0; 00206 00207 // read until start byte (0xFF) 00208 while(_spi.write(0xFF) != 0xFE); 00209 00210 // read data 00211 for(int i=0; i<length; i++) { 00212 buffer[i] = _spi.write(0xFF); 00213 } 00214 _spi.write(0xFF); // checksum 00215 _spi.write(0xFF); 00216 00217 _cs = 1; 00218 return 0; 00219 } 00220 00221 int _write(BYTE *buffer, int length) { 00222 _cs = 0; 00223 00224 // indicate start of block 00225 _spi.write(0xFE); 00226 00227 // write the data 00228 for(int i=0; i<length; i++) { 00229 _spi.write(buffer[i]); 00230 } 00231 00232 // write the checksum 00233 _spi.write(0xFF); 00234 _spi.write(0xFF); 00235 00236 // check the repsonse token 00237 if((_spi.write(0xFF) & 0x1F) != 0x05) { 00238 _cs = 1; 00239 return 1; 00240 } 00241 00242 // wait for write to finish 00243 while(_spi.write(0xFF) == 0); 00244 00245 _cs = 1; 00246 return 0; 00247 } 00248 00249 int ext_bits(BYTE *data, int msb, int lsb) { 00250 int bits = 0; 00251 int size = 1 + msb - lsb; 00252 for(int i=0; i<size; i++) { 00253 int position = lsb + i; 00254 int byte = 15 - (position >> 3); 00255 int bit = position & 0x7; 00256 int value = (data[byte] >> bit) & 1; 00257 bits |= value << i; 00258 } 00259 return bits; 00260 } 00261 00262 int _sd_sectors() { 00263 00264 // CMD9, Response R2 (R1 byte + 16-byte block read) 00265 if(_cmd(9, 0) != 0) { 00266 fprintf(stderr, "Didn't get a response from the disk\n"); 00267 return 0; 00268 } 00269 00270 BYTE csd[16]; 00271 if(_read(csd, 16) != 0) { 00272 fprintf(stderr, "Couldn't read csd response from disk\n"); 00273 return 0; 00274 } 00275 00276 // csd_structure : csd[127:126] 00277 // c_size : csd[73:62] 00278 // c_size_mult : csd[49:47] 00279 // read_bl_len : csd[83:80] 00280 00281 int csd_structure = ext_bits(csd, 127, 126); 00282 int c_size = ext_bits(csd, 73, 62); 00283 int c_size_mult = ext_bits(csd, 49, 47); 00284 int read_bl_len = ext_bits(csd, 83, 80); 00285 00286 if(csd_structure != 0) { 00287 fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures"); 00288 return 0; 00289 } 00290 00291 int blocks = (c_size + 1) * (1 << (c_size_mult + 2)); 00292 int block_size = 1 << read_bl_len; 00293 00294 if(block_size != 512) { 00295 fprintf(stderr, "This disk tastes funny! I only like 512 byte blocks (%d)\r\n",block_size); 00296 return 0; 00297 } 00298 00299 return blocks; 00300 }
Generated on Thu Jul 14 2022 09:05:34 by
1.7.2