test

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers diskio.c Source File

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 }