test
diskio.c@1:68378811b1e2, 2011-01-10 (annotated)
- Committer:
- emh203
- Date:
- Mon Jan 10 15:02:22 2011 +0000
- Revision:
- 1:68378811b1e2
test
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
emh203 | 1:68378811b1e2 | 1 | /*-----------------------------------------------------------------------*/ |
emh203 | 1:68378811b1e2 | 2 | /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */ |
emh203 | 1:68378811b1e2 | 3 | /*-----------------------------------------------------------------------*/ |
emh203 | 1:68378811b1e2 | 4 | /* This is a stub disk I/O module that acts as front end of the existing */ |
emh203 | 1:68378811b1e2 | 5 | /* disk I/O modules and attach it to FatFs module with common interface. */ |
emh203 | 1:68378811b1e2 | 6 | /*-----------------------------------------------------------------------*/ |
emh203 | 1:68378811b1e2 | 7 | |
emh203 | 1:68378811b1e2 | 8 | #include "diskio.h" |
emh203 | 1:68378811b1e2 | 9 | #include "mbed.h" |
emh203 | 1:68378811b1e2 | 10 | |
emh203 | 1:68378811b1e2 | 11 | |
emh203 | 1:68378811b1e2 | 12 | //****************************************************************************************************************** |
emh203 | 1:68378811b1e2 | 13 | // MBED SPI/CS Select functions.... Modify for your layout. |
emh203 | 1:68378811b1e2 | 14 | //************************************************************************************** |
emh203 | 1:68378811b1e2 | 15 | |
emh203 | 1:68378811b1e2 | 16 | SPI _spi(p5, p6, p7); // mosi, miso, sclk |
emh203 | 1:68378811b1e2 | 17 | DigitalOut _cs(p8); |
emh203 | 1:68378811b1e2 | 18 | |
emh203 | 1:68378811b1e2 | 19 | //****************************************************************************************************************** |
emh203 | 1:68378811b1e2 | 20 | // Low Level Sector Access Function Prototypes('C' Castrated versions of Simon Ford's C++ MBED SDFileSystem class |
emh203 | 1:68378811b1e2 | 21 | //****************************************************************************************************************** |
emh203 | 1:68378811b1e2 | 22 | int _cmd(int cmd, int arg); |
emh203 | 1:68378811b1e2 | 23 | int _read(BYTE *buffer, int length); |
emh203 | 1:68378811b1e2 | 24 | int _write(BYTE *buffer, int length); |
emh203 | 1:68378811b1e2 | 25 | int ext_bits(BYTE *data, int msb, int lsb); |
emh203 | 1:68378811b1e2 | 26 | int _sd_sectors(); |
emh203 | 1:68378811b1e2 | 27 | int _sectors; |
emh203 | 1:68378811b1e2 | 28 | |
emh203 | 1:68378811b1e2 | 29 | #define SD_COMMAND_TIMEOUT 5000 |
emh203 | 1:68378811b1e2 | 30 | |
emh203 | 1:68378811b1e2 | 31 | |
emh203 | 1:68378811b1e2 | 32 | //****************************************************************************************************************** |
emh203 | 1:68378811b1e2 | 33 | // Sector Access functions for CHAN FatFs |
emh203 | 1:68378811b1e2 | 34 | //****************************************************************************************************************** |
emh203 | 1:68378811b1e2 | 35 | |
emh203 | 1:68378811b1e2 | 36 | DRESULT disk_ioctl ( |
emh203 | 1:68378811b1e2 | 37 | BYTE drv, /* Physical drive nmuber (0..) */ |
emh203 | 1:68378811b1e2 | 38 | BYTE ctrl, /* Control code */ |
emh203 | 1:68378811b1e2 | 39 | void *buff /* Buffer to send/receive control data */ |
emh203 | 1:68378811b1e2 | 40 | ) |
emh203 | 1:68378811b1e2 | 41 | { |
emh203 | 1:68378811b1e2 | 42 | DRESULT res; |
emh203 | 1:68378811b1e2 | 43 | |
emh203 | 1:68378811b1e2 | 44 | switch(ctrl) |
emh203 | 1:68378811b1e2 | 45 | { |
emh203 | 1:68378811b1e2 | 46 | case CTRL_SYNC: |
emh203 | 1:68378811b1e2 | 47 | res = RES_OK; |
emh203 | 1:68378811b1e2 | 48 | break; |
emh203 | 1:68378811b1e2 | 49 | |
emh203 | 1:68378811b1e2 | 50 | case GET_SECTOR_SIZE: |
emh203 | 1:68378811b1e2 | 51 | res = RES_OK; |
emh203 | 1:68378811b1e2 | 52 | *(WORD *)buff = 512; |
emh203 | 1:68378811b1e2 | 53 | break; |
emh203 | 1:68378811b1e2 | 54 | |
emh203 | 1:68378811b1e2 | 55 | case GET_SECTOR_COUNT: |
emh203 | 1:68378811b1e2 | 56 | res = RES_OK; |
emh203 | 1:68378811b1e2 | 57 | *(DWORD *)buff = (WORD)_sd_sectors(); |
emh203 | 1:68378811b1e2 | 58 | break; |
emh203 | 1:68378811b1e2 | 59 | |
emh203 | 1:68378811b1e2 | 60 | case GET_BLOCK_SIZE: |
emh203 | 1:68378811b1e2 | 61 | res = RES_OK; |
emh203 | 1:68378811b1e2 | 62 | *(DWORD *)buff = 1; |
emh203 | 1:68378811b1e2 | 63 | break; |
emh203 | 1:68378811b1e2 | 64 | |
emh203 | 1:68378811b1e2 | 65 | default: |
emh203 | 1:68378811b1e2 | 66 | res = RES_OK; |
emh203 | 1:68378811b1e2 | 67 | break; |
emh203 | 1:68378811b1e2 | 68 | } |
emh203 | 1:68378811b1e2 | 69 | return res; |
emh203 | 1:68378811b1e2 | 70 | } |
emh203 | 1:68378811b1e2 | 71 | |
emh203 | 1:68378811b1e2 | 72 | DSTATUS disk_initialize(BYTE Drive) { |
emh203 | 1:68378811b1e2 | 73 | |
emh203 | 1:68378811b1e2 | 74 | _spi.frequency(100000); // Set to 100kHz for initialisation |
emh203 | 1:68378811b1e2 | 75 | |
emh203 | 1:68378811b1e2 | 76 | // Initialise the card by clocking it a bit (cs = 1) |
emh203 | 1:68378811b1e2 | 77 | for(int i=0; i<16; i++) { |
emh203 | 1:68378811b1e2 | 78 | _spi.write(0xFF); |
emh203 | 1:68378811b1e2 | 79 | } |
emh203 | 1:68378811b1e2 | 80 | |
emh203 | 1:68378811b1e2 | 81 | // send CMD0, should return with all zeros except IDLE STATE set (bit 0) |
emh203 | 1:68378811b1e2 | 82 | if(_cmd(0, 0) != 0x01) { |
emh203 | 1:68378811b1e2 | 83 | fprintf(stderr, "Not in idle state\n"); |
emh203 | 1:68378811b1e2 | 84 | return STA_NOINIT; |
emh203 | 1:68378811b1e2 | 85 | } |
emh203 | 1:68378811b1e2 | 86 | |
emh203 | 1:68378811b1e2 | 87 | // ACMD41 to give host capacity support (repeat until not busy) |
emh203 | 1:68378811b1e2 | 88 | // ACMD41 is application specific command, so we send APP_CMD (CMD55) beforehand |
emh203 | 1:68378811b1e2 | 89 | for(int i=0;; i++) { |
emh203 | 1:68378811b1e2 | 90 | _cmd(55, 0); |
emh203 | 1:68378811b1e2 | 91 | int response = _cmd(41, 0); |
emh203 | 1:68378811b1e2 | 92 | if(response == 0) { |
emh203 | 1:68378811b1e2 | 93 | break; |
emh203 | 1:68378811b1e2 | 94 | } else if(i > SD_COMMAND_TIMEOUT) { |
emh203 | 1:68378811b1e2 | 95 | fprintf(stderr, "Timeout waiting for card\n"); |
emh203 | 1:68378811b1e2 | 96 | return STA_NOINIT; |
emh203 | 1:68378811b1e2 | 97 | } |
emh203 | 1:68378811b1e2 | 98 | } |
emh203 | 1:68378811b1e2 | 99 | |
emh203 | 1:68378811b1e2 | 100 | _sectors = _sd_sectors(); |
emh203 | 1:68378811b1e2 | 101 | |
emh203 | 1:68378811b1e2 | 102 | // Set block length to 512 (CMD16) |
emh203 | 1:68378811b1e2 | 103 | if(_cmd(16, 512) != 0) { |
emh203 | 1:68378811b1e2 | 104 | fprintf(stderr, "Set block timeout\n"); |
emh203 | 1:68378811b1e2 | 105 | return STA_NOINIT; |
emh203 | 1:68378811b1e2 | 106 | } |
emh203 | 1:68378811b1e2 | 107 | |
emh203 | 1:68378811b1e2 | 108 | _spi.frequency(10000000); // Set to 10MHz for data transfer |
emh203 | 1:68378811b1e2 | 109 | return 0; |
emh203 | 1:68378811b1e2 | 110 | } |
emh203 | 1:68378811b1e2 | 111 | |
emh203 | 1:68378811b1e2 | 112 | DRESULT disk_write(BYTE Drive,const BYTE * Buffer, DWORD SectorNumber, BYTE SectorCount) |
emh203 | 1:68378811b1e2 | 113 | { |
emh203 | 1:68378811b1e2 | 114 | BYTE i; |
emh203 | 1:68378811b1e2 | 115 | |
emh203 | 1:68378811b1e2 | 116 | BYTE * MyBufOut = (BYTE *)Buffer; |
emh203 | 1:68378811b1e2 | 117 | |
emh203 | 1:68378811b1e2 | 118 | for(i=0;i<SectorCount;i++) |
emh203 | 1:68378811b1e2 | 119 | { |
emh203 | 1:68378811b1e2 | 120 | // set write address for single block (CMD24) |
emh203 | 1:68378811b1e2 | 121 | if(_cmd(24, (SectorNumber + i) * 512 ) != 0) { |
emh203 | 1:68378811b1e2 | 122 | return RES_ERROR; |
emh203 | 1:68378811b1e2 | 123 | } |
emh203 | 1:68378811b1e2 | 124 | |
emh203 | 1:68378811b1e2 | 125 | // send the data block |
emh203 | 1:68378811b1e2 | 126 | _write(MyBufOut, 512); |
emh203 | 1:68378811b1e2 | 127 | |
emh203 | 1:68378811b1e2 | 128 | MyBufOut+=512; |
emh203 | 1:68378811b1e2 | 129 | } |
emh203 | 1:68378811b1e2 | 130 | return RES_OK; |
emh203 | 1:68378811b1e2 | 131 | } |
emh203 | 1:68378811b1e2 | 132 | |
emh203 | 1:68378811b1e2 | 133 | DRESULT disk_read(BYTE Drive, BYTE * Buffer,DWORD SectorNumber, BYTE SectorCount) |
emh203 | 1:68378811b1e2 | 134 | { |
emh203 | 1:68378811b1e2 | 135 | BYTE i; |
emh203 | 1:68378811b1e2 | 136 | for(i=0;i<SectorCount;i++) |
emh203 | 1:68378811b1e2 | 137 | { |
emh203 | 1:68378811b1e2 | 138 | // set read address for single block (CMD17) |
emh203 | 1:68378811b1e2 | 139 | if(_cmd(17, (SectorNumber+i) * 512) != 0) |
emh203 | 1:68378811b1e2 | 140 | { |
emh203 | 1:68378811b1e2 | 141 | return RES_ERROR; |
emh203 | 1:68378811b1e2 | 142 | } |
emh203 | 1:68378811b1e2 | 143 | // receive the data |
emh203 | 1:68378811b1e2 | 144 | _read(Buffer, 512); |
emh203 | 1:68378811b1e2 | 145 | |
emh203 | 1:68378811b1e2 | 146 | Buffer+=512; |
emh203 | 1:68378811b1e2 | 147 | } |
emh203 | 1:68378811b1e2 | 148 | return RES_OK; |
emh203 | 1:68378811b1e2 | 149 | } |
emh203 | 1:68378811b1e2 | 150 | |
emh203 | 1:68378811b1e2 | 151 | |
emh203 | 1:68378811b1e2 | 152 | DWORD get_fattime(void) |
emh203 | 1:68378811b1e2 | 153 | { |
emh203 | 1:68378811b1e2 | 154 | time_t CurrentTimeStamp; |
emh203 | 1:68378811b1e2 | 155 | tm *CurrentLocalTime; |
emh203 | 1:68378811b1e2 | 156 | DWORD FATFSTimeCode; |
emh203 | 1:68378811b1e2 | 157 | |
emh203 | 1:68378811b1e2 | 158 | CurrentTimeStamp = time(NULL); |
emh203 | 1:68378811b1e2 | 159 | CurrentLocalTime = localtime(&CurrentTimeStamp); |
emh203 | 1:68378811b1e2 | 160 | |
emh203 | 1:68378811b1e2 | 161 | //Map the tm struct time into the FatFs time code |
emh203 | 1:68378811b1e2 | 162 | FATFSTimeCode = ((CurrentLocalTime->tm_year-80)<<25) | |
emh203 | 1:68378811b1e2 | 163 | ((CurrentLocalTime->tm_mon+1)<<21) | |
emh203 | 1:68378811b1e2 | 164 | ((CurrentLocalTime->tm_mday)<<16) | |
emh203 | 1:68378811b1e2 | 165 | ((CurrentLocalTime->tm_hour)<<11) | |
emh203 | 1:68378811b1e2 | 166 | ((CurrentLocalTime->tm_min)<<5) | |
emh203 | 1:68378811b1e2 | 167 | ((CurrentLocalTime->tm_sec)); |
emh203 | 1:68378811b1e2 | 168 | |
emh203 | 1:68378811b1e2 | 169 | return FATFSTimeCode; |
emh203 | 1:68378811b1e2 | 170 | } |
emh203 | 1:68378811b1e2 | 171 | |
emh203 | 1:68378811b1e2 | 172 | DSTATUS disk_status(BYTE Drive) |
emh203 | 1:68378811b1e2 | 173 | { |
emh203 | 1:68378811b1e2 | 174 | return 0; |
emh203 | 1:68378811b1e2 | 175 | } |
emh203 | 1:68378811b1e2 | 176 | |
emh203 | 1:68378811b1e2 | 177 | //************************************************************************************** |
emh203 | 1:68378811b1e2 | 178 | // Low Level Sector Access Functions (Castrated versions of Simon Fords C++ MBED class |
emh203 | 1:68378811b1e2 | 179 | //************************************************************************************** |
emh203 | 1:68378811b1e2 | 180 | |
emh203 | 1:68378811b1e2 | 181 | int _cmd(int cmd, int arg) { |
emh203 | 1:68378811b1e2 | 182 | _cs = 0; |
emh203 | 1:68378811b1e2 | 183 | |
emh203 | 1:68378811b1e2 | 184 | // send a command |
emh203 | 1:68378811b1e2 | 185 | _spi.write(0x40 | cmd); |
emh203 | 1:68378811b1e2 | 186 | _spi.write(arg >> 24); |
emh203 | 1:68378811b1e2 | 187 | _spi.write(arg >> 16); |
emh203 | 1:68378811b1e2 | 188 | _spi.write(arg >> 8); |
emh203 | 1:68378811b1e2 | 189 | _spi.write(arg >> 0); |
emh203 | 1:68378811b1e2 | 190 | _spi.write(0x95); |
emh203 | 1:68378811b1e2 | 191 | |
emh203 | 1:68378811b1e2 | 192 | // wait for the repsonse (response[7] == 0) |
emh203 | 1:68378811b1e2 | 193 | for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { |
emh203 | 1:68378811b1e2 | 194 | int response = _spi.write(0xFF); |
emh203 | 1:68378811b1e2 | 195 | if(!(response & 0x80)) { |
emh203 | 1:68378811b1e2 | 196 | _cs = 1; |
emh203 | 1:68378811b1e2 | 197 | return response; |
emh203 | 1:68378811b1e2 | 198 | } |
emh203 | 1:68378811b1e2 | 199 | } |
emh203 | 1:68378811b1e2 | 200 | _cs = 1; |
emh203 | 1:68378811b1e2 | 201 | return -1; // timeout |
emh203 | 1:68378811b1e2 | 202 | } |
emh203 | 1:68378811b1e2 | 203 | |
emh203 | 1:68378811b1e2 | 204 | int _read(BYTE *buffer, int length) { |
emh203 | 1:68378811b1e2 | 205 | _cs = 0; |
emh203 | 1:68378811b1e2 | 206 | |
emh203 | 1:68378811b1e2 | 207 | // read until start byte (0xFF) |
emh203 | 1:68378811b1e2 | 208 | while(_spi.write(0xFF) != 0xFE); |
emh203 | 1:68378811b1e2 | 209 | |
emh203 | 1:68378811b1e2 | 210 | // read data |
emh203 | 1:68378811b1e2 | 211 | for(int i=0; i<length; i++) { |
emh203 | 1:68378811b1e2 | 212 | buffer[i] = _spi.write(0xFF); |
emh203 | 1:68378811b1e2 | 213 | } |
emh203 | 1:68378811b1e2 | 214 | _spi.write(0xFF); // checksum |
emh203 | 1:68378811b1e2 | 215 | _spi.write(0xFF); |
emh203 | 1:68378811b1e2 | 216 | |
emh203 | 1:68378811b1e2 | 217 | _cs = 1; |
emh203 | 1:68378811b1e2 | 218 | return 0; |
emh203 | 1:68378811b1e2 | 219 | } |
emh203 | 1:68378811b1e2 | 220 | |
emh203 | 1:68378811b1e2 | 221 | int _write(BYTE *buffer, int length) { |
emh203 | 1:68378811b1e2 | 222 | _cs = 0; |
emh203 | 1:68378811b1e2 | 223 | |
emh203 | 1:68378811b1e2 | 224 | // indicate start of block |
emh203 | 1:68378811b1e2 | 225 | _spi.write(0xFE); |
emh203 | 1:68378811b1e2 | 226 | |
emh203 | 1:68378811b1e2 | 227 | // write the data |
emh203 | 1:68378811b1e2 | 228 | for(int i=0; i<length; i++) { |
emh203 | 1:68378811b1e2 | 229 | _spi.write(buffer[i]); |
emh203 | 1:68378811b1e2 | 230 | } |
emh203 | 1:68378811b1e2 | 231 | |
emh203 | 1:68378811b1e2 | 232 | // write the checksum |
emh203 | 1:68378811b1e2 | 233 | _spi.write(0xFF); |
emh203 | 1:68378811b1e2 | 234 | _spi.write(0xFF); |
emh203 | 1:68378811b1e2 | 235 | |
emh203 | 1:68378811b1e2 | 236 | // check the repsonse token |
emh203 | 1:68378811b1e2 | 237 | if((_spi.write(0xFF) & 0x1F) != 0x05) { |
emh203 | 1:68378811b1e2 | 238 | _cs = 1; |
emh203 | 1:68378811b1e2 | 239 | return 1; |
emh203 | 1:68378811b1e2 | 240 | } |
emh203 | 1:68378811b1e2 | 241 | |
emh203 | 1:68378811b1e2 | 242 | // wait for write to finish |
emh203 | 1:68378811b1e2 | 243 | while(_spi.write(0xFF) == 0); |
emh203 | 1:68378811b1e2 | 244 | |
emh203 | 1:68378811b1e2 | 245 | _cs = 1; |
emh203 | 1:68378811b1e2 | 246 | return 0; |
emh203 | 1:68378811b1e2 | 247 | } |
emh203 | 1:68378811b1e2 | 248 | |
emh203 | 1:68378811b1e2 | 249 | int ext_bits(BYTE *data, int msb, int lsb) { |
emh203 | 1:68378811b1e2 | 250 | int bits = 0; |
emh203 | 1:68378811b1e2 | 251 | int size = 1 + msb - lsb; |
emh203 | 1:68378811b1e2 | 252 | for(int i=0; i<size; i++) { |
emh203 | 1:68378811b1e2 | 253 | int position = lsb + i; |
emh203 | 1:68378811b1e2 | 254 | int byte = 15 - (position >> 3); |
emh203 | 1:68378811b1e2 | 255 | int bit = position & 0x7; |
emh203 | 1:68378811b1e2 | 256 | int value = (data[byte] >> bit) & 1; |
emh203 | 1:68378811b1e2 | 257 | bits |= value << i; |
emh203 | 1:68378811b1e2 | 258 | } |
emh203 | 1:68378811b1e2 | 259 | return bits; |
emh203 | 1:68378811b1e2 | 260 | } |
emh203 | 1:68378811b1e2 | 261 | |
emh203 | 1:68378811b1e2 | 262 | int _sd_sectors() { |
emh203 | 1:68378811b1e2 | 263 | |
emh203 | 1:68378811b1e2 | 264 | // CMD9, Response R2 (R1 byte + 16-byte block read) |
emh203 | 1:68378811b1e2 | 265 | if(_cmd(9, 0) != 0) { |
emh203 | 1:68378811b1e2 | 266 | fprintf(stderr, "Didn't get a response from the disk\n"); |
emh203 | 1:68378811b1e2 | 267 | return 0; |
emh203 | 1:68378811b1e2 | 268 | } |
emh203 | 1:68378811b1e2 | 269 | |
emh203 | 1:68378811b1e2 | 270 | BYTE csd[16]; |
emh203 | 1:68378811b1e2 | 271 | if(_read(csd, 16) != 0) { |
emh203 | 1:68378811b1e2 | 272 | fprintf(stderr, "Couldn't read csd response from disk\n"); |
emh203 | 1:68378811b1e2 | 273 | return 0; |
emh203 | 1:68378811b1e2 | 274 | } |
emh203 | 1:68378811b1e2 | 275 | |
emh203 | 1:68378811b1e2 | 276 | // csd_structure : csd[127:126] |
emh203 | 1:68378811b1e2 | 277 | // c_size : csd[73:62] |
emh203 | 1:68378811b1e2 | 278 | // c_size_mult : csd[49:47] |
emh203 | 1:68378811b1e2 | 279 | // read_bl_len : csd[83:80] |
emh203 | 1:68378811b1e2 | 280 | |
emh203 | 1:68378811b1e2 | 281 | int csd_structure = ext_bits(csd, 127, 126); |
emh203 | 1:68378811b1e2 | 282 | int c_size = ext_bits(csd, 73, 62); |
emh203 | 1:68378811b1e2 | 283 | int c_size_mult = ext_bits(csd, 49, 47); |
emh203 | 1:68378811b1e2 | 284 | int read_bl_len = ext_bits(csd, 83, 80); |
emh203 | 1:68378811b1e2 | 285 | |
emh203 | 1:68378811b1e2 | 286 | if(csd_structure != 0) { |
emh203 | 1:68378811b1e2 | 287 | fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures"); |
emh203 | 1:68378811b1e2 | 288 | return 0; |
emh203 | 1:68378811b1e2 | 289 | } |
emh203 | 1:68378811b1e2 | 290 | |
emh203 | 1:68378811b1e2 | 291 | int blocks = (c_size + 1) * (1 << (c_size_mult + 2)); |
emh203 | 1:68378811b1e2 | 292 | int block_size = 1 << read_bl_len; |
emh203 | 1:68378811b1e2 | 293 | |
emh203 | 1:68378811b1e2 | 294 | if(block_size != 512) { |
emh203 | 1:68378811b1e2 | 295 | fprintf(stderr, "This disk tastes funny! I only like 512 byte blocks (%d)\r\n",block_size); |
emh203 | 1:68378811b1e2 | 296 | return 0; |
emh203 | 1:68378811b1e2 | 297 | } |
emh203 | 1:68378811b1e2 | 298 | |
emh203 | 1:68378811b1e2 | 299 | return blocks; |
emh203 | 1:68378811b1e2 | 300 | } |