updated chan_fatfs

Dependents:   HARP2 HARP3

Fork of chan_fatfs by Eli Hughes

Committer:
tylerjw
Date:
Fri Dec 28 17:12:02 2012 +0000
Revision:
8:1f9748c6b865
Parent:
4:f88948891a05
Added f_size() macro, not tested!!!

Who changed what in which revision?

UserRevisionLine numberNew 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"
tylerjw 2:e8cd708f09ff 10 #include "mbed_debug.h"
emh203 1:68378811b1e2 11
emh203 1:68378811b1e2 12
emh203 1:68378811b1e2 13 //******************************************************************************************************************
emh203 1:68378811b1e2 14 // MBED SPI/CS Select functions.... Modify for your layout.
emh203 1:68378811b1e2 15 //**************************************************************************************
emh203 1:68378811b1e2 16
emh203 1:68378811b1e2 17 SPI _spi(p5, p6, p7); // mosi, miso, sclk
emh203 1:68378811b1e2 18 DigitalOut _cs(p8);
emh203 1:68378811b1e2 19
emh203 1:68378811b1e2 20 //******************************************************************************************************************
emh203 1:68378811b1e2 21 // Low Level Sector Access Function Prototypes('C' Castrated versions of Simon Ford's C++ MBED SDFileSystem class
emh203 1:68378811b1e2 22 //******************************************************************************************************************
emh203 1:68378811b1e2 23 int _cmd(int cmd, int arg);
emh203 1:68378811b1e2 24 int _read(BYTE *buffer, int length);
emh203 1:68378811b1e2 25 int _write(BYTE *buffer, int length);
tylerjw 2:e8cd708f09ff 26 uint32_t ext_bits(BYTE *data, int msb, int lsb);
emh203 1:68378811b1e2 27 int _sd_sectors();
emh203 1:68378811b1e2 28 int _sectors;
tylerjw 2:e8cd708f09ff 29 int _cmd(int cmd, int arg);
tylerjw 2:e8cd708f09ff 30 int _cmdx(int cmd, int arg);
tylerjw 2:e8cd708f09ff 31 int _cmd8();
tylerjw 2:e8cd708f09ff 32 int _cmd58();
tylerjw 2:e8cd708f09ff 33 int cdv;
emh203 1:68378811b1e2 34
emh203 1:68378811b1e2 35 #define SD_COMMAND_TIMEOUT 5000
emh203 1:68378811b1e2 36
tylerjw 2:e8cd708f09ff 37 #define R1_IDLE_STATE (1 << 0)
tylerjw 2:e8cd708f09ff 38 #define R1_ERASE_RESET (1 << 1)
tylerjw 2:e8cd708f09ff 39 #define R1_ILLEGAL_COMMAND (1 << 2)
tylerjw 2:e8cd708f09ff 40 #define R1_COM_CRC_ERROR (1 << 3)
tylerjw 2:e8cd708f09ff 41 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
tylerjw 2:e8cd708f09ff 42 #define R1_ADDRESS_ERROR (1 << 5)
tylerjw 2:e8cd708f09ff 43 #define R1_PARAMETER_ERROR (1 << 6)
tylerjw 2:e8cd708f09ff 44
emh203 1:68378811b1e2 45
emh203 1:68378811b1e2 46 //******************************************************************************************************************
tylerjw 2:e8cd708f09ff 47 // Sector Access functions for CHAN FatFs
emh203 1:68378811b1e2 48 //******************************************************************************************************************
emh203 1:68378811b1e2 49
emh203 1:68378811b1e2 50 DRESULT disk_ioctl (
emh203 1:68378811b1e2 51 BYTE drv, /* Physical drive nmuber (0..) */
emh203 1:68378811b1e2 52 BYTE ctrl, /* Control code */
emh203 1:68378811b1e2 53 void *buff /* Buffer to send/receive control data */
emh203 1:68378811b1e2 54 )
emh203 1:68378811b1e2 55 {
emh203 1:68378811b1e2 56 DRESULT res;
emh203 1:68378811b1e2 57
tylerjw 2:e8cd708f09ff 58 switch(ctrl) {
emh203 1:68378811b1e2 59 case CTRL_SYNC:
tylerjw 2:e8cd708f09ff 60 res = RES_OK;
tylerjw 2:e8cd708f09ff 61 break;
tylerjw 2:e8cd708f09ff 62
emh203 1:68378811b1e2 63 case GET_SECTOR_SIZE:
tylerjw 2:e8cd708f09ff 64 res = RES_OK;
emh203 1:68378811b1e2 65 *(WORD *)buff = 512;
tylerjw 2:e8cd708f09ff 66 break;
tylerjw 2:e8cd708f09ff 67
emh203 1:68378811b1e2 68 case GET_SECTOR_COUNT:
emh203 1:68378811b1e2 69 res = RES_OK;
tylerjw 2:e8cd708f09ff 70 *(DWORD *)buff = (WORD)_sd_sectors();
tylerjw 2:e8cd708f09ff 71 break;
tylerjw 2:e8cd708f09ff 72
emh203 1:68378811b1e2 73 case GET_BLOCK_SIZE:
tylerjw 2:e8cd708f09ff 74 res = RES_OK;
tylerjw 2:e8cd708f09ff 75 *(DWORD *)buff = 1;
tylerjw 2:e8cd708f09ff 76 break;
tylerjw 2:e8cd708f09ff 77
emh203 1:68378811b1e2 78 default:
tylerjw 2:e8cd708f09ff 79 res = RES_OK;
tylerjw 2:e8cd708f09ff 80 break;
emh203 1:68378811b1e2 81 }
emh203 1:68378811b1e2 82 return res;
emh203 1:68378811b1e2 83 }
emh203 1:68378811b1e2 84
tylerjw 4:f88948891a05 85 DSTATUS card_initialize(BYTE Drive)
tylerjw 2:e8cd708f09ff 86 {
tylerjw 2:e8cd708f09ff 87 // Set to 100kHz for initialisation, and clock card with cs = 1
tylerjw 2:e8cd708f09ff 88 _spi.frequency(100000);
tylerjw 2:e8cd708f09ff 89 _cs = 1;
tylerjw 2:e8cd708f09ff 90 for (int i = 0; i < 16; i++) {
emh203 1:68378811b1e2 91 _spi.write(0xFF);
emh203 1:68378811b1e2 92 }
emh203 1:68378811b1e2 93
emh203 1:68378811b1e2 94 // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
tylerjw 2:e8cd708f09ff 95 if (_cmd(0, 0) != R1_IDLE_STATE) {
tylerjw 2:e8cd708f09ff 96 debug("No disk, or could not put SD card in to SPI idle state\n");
emh203 1:68378811b1e2 97 return STA_NOINIT;
emh203 1:68378811b1e2 98 }
tylerjw 2:e8cd708f09ff 99
tylerjw 2:e8cd708f09ff 100 // send CMD8 to determine whther it is ver 2.x
tylerjw 2:e8cd708f09ff 101 int r = _cmd8();
tylerjw 2:e8cd708f09ff 102 if (r == R1_IDLE_STATE) {
tylerjw 2:e8cd708f09ff 103 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
tylerjw 2:e8cd708f09ff 104 wait_ms(50);
tylerjw 2:e8cd708f09ff 105 _cmd58();
tylerjw 2:e8cd708f09ff 106 _cmd(55, 0);
tylerjw 2:e8cd708f09ff 107 if (_cmd(41, 0x40000000) == 0) {
tylerjw 2:e8cd708f09ff 108 _cmd58();
tylerjw 2:e8cd708f09ff 109 //debug_if(SD_DBG, "\n\rInit: SDCARD_V2\n\r");
tylerjw 2:e8cd708f09ff 110 cdv = 1;
tylerjw 2:e8cd708f09ff 111 return 0;
tylerjw 2:e8cd708f09ff 112 }
tylerjw 2:e8cd708f09ff 113 }
tylerjw 2:e8cd708f09ff 114 debug("Timeout waiting for v2.x card\n");
tylerjw 2:e8cd708f09ff 115 return STA_NOINIT;
tylerjw 2:e8cd708f09ff 116
tylerjw 2:e8cd708f09ff 117 } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
tylerjw 2:e8cd708f09ff 118 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
tylerjw 2:e8cd708f09ff 119 _cmd(55, 0);
tylerjw 2:e8cd708f09ff 120 if (_cmd(41, 0) == 0) {
tylerjw 2:e8cd708f09ff 121 cdv = 512;
tylerjw 2:e8cd708f09ff 122 //debug_if(SD_DBG, "\n\rInit: SEDCARD_V1\n\r");
tylerjw 2:e8cd708f09ff 123 return 0;
tylerjw 2:e8cd708f09ff 124 }
tylerjw 2:e8cd708f09ff 125 }
tylerjw 2:e8cd708f09ff 126 debug("Timeout waiting for v1.x card\n");
tylerjw 2:e8cd708f09ff 127 return STA_NOINIT;
tylerjw 2:e8cd708f09ff 128
tylerjw 2:e8cd708f09ff 129 } else {
tylerjw 2:e8cd708f09ff 130 debug("Not in idle state after sending CMD8 (not an SD card?)\n");
tylerjw 2:e8cd708f09ff 131 return STA_NOINIT;
emh203 1:68378811b1e2 132 }
tylerjw 4:f88948891a05 133 }
tylerjw 4:f88948891a05 134
tylerjw 4:f88948891a05 135 DSTATUS disk_initialize(BYTE Drive)
tylerjw 4:f88948891a05 136 {
tylerjw 4:f88948891a05 137 DSTATUS ret = card_initialize(Drive);
emh203 1:68378811b1e2 138
emh203 1:68378811b1e2 139 _sectors = _sd_sectors();
emh203 1:68378811b1e2 140
emh203 1:68378811b1e2 141 // Set block length to 512 (CMD16)
tylerjw 2:e8cd708f09ff 142 if (_cmd(16, 512) != 0) {
tylerjw 2:e8cd708f09ff 143 debug("Set 512-byte block timed out\n");
emh203 1:68378811b1e2 144 return STA_NOINIT;
emh203 1:68378811b1e2 145 }
tylerjw 2:e8cd708f09ff 146
emh203 1:68378811b1e2 147 _spi.frequency(10000000); // Set to 10MHz for data transfer
tylerjw 4:f88948891a05 148 return ret;
emh203 1:68378811b1e2 149 }
emh203 1:68378811b1e2 150
emh203 1:68378811b1e2 151 DRESULT disk_write(BYTE Drive,const BYTE * Buffer, DWORD SectorNumber, BYTE SectorCount)
emh203 1:68378811b1e2 152 {
emh203 1:68378811b1e2 153 BYTE i;
tylerjw 2:e8cd708f09ff 154
emh203 1:68378811b1e2 155 BYTE * MyBufOut = (BYTE *)Buffer;
tylerjw 2:e8cd708f09ff 156
tylerjw 2:e8cd708f09ff 157 for(i=0; i<SectorCount; i++) {
emh203 1:68378811b1e2 158 // set write address for single block (CMD24)
emh203 1:68378811b1e2 159 if(_cmd(24, (SectorNumber + i) * 512 ) != 0) {
emh203 1:68378811b1e2 160 return RES_ERROR;
emh203 1:68378811b1e2 161 }
emh203 1:68378811b1e2 162
emh203 1:68378811b1e2 163 // send the data block
tylerjw 2:e8cd708f09ff 164 _write(MyBufOut, 512);
tylerjw 2:e8cd708f09ff 165
emh203 1:68378811b1e2 166 MyBufOut+=512;
emh203 1:68378811b1e2 167 }
tylerjw 2:e8cd708f09ff 168 return RES_OK;
emh203 1:68378811b1e2 169 }
emh203 1:68378811b1e2 170
emh203 1:68378811b1e2 171 DRESULT disk_read(BYTE Drive, BYTE * Buffer,DWORD SectorNumber, BYTE SectorCount)
tylerjw 2:e8cd708f09ff 172 {
emh203 1:68378811b1e2 173 BYTE i;
tylerjw 2:e8cd708f09ff 174 for(i=0; i<SectorCount; i++) {
emh203 1:68378811b1e2 175 // set read address for single block (CMD17)
tylerjw 2:e8cd708f09ff 176 if(_cmd(17, (SectorNumber+i) * 512) != 0) {
emh203 1:68378811b1e2 177 return RES_ERROR;
emh203 1:68378811b1e2 178 }
emh203 1:68378811b1e2 179 // receive the data
emh203 1:68378811b1e2 180 _read(Buffer, 512);
tylerjw 2:e8cd708f09ff 181
emh203 1:68378811b1e2 182 Buffer+=512;
emh203 1:68378811b1e2 183 }
tylerjw 2:e8cd708f09ff 184 return RES_OK;
emh203 1:68378811b1e2 185 }
emh203 1:68378811b1e2 186
emh203 1:68378811b1e2 187
emh203 1:68378811b1e2 188 DWORD get_fattime(void)
emh203 1:68378811b1e2 189 {
emh203 1:68378811b1e2 190 time_t CurrentTimeStamp;
emh203 1:68378811b1e2 191 tm *CurrentLocalTime;
emh203 1:68378811b1e2 192 DWORD FATFSTimeCode;
tylerjw 2:e8cd708f09ff 193
emh203 1:68378811b1e2 194 CurrentTimeStamp = time(NULL);
emh203 1:68378811b1e2 195 CurrentLocalTime = localtime(&CurrentTimeStamp);
tylerjw 2:e8cd708f09ff 196
tylerjw 2:e8cd708f09ff 197 //Map the tm struct time into the FatFs time code
tylerjw 2:e8cd708f09ff 198 FATFSTimeCode = ((CurrentLocalTime->tm_year-80)<<25) |
tylerjw 2:e8cd708f09ff 199 ((CurrentLocalTime->tm_mon+1)<<21) |
tylerjw 2:e8cd708f09ff 200 ((CurrentLocalTime->tm_mday)<<16) |
emh203 1:68378811b1e2 201 ((CurrentLocalTime->tm_hour)<<11) |
tylerjw 2:e8cd708f09ff 202 ((CurrentLocalTime->tm_min)<<5) |
emh203 1:68378811b1e2 203 ((CurrentLocalTime->tm_sec));
emh203 1:68378811b1e2 204
tylerjw 2:e8cd708f09ff 205 return FATFSTimeCode;
emh203 1:68378811b1e2 206 }
emh203 1:68378811b1e2 207
emh203 1:68378811b1e2 208 DSTATUS disk_status(BYTE Drive)
emh203 1:68378811b1e2 209 {
emh203 1:68378811b1e2 210 return 0;
emh203 1:68378811b1e2 211 }
emh203 1:68378811b1e2 212
emh203 1:68378811b1e2 213 //**************************************************************************************
emh203 1:68378811b1e2 214 // Low Level Sector Access Functions (Castrated versions of Simon Fords C++ MBED class
emh203 1:68378811b1e2 215 //**************************************************************************************
emh203 1:68378811b1e2 216
tylerjw 2:e8cd708f09ff 217 int _cmd(int cmd, int arg)
tylerjw 2:e8cd708f09ff 218 {
tylerjw 2:e8cd708f09ff 219 _cs = 0;
tylerjw 2:e8cd708f09ff 220
tylerjw 2:e8cd708f09ff 221 // send a command
tylerjw 2:e8cd708f09ff 222 _spi.write(0x40 | cmd);
tylerjw 2:e8cd708f09ff 223 _spi.write(arg >> 24);
tylerjw 2:e8cd708f09ff 224 _spi.write(arg >> 16);
tylerjw 2:e8cd708f09ff 225 _spi.write(arg >> 8);
tylerjw 2:e8cd708f09ff 226 _spi.write(arg >> 0);
tylerjw 2:e8cd708f09ff 227 _spi.write(0x95);
tylerjw 2:e8cd708f09ff 228
tylerjw 2:e8cd708f09ff 229 // wait for the repsonse (response[7] == 0)
tylerjw 2:e8cd708f09ff 230 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
tylerjw 2:e8cd708f09ff 231 int response = _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 232 if (!(response & 0x80)) {
tylerjw 2:e8cd708f09ff 233 _cs = 1;
tylerjw 2:e8cd708f09ff 234 _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 235 return response;
tylerjw 2:e8cd708f09ff 236 }
tylerjw 2:e8cd708f09ff 237 }
tylerjw 2:e8cd708f09ff 238 _cs = 1;
tylerjw 2:e8cd708f09ff 239 _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 240 return -1; // timeout
tylerjw 2:e8cd708f09ff 241 }
tylerjw 2:e8cd708f09ff 242 int _cmdx(int cmd, int arg)
tylerjw 2:e8cd708f09ff 243 {
tylerjw 2:e8cd708f09ff 244 _cs = 0;
emh203 1:68378811b1e2 245
emh203 1:68378811b1e2 246 // send a command
emh203 1:68378811b1e2 247 _spi.write(0x40 | cmd);
emh203 1:68378811b1e2 248 _spi.write(arg >> 24);
emh203 1:68378811b1e2 249 _spi.write(arg >> 16);
emh203 1:68378811b1e2 250 _spi.write(arg >> 8);
emh203 1:68378811b1e2 251 _spi.write(arg >> 0);
emh203 1:68378811b1e2 252 _spi.write(0x95);
emh203 1:68378811b1e2 253
emh203 1:68378811b1e2 254 // wait for the repsonse (response[7] == 0)
tylerjw 2:e8cd708f09ff 255 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
emh203 1:68378811b1e2 256 int response = _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 257 if (!(response & 0x80)) {
tylerjw 2:e8cd708f09ff 258 return response;
tylerjw 2:e8cd708f09ff 259 }
tylerjw 2:e8cd708f09ff 260 }
tylerjw 2:e8cd708f09ff 261 _cs = 1;
tylerjw 2:e8cd708f09ff 262 _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 263 return -1; // timeout
tylerjw 2:e8cd708f09ff 264 }
tylerjw 2:e8cd708f09ff 265
tylerjw 2:e8cd708f09ff 266
tylerjw 2:e8cd708f09ff 267 int _cmd58()
tylerjw 2:e8cd708f09ff 268 {
tylerjw 2:e8cd708f09ff 269 _cs = 0;
tylerjw 2:e8cd708f09ff 270 int arg = 0;
tylerjw 2:e8cd708f09ff 271
tylerjw 2:e8cd708f09ff 272 // send a command
tylerjw 2:e8cd708f09ff 273 _spi.write(0x40 | 58);
tylerjw 2:e8cd708f09ff 274 _spi.write(arg >> 24);
tylerjw 2:e8cd708f09ff 275 _spi.write(arg >> 16);
tylerjw 2:e8cd708f09ff 276 _spi.write(arg >> 8);
tylerjw 2:e8cd708f09ff 277 _spi.write(arg >> 0);
tylerjw 2:e8cd708f09ff 278 _spi.write(0x95);
tylerjw 2:e8cd708f09ff 279
tylerjw 2:e8cd708f09ff 280 // wait for the repsonse (response[7] == 0)
tylerjw 2:e8cd708f09ff 281 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
tylerjw 2:e8cd708f09ff 282 int response = _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 283 if (!(response & 0x80)) {
tylerjw 2:e8cd708f09ff 284 int ocr = _spi.write(0xFF) << 24;
tylerjw 2:e8cd708f09ff 285 ocr |= _spi.write(0xFF) << 16;
tylerjw 2:e8cd708f09ff 286 ocr |= _spi.write(0xFF) << 8;
tylerjw 2:e8cd708f09ff 287 ocr |= _spi.write(0xFF) << 0;
emh203 1:68378811b1e2 288 _cs = 1;
tylerjw 2:e8cd708f09ff 289 _spi.write(0xFF);
emh203 1:68378811b1e2 290 return response;
emh203 1:68378811b1e2 291 }
emh203 1:68378811b1e2 292 }
emh203 1:68378811b1e2 293 _cs = 1;
tylerjw 2:e8cd708f09ff 294 _spi.write(0xFF);
emh203 1:68378811b1e2 295 return -1; // timeout
emh203 1:68378811b1e2 296 }
emh203 1:68378811b1e2 297
tylerjw 2:e8cd708f09ff 298 int _cmd8()
tylerjw 2:e8cd708f09ff 299 {
tylerjw 2:e8cd708f09ff 300 _cs = 0;
tylerjw 2:e8cd708f09ff 301
tylerjw 2:e8cd708f09ff 302 // send a command
tylerjw 2:e8cd708f09ff 303 _spi.write(0x40 | 8); // CMD8
tylerjw 2:e8cd708f09ff 304 _spi.write(0x00); // reserved
tylerjw 2:e8cd708f09ff 305 _spi.write(0x00); // reserved
tylerjw 2:e8cd708f09ff 306 _spi.write(0x01); // 3.3v
tylerjw 2:e8cd708f09ff 307 _spi.write(0xAA); // check pattern
tylerjw 2:e8cd708f09ff 308 _spi.write(0x87); // crc
tylerjw 2:e8cd708f09ff 309
tylerjw 2:e8cd708f09ff 310 // wait for the repsonse (response[7] == 0)
tylerjw 2:e8cd708f09ff 311 for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) {
tylerjw 2:e8cd708f09ff 312 char response[5];
tylerjw 2:e8cd708f09ff 313 response[0] = _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 314 if (!(response[0] & 0x80)) {
tylerjw 2:e8cd708f09ff 315 for (int j = 1; j < 5; j++) {
tylerjw 2:e8cd708f09ff 316 response[i] = _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 317 }
tylerjw 2:e8cd708f09ff 318 _cs = 1;
tylerjw 2:e8cd708f09ff 319 _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 320 return response[0];
tylerjw 2:e8cd708f09ff 321 }
tylerjw 2:e8cd708f09ff 322 }
tylerjw 2:e8cd708f09ff 323 _cs = 1;
tylerjw 2:e8cd708f09ff 324 _spi.write(0xFF);
tylerjw 2:e8cd708f09ff 325 return -1; // timeout
tylerjw 2:e8cd708f09ff 326 }
tylerjw 2:e8cd708f09ff 327 int _read(BYTE *buffer, int length)
tylerjw 2:e8cd708f09ff 328 {
emh203 1:68378811b1e2 329 _cs = 0;
emh203 1:68378811b1e2 330
emh203 1:68378811b1e2 331 // read until start byte (0xFF)
tylerjw 2:e8cd708f09ff 332 while (_spi.write(0xFF) != 0xFE);
emh203 1:68378811b1e2 333
emh203 1:68378811b1e2 334 // read data
tylerjw 2:e8cd708f09ff 335 for (int i = 0; i < length; i++) {
emh203 1:68378811b1e2 336 buffer[i] = _spi.write(0xFF);
emh203 1:68378811b1e2 337 }
emh203 1:68378811b1e2 338 _spi.write(0xFF); // checksum
emh203 1:68378811b1e2 339 _spi.write(0xFF);
emh203 1:68378811b1e2 340
tylerjw 2:e8cd708f09ff 341 _cs = 1;
tylerjw 2:e8cd708f09ff 342 _spi.write(0xFF);
emh203 1:68378811b1e2 343 return 0;
emh203 1:68378811b1e2 344 }
emh203 1:68378811b1e2 345
tylerjw 2:e8cd708f09ff 346
tylerjw 2:e8cd708f09ff 347 int _write(BYTE *buffer, int length)
tylerjw 2:e8cd708f09ff 348 {
emh203 1:68378811b1e2 349 _cs = 0;
tylerjw 2:e8cd708f09ff 350
emh203 1:68378811b1e2 351 // indicate start of block
emh203 1:68378811b1e2 352 _spi.write(0xFE);
tylerjw 2:e8cd708f09ff 353
emh203 1:68378811b1e2 354 // write the data
tylerjw 2:e8cd708f09ff 355 for (int i = 0; i < length; i++) {
emh203 1:68378811b1e2 356 _spi.write(buffer[i]);
emh203 1:68378811b1e2 357 }
tylerjw 2:e8cd708f09ff 358
emh203 1:68378811b1e2 359 // write the checksum
tylerjw 2:e8cd708f09ff 360 _spi.write(0xFF);
emh203 1:68378811b1e2 361 _spi.write(0xFF);
emh203 1:68378811b1e2 362
tylerjw 2:e8cd708f09ff 363 // check the response token
tylerjw 2:e8cd708f09ff 364 if ((_spi.write(0xFF) & 0x1F) != 0x05) {
tylerjw 2:e8cd708f09ff 365 _cs = 1;
tylerjw 2:e8cd708f09ff 366 _spi.write(0xFF);
emh203 1:68378811b1e2 367 return 1;
emh203 1:68378811b1e2 368 }
emh203 1:68378811b1e2 369
emh203 1:68378811b1e2 370 // wait for write to finish
tylerjw 2:e8cd708f09ff 371 while (_spi.write(0xFF) == 0);
emh203 1:68378811b1e2 372
tylerjw 2:e8cd708f09ff 373 _cs = 1;
tylerjw 2:e8cd708f09ff 374 _spi.write(0xFF);
emh203 1:68378811b1e2 375 return 0;
emh203 1:68378811b1e2 376 }
emh203 1:68378811b1e2 377
tylerjw 2:e8cd708f09ff 378 static uint32_t ext_bits(unsigned char *data, int msb, int lsb)
tylerjw 2:e8cd708f09ff 379 {
tylerjw 2:e8cd708f09ff 380 uint32_t bits = 0;
tylerjw 2:e8cd708f09ff 381 uint32_t size = 1 + msb - lsb;
tylerjw 2:e8cd708f09ff 382 for (int i = 0; i < size; i++) {
tylerjw 2:e8cd708f09ff 383 uint32_t position = lsb + i;
tylerjw 2:e8cd708f09ff 384 uint32_t byte = 15 - (position >> 3);
tylerjw 2:e8cd708f09ff 385 uint32_t bit = position & 0x7;
tylerjw 2:e8cd708f09ff 386 uint32_t value = (data[byte] >> bit) & 1;
emh203 1:68378811b1e2 387 bits |= value << i;
emh203 1:68378811b1e2 388 }
emh203 1:68378811b1e2 389 return bits;
emh203 1:68378811b1e2 390 }
emh203 1:68378811b1e2 391
tylerjw 2:e8cd708f09ff 392 int _sd_sectors()
tylerjw 2:e8cd708f09ff 393 {
tylerjw 2:e8cd708f09ff 394 uint32_t c_size, c_size_mult, read_bl_len;
tylerjw 2:e8cd708f09ff 395 uint32_t block_len, mult, blocknr, capacity;
tylerjw 2:e8cd708f09ff 396 uint32_t hc_c_size;
tylerjw 2:e8cd708f09ff 397 uint64_t blocks;
emh203 1:68378811b1e2 398
emh203 1:68378811b1e2 399 // CMD9, Response R2 (R1 byte + 16-byte block read)
tylerjw 2:e8cd708f09ff 400 if (_cmdx(9, 0) != 0) {
tylerjw 2:e8cd708f09ff 401 debug("Didn't get a response from the disk\n");
emh203 1:68378811b1e2 402 return 0;
emh203 1:68378811b1e2 403 }
tylerjw 2:e8cd708f09ff 404
tylerjw 2:e8cd708f09ff 405 uint8_t csd[16];
tylerjw 2:e8cd708f09ff 406 if (_read(csd, 16) != 0) {
tylerjw 2:e8cd708f09ff 407 debug("Couldn't read csd response from disk\n");
emh203 1:68378811b1e2 408 return 0;
emh203 1:68378811b1e2 409 }
emh203 1:68378811b1e2 410
emh203 1:68378811b1e2 411 // csd_structure : csd[127:126]
emh203 1:68378811b1e2 412 // c_size : csd[73:62]
emh203 1:68378811b1e2 413 // c_size_mult : csd[49:47]
tylerjw 2:e8cd708f09ff 414 // read_bl_len : csd[83:80] - the *maximum* read block length
emh203 1:68378811b1e2 415
emh203 1:68378811b1e2 416 int csd_structure = ext_bits(csd, 127, 126);
tylerjw 2:e8cd708f09ff 417
tylerjw 2:e8cd708f09ff 418 switch (csd_structure) {
tylerjw 2:e8cd708f09ff 419 case 0:
tylerjw 2:e8cd708f09ff 420 cdv = 512;
tylerjw 2:e8cd708f09ff 421 c_size = ext_bits(csd, 73, 62);
tylerjw 2:e8cd708f09ff 422 c_size_mult = ext_bits(csd, 49, 47);
tylerjw 2:e8cd708f09ff 423 read_bl_len = ext_bits(csd, 83, 80);
emh203 1:68378811b1e2 424
tylerjw 2:e8cd708f09ff 425 block_len = 1 << read_bl_len;
tylerjw 2:e8cd708f09ff 426 mult = 1 << (c_size_mult + 2);
tylerjw 2:e8cd708f09ff 427 blocknr = (c_size + 1) * mult;
tylerjw 2:e8cd708f09ff 428 capacity = blocknr * block_len;
tylerjw 2:e8cd708f09ff 429 blocks = capacity / 512;
tylerjw 2:e8cd708f09ff 430 //debug_if(SD_DBG, "\n\rSDCard\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks);
tylerjw 2:e8cd708f09ff 431 break;
tylerjw 2:e8cd708f09ff 432
tylerjw 2:e8cd708f09ff 433 case 1:
tylerjw 2:e8cd708f09ff 434 cdv = 1;
tylerjw 2:e8cd708f09ff 435 hc_c_size = ext_bits(csd, 63, 48);
tylerjw 2:e8cd708f09ff 436 blocks = (hc_c_size+1)*1024;
tylerjw 2:e8cd708f09ff 437 //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);
tylerjw 2:e8cd708f09ff 438 break;
tylerjw 2:e8cd708f09ff 439
tylerjw 2:e8cd708f09ff 440 default:
tylerjw 2:e8cd708f09ff 441 debug("CSD struct unsupported\r\n");
tylerjw 2:e8cd708f09ff 442 return 0;
tylerjw 2:e8cd708f09ff 443 };
emh203 1:68378811b1e2 444 return blocks;
tylerjw 2:e8cd708f09ff 445 }