This is Petit FAT File System Module for mbed NXP LPC1768. The ported library from http://elm-chan.org/fsw/ff/00index_p.html made by Mr. ChaN. The connection is same as SDCard library here http://mbed.org/projects/cookbook/wiki/SDCard . If you need change a pin, You can find the definition at libpff/connect.h :)

Dependencies:   mbed

Committer:
shintamainjp
Date:
Fri Jun 04 23:47:39 2010 +0000
Revision:
1:a24950493dec
Parent:
0:b5453be5ad07

        

Who changed what in which revision?

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