For Terrance

Dependencies:   mbed

Committer:
emh203
Date:
Wed Jun 13 15:10:06 2012 +0000
Revision:
0:085749c8446f

        

Who changed what in which revision?

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