Lightweight SD card FAT file system. Originaled by chan http://elm-chan.org/fsw/ff/00index_p.html

Petit FAT File System for LPC1114

originaled by elm

If you want to use except LPC1114, you can change pin definitions at mmcPinConfig.h

more detail and original code at http://elm-chan.org/fsw/ff/00index_p.html

This library is NOT compatible with mbed official SDFileSystem

Committer:
hsgw
Date:
Fri May 09 19:41:49 2014 +0000
Revision:
0:845390b117a7
1st commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hsgw 0:845390b117a7 1 /*-------------------------------------------------------------------------*/
hsgw 0:845390b117a7 2 /*PFF for mbed porting by Takuya Urakawa*/
hsgw 0:845390b117a7 3 /*Based on PFF - Low level disk control module for PIC (C)ChaN, 2010 */
hsgw 0:845390b117a7 4 /*-------------------------------------------------------------------------*/
hsgw 0:845390b117a7 5
hsgw 0:845390b117a7 6 #include "pff.h"
hsgw 0:845390b117a7 7 #include "diskio.h"
hsgw 0:845390b117a7 8
hsgw 0:845390b117a7 9 /*-------------------------------------------------------------------------*/
hsgw 0:845390b117a7 10 /* Platform dependent macros and functions needed to be modified */
hsgw 0:845390b117a7 11 /*-------------------------------------------------------------------------*/
hsgw 0:845390b117a7 12
hsgw 0:845390b117a7 13 #include "mbed.h"
hsgw 0:845390b117a7 14 #include "mmcPinConfig.h"
hsgw 0:845390b117a7 15
hsgw 0:845390b117a7 16 #define SELECT() cs.write(0) /* CS = L */
hsgw 0:845390b117a7 17 #define DESELECT() cs.write(1) /* CS = H */
hsgw 0:845390b117a7 18 #define MMC_SEL !cs.read() /* CS status (true:CS == L) */
hsgw 0:845390b117a7 19 #define FORWARD(d) putchar(d) /* Data forwarding function (Console out in this example) */
hsgw 0:845390b117a7 20
hsgw 0:845390b117a7 21 #define SPI_SPEED (20000000)
hsgw 0:845390b117a7 22
hsgw 0:845390b117a7 23 SPI spi(MMC_MOSI, MMC_MISO, MMC_SCLK);
hsgw 0:845390b117a7 24 DigitalOut cs(MMC_CS);
hsgw 0:845390b117a7 25
hsgw 0:845390b117a7 26
hsgw 0:845390b117a7 27 static
hsgw 0:845390b117a7 28 void init_spi (void) /* Initialize SPI port */
hsgw 0:845390b117a7 29 {
hsgw 0:845390b117a7 30 cs = 1;
hsgw 0:845390b117a7 31 spi.format(8);
hsgw 0:845390b117a7 32 spi.frequency(100000);
hsgw 0:845390b117a7 33 }
hsgw 0:845390b117a7 34
hsgw 0:845390b117a7 35 void dly_100us (void) /* Delay 100 microseconds */
hsgw 0:845390b117a7 36 {
hsgw 0:845390b117a7 37 wait_us(100);
hsgw 0:845390b117a7 38 }
hsgw 0:845390b117a7 39
hsgw 0:845390b117a7 40 static
hsgw 0:845390b117a7 41 void xmit_spi (BYTE d) /* Send a byte to the MMC */
hsgw 0:845390b117a7 42 {
hsgw 0:845390b117a7 43 spi.write(d);
hsgw 0:845390b117a7 44 }
hsgw 0:845390b117a7 45
hsgw 0:845390b117a7 46 static
hsgw 0:845390b117a7 47 BYTE rcv_spi (void) /* Send a 0xFF to the MMC and get the received byte */
hsgw 0:845390b117a7 48 {
hsgw 0:845390b117a7 49 return spi.write(0xFF);
hsgw 0:845390b117a7 50 }
hsgw 0:845390b117a7 51
hsgw 0:845390b117a7 52 /*--------------------------------------------------------------------------
hsgw 0:845390b117a7 53
hsgw 0:845390b117a7 54 Module Private Functions
hsgw 0:845390b117a7 55
hsgw 0:845390b117a7 56 ---------------------------------------------------------------------------*/
hsgw 0:845390b117a7 57
hsgw 0:845390b117a7 58 /* Definitions for MMC/SDC command */
hsgw 0:845390b117a7 59 #define CMD0 (0x40+0) /* GO_IDLE_STATE */
hsgw 0:845390b117a7 60 #define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
hsgw 0:845390b117a7 61 #define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
hsgw 0:845390b117a7 62 #define CMD8 (0x40+8) /* SEND_IF_COND */
hsgw 0:845390b117a7 63 #define CMD16 (0x40+16) /* SET_BLOCKLEN */
hsgw 0:845390b117a7 64 #define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
hsgw 0:845390b117a7 65 #define CMD24 (0x40+24) /* WRITE_BLOCK */
hsgw 0:845390b117a7 66 #define CMD55 (0x40+55) /* APP_CMD */
hsgw 0:845390b117a7 67 #define CMD58 (0x40+58) /* READ_OCR */
hsgw 0:845390b117a7 68
hsgw 0:845390b117a7 69
hsgw 0:845390b117a7 70 /* Card type flags (CardType) */
hsgw 0:845390b117a7 71 #define CT_MMC 0x01 /* MMC ver 3 */
hsgw 0:845390b117a7 72 #define CT_SD1 0x02 /* SD ver 1 */
hsgw 0:845390b117a7 73 #define CT_SD2 0x04 /* SD ver 2 */
hsgw 0:845390b117a7 74 #define CT_BLOCK 0x08 /* Block addressing */
hsgw 0:845390b117a7 75
hsgw 0:845390b117a7 76
hsgw 0:845390b117a7 77 static
hsgw 0:845390b117a7 78 BYTE CardType;
hsgw 0:845390b117a7 79
hsgw 0:845390b117a7 80
hsgw 0:845390b117a7 81 /*-----------------------------------------------------------------------*/
hsgw 0:845390b117a7 82 /* Send a command packet to MMC */
hsgw 0:845390b117a7 83 /*-----------------------------------------------------------------------*/
hsgw 0:845390b117a7 84
hsgw 0:845390b117a7 85 static
hsgw 0:845390b117a7 86 BYTE send_cmd (
hsgw 0:845390b117a7 87 BYTE cmd, /* 1st byte (Start + Index) */
hsgw 0:845390b117a7 88 DWORD arg /* Argument (32 bits) */
hsgw 0:845390b117a7 89 )
hsgw 0:845390b117a7 90 {
hsgw 0:845390b117a7 91 BYTE n, res;
hsgw 0:845390b117a7 92
hsgw 0:845390b117a7 93
hsgw 0:845390b117a7 94 if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
hsgw 0:845390b117a7 95 cmd &= 0x7F;
hsgw 0:845390b117a7 96 res = send_cmd(CMD55, 0);
hsgw 0:845390b117a7 97 if (res > 1) return res;
hsgw 0:845390b117a7 98 }
hsgw 0:845390b117a7 99
hsgw 0:845390b117a7 100 /* Select the card */
hsgw 0:845390b117a7 101 DESELECT();
hsgw 0:845390b117a7 102 rcv_spi();
hsgw 0:845390b117a7 103 SELECT();
hsgw 0:845390b117a7 104 rcv_spi();
hsgw 0:845390b117a7 105
hsgw 0:845390b117a7 106 /* Send a command packet */
hsgw 0:845390b117a7 107 xmit_spi(cmd); /* Start + Command index */
hsgw 0:845390b117a7 108 xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
hsgw 0:845390b117a7 109 xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
hsgw 0:845390b117a7 110 xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
hsgw 0:845390b117a7 111 xmit_spi((BYTE)arg); /* Argument[7..0] */
hsgw 0:845390b117a7 112 n = 0x01; /* Dummy CRC + Stop */
hsgw 0:845390b117a7 113 if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
hsgw 0:845390b117a7 114 if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
hsgw 0:845390b117a7 115 xmit_spi(n);
hsgw 0:845390b117a7 116
hsgw 0:845390b117a7 117 /* Receive a command response */
hsgw 0:845390b117a7 118 n = 10; /* Wait for a valid response in timeout of 10 attempts */
hsgw 0:845390b117a7 119 do {
hsgw 0:845390b117a7 120 res = rcv_spi();
hsgw 0:845390b117a7 121 } while ((res & 0x80) && --n);
hsgw 0:845390b117a7 122
hsgw 0:845390b117a7 123 return res; /* Return with the response value */
hsgw 0:845390b117a7 124 }
hsgw 0:845390b117a7 125
hsgw 0:845390b117a7 126
hsgw 0:845390b117a7 127
hsgw 0:845390b117a7 128
hsgw 0:845390b117a7 129 /*--------------------------------------------------------------------------
hsgw 0:845390b117a7 130
hsgw 0:845390b117a7 131 Public Functions
hsgw 0:845390b117a7 132
hsgw 0:845390b117a7 133 ---------------------------------------------------------------------------*/
hsgw 0:845390b117a7 134
hsgw 0:845390b117a7 135 /*-----------------------------------------------------------------------*/
hsgw 0:845390b117a7 136 /* Initialize Disk Drive */
hsgw 0:845390b117a7 137 /*-----------------------------------------------------------------------*/
hsgw 0:845390b117a7 138
hsgw 0:845390b117a7 139 DSTATUS disk_initialize (void)
hsgw 0:845390b117a7 140 {
hsgw 0:845390b117a7 141 BYTE n, cmd, ty, ocr[4];
hsgw 0:845390b117a7 142 UINT tmr;
hsgw 0:845390b117a7 143
hsgw 0:845390b117a7 144 #if _USE_WRITE
hsgw 0:845390b117a7 145 if (CardType && MMC_SEL) disk_writep(0, 0); /* Finalize write process if it is in progress */
hsgw 0:845390b117a7 146 #endif
hsgw 0:845390b117a7 147 init_spi(); /* Initialize ports to control MMC */
hsgw 0:845390b117a7 148 DESELECT();
hsgw 0:845390b117a7 149 for (n = 10; n; n--) rcv_spi(); /* 80 Dummy clocks with CS=H */
hsgw 0:845390b117a7 150
hsgw 0:845390b117a7 151 ty = 0;
hsgw 0:845390b117a7 152 if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
hsgw 0:845390b117a7 153 if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */
hsgw 0:845390b117a7 154 for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); /* Get trailing return value of R7 resp */
hsgw 0:845390b117a7 155 if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
hsgw 0:845390b117a7 156 for (tmr = 10000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) dly_100us(); /* Wait for leaving idle state (ACMD41 with HCS bit) */
hsgw 0:845390b117a7 157 if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
hsgw 0:845390b117a7 158 for (n = 0; n < 4; n++) ocr[n] = rcv_spi();
hsgw 0:845390b117a7 159 ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */
hsgw 0:845390b117a7 160 }
hsgw 0:845390b117a7 161 }
hsgw 0:845390b117a7 162 } else { /* SDv1 or MMCv3 */
hsgw 0:845390b117a7 163 if (send_cmd(ACMD41, 0) <= 1) {
hsgw 0:845390b117a7 164 ty = CT_SD1; cmd = ACMD41; /* SDv1 */
hsgw 0:845390b117a7 165 } else {
hsgw 0:845390b117a7 166 ty = CT_MMC; cmd = CMD1; /* MMCv3 */
hsgw 0:845390b117a7 167 }
hsgw 0:845390b117a7 168 for (tmr = 10000; tmr && send_cmd(cmd, 0); tmr--) dly_100us(); /* Wait for leaving idle state */
hsgw 0:845390b117a7 169 if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
hsgw 0:845390b117a7 170 ty = 0;
hsgw 0:845390b117a7 171 }
hsgw 0:845390b117a7 172 }
hsgw 0:845390b117a7 173 CardType = ty;
hsgw 0:845390b117a7 174 DESELECT();
hsgw 0:845390b117a7 175 rcv_spi();
hsgw 0:845390b117a7 176
hsgw 0:845390b117a7 177 spi.frequency(SPI_SPEED);
hsgw 0:845390b117a7 178
hsgw 0:845390b117a7 179 return ty ? 0 : STA_NOINIT;
hsgw 0:845390b117a7 180 }
hsgw 0:845390b117a7 181
hsgw 0:845390b117a7 182
hsgw 0:845390b117a7 183
hsgw 0:845390b117a7 184 /*-----------------------------------------------------------------------*/
hsgw 0:845390b117a7 185 /* Read partial sector */
hsgw 0:845390b117a7 186 /*-----------------------------------------------------------------------*/
hsgw 0:845390b117a7 187
hsgw 0:845390b117a7 188 DRESULT disk_readp (
hsgw 0:845390b117a7 189 BYTE *buff, /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
hsgw 0:845390b117a7 190 DWORD lba, /* Sector number (LBA) */
hsgw 0:845390b117a7 191 WORD ofs, /* Byte offset to read from (0..511) */
hsgw 0:845390b117a7 192 WORD cnt /* Number of bytes to read (ofs + cnt mus be <= 512) */
hsgw 0:845390b117a7 193 )
hsgw 0:845390b117a7 194 {
hsgw 0:845390b117a7 195 DRESULT res;
hsgw 0:845390b117a7 196 BYTE rc;
hsgw 0:845390b117a7 197 WORD bc;
hsgw 0:845390b117a7 198
hsgw 0:845390b117a7 199
hsgw 0:845390b117a7 200 if (!(CardType & CT_BLOCK)) lba *= 512; /* Convert to byte address if needed */
hsgw 0:845390b117a7 201
hsgw 0:845390b117a7 202 res = RES_ERROR;
hsgw 0:845390b117a7 203 if (send_cmd(CMD17, lba) == 0) { /* READ_SINGLE_BLOCK */
hsgw 0:845390b117a7 204
hsgw 0:845390b117a7 205 bc = 40000;
hsgw 0:845390b117a7 206 do { /* Wait for data packet */
hsgw 0:845390b117a7 207 rc = rcv_spi();
hsgw 0:845390b117a7 208 } while (rc == 0xFF && --bc);
hsgw 0:845390b117a7 209
hsgw 0:845390b117a7 210 if (rc == 0xFE) { /* A data packet arrived */
hsgw 0:845390b117a7 211 bc = 514 - ofs - cnt;
hsgw 0:845390b117a7 212
hsgw 0:845390b117a7 213 /* Skip leading bytes */
hsgw 0:845390b117a7 214 if (ofs) {
hsgw 0:845390b117a7 215 do rcv_spi(); while (--ofs);
hsgw 0:845390b117a7 216 }
hsgw 0:845390b117a7 217
hsgw 0:845390b117a7 218 /* Receive a part of the sector */
hsgw 0:845390b117a7 219 if (buff) { /* Store data to the memory */
hsgw 0:845390b117a7 220 do {
hsgw 0:845390b117a7 221 *buff++ = rcv_spi();
hsgw 0:845390b117a7 222 } while (--cnt);
hsgw 0:845390b117a7 223 } else { /* Forward data to the outgoing stream (depends on the project) */
hsgw 0:845390b117a7 224 do {
hsgw 0:845390b117a7 225 FORWARD(rcv_spi());
hsgw 0:845390b117a7 226 } while (--cnt);
hsgw 0:845390b117a7 227 }
hsgw 0:845390b117a7 228
hsgw 0:845390b117a7 229 /* Skip trailing bytes and CRC */
hsgw 0:845390b117a7 230 do rcv_spi(); while (--bc);
hsgw 0:845390b117a7 231
hsgw 0:845390b117a7 232 res = RES_OK;
hsgw 0:845390b117a7 233 }
hsgw 0:845390b117a7 234 }
hsgw 0:845390b117a7 235
hsgw 0:845390b117a7 236 DESELECT();
hsgw 0:845390b117a7 237 rcv_spi();
hsgw 0:845390b117a7 238
hsgw 0:845390b117a7 239 return res;
hsgw 0:845390b117a7 240 }
hsgw 0:845390b117a7 241
hsgw 0:845390b117a7 242
hsgw 0:845390b117a7 243
hsgw 0:845390b117a7 244 /*-----------------------------------------------------------------------*/
hsgw 0:845390b117a7 245 /* Write partial sector */
hsgw 0:845390b117a7 246 /*-----------------------------------------------------------------------*/
hsgw 0:845390b117a7 247
hsgw 0:845390b117a7 248 #if _USE_WRITE
hsgw 0:845390b117a7 249 DRESULT disk_writep (
hsgw 0:845390b117a7 250 const BYTE *buff, /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */
hsgw 0:845390b117a7 251 DWORD sa /* Number of bytes to send, Sector number (LBA) or zero */
hsgw 0:845390b117a7 252 )
hsgw 0:845390b117a7 253 {
hsgw 0:845390b117a7 254 DRESULT res;
hsgw 0:845390b117a7 255 WORD bc;
hsgw 0:845390b117a7 256 static WORD wc;
hsgw 0:845390b117a7 257
hsgw 0:845390b117a7 258 res = RES_ERROR;
hsgw 0:845390b117a7 259
hsgw 0:845390b117a7 260 if (buff) { /* Send data bytes */
hsgw 0:845390b117a7 261 bc = (WORD)sa;
hsgw 0:845390b117a7 262 while (bc && wc) { /* Send data bytes to the card */
hsgw 0:845390b117a7 263 xmit_spi(*buff++);
hsgw 0:845390b117a7 264 wc--; bc--;
hsgw 0:845390b117a7 265 }
hsgw 0:845390b117a7 266 res = RES_OK;
hsgw 0:845390b117a7 267 } else {
hsgw 0:845390b117a7 268 if (sa) { /* Initiate sector write process */
hsgw 0:845390b117a7 269 if (!(CardType & CT_BLOCK)) sa *= 512; /* Convert to byte address if needed */
hsgw 0:845390b117a7 270 if (send_cmd(CMD24, sa) == 0) { /* WRITE_SINGLE_BLOCK */
hsgw 0:845390b117a7 271 xmit_spi(0xFF); xmit_spi(0xFE); /* Data block header */
hsgw 0:845390b117a7 272 wc = 512; /* Set byte counter */
hsgw 0:845390b117a7 273 res = RES_OK;
hsgw 0:845390b117a7 274 }
hsgw 0:845390b117a7 275 } else { /* Finalize sector write process */
hsgw 0:845390b117a7 276 bc = wc + 2;
hsgw 0:845390b117a7 277 while (bc--) xmit_spi(0); /* Fill left bytes and CRC with zeros */
hsgw 0:845390b117a7 278 if ((rcv_spi() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 500ms */
hsgw 0:845390b117a7 279 for (bc = 5000; rcv_spi() != 0xFF && bc; bc--) dly_100us(); /* Wait ready */
hsgw 0:845390b117a7 280 if (bc) res = RES_OK;
hsgw 0:845390b117a7 281 }
hsgw 0:845390b117a7 282 DESELECT();
hsgw 0:845390b117a7 283 rcv_spi();
hsgw 0:845390b117a7 284 }
hsgw 0:845390b117a7 285 }
hsgw 0:845390b117a7 286
hsgw 0:845390b117a7 287 return res;
hsgw 0:845390b117a7 288 }
hsgw 0:845390b117a7 289 #endif