Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
diskio_mmc.cpp
00001 /*-----------------------------------------------------------------------*/ 00002 /* PFF - Low level disk control module for ATtiny85 (C)ChaN, 2009 */ 00003 /*-----------------------------------------------------------------------*/ 00004 00005 #define _WRITE_FUNC 1 00006 00007 #include "diskio.h" 00008 #include "mbed.h" 00009 #include "connect.h" 00010 00011 /* Definitions for MMC/SDC command */ 00012 #define CMD0 (0x40+0) /* GO_IDLE_STATE */ 00013 #define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */ 00014 #define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */ 00015 #define CMD8 (0x40+8) /* SEND_IF_COND */ 00016 #define CMD16 (0x40+16) /* SET_BLOCKLEN */ 00017 #define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */ 00018 #define CMD24 (0x40+24) /* WRITE_BLOCK */ 00019 #define CMD55 (0x40+55) /* APP_CMD */ 00020 #define CMD58 (0x40+58) /* READ_OCR */ 00021 00022 SPI device(CONNECT_MOSI,CONNECT_MISO,CONNECT_SCK); 00023 DigitalOut cs(CONNECT_CS); 00024 00025 /* Port Controls (Platform dependent) */ 00026 #define SELECT() cs.write(0) /* MMC CS = L */ 00027 #define DESELECT() cs.write(1) /* MMC CS = H */ 00028 #define MMC_SEL !cs.read() /* MMC CS status (true:selected) */ 00029 00030 void xmit_spi (BYTE c) { 00031 device.write(c); /* Send a byte */ 00032 } 00033 00034 BYTE rcv_spi (void) { 00035 return device.write(0xff); 00036 } 00037 00038 /*-------------------------------------------------------------------------- 00039 00040 Module Private Functions 00041 00042 ---------------------------------------------------------------------------*/ 00043 00044 static 00045 BYTE CardType; 00046 00047 00048 /*-----------------------------------------------------------------------*/ 00049 /* Deselect the card and release SPI bus */ 00050 /*-----------------------------------------------------------------------*/ 00051 00052 static 00053 void release_spi (void) { 00054 DESELECT(); 00055 rcv_spi(); 00056 } 00057 00058 00059 /*-----------------------------------------------------------------------*/ 00060 /* Send a command packet to MMC */ 00061 /*-----------------------------------------------------------------------*/ 00062 00063 static 00064 BYTE send_cmd ( 00065 BYTE cmd, /* Command byte */ 00066 DWORD arg /* Argument */ 00067 ) { 00068 BYTE n, res; 00069 00070 00071 if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */ 00072 cmd &= 0x7F; 00073 res = send_cmd(CMD55, 0); 00074 if (res > 1) return res; 00075 } 00076 00077 /* Select the card */ 00078 DESELECT(); 00079 rcv_spi(); 00080 SELECT(); 00081 rcv_spi(); 00082 00083 /* Send a command packet */ 00084 xmit_spi(cmd); /* Start + Command index */ 00085 xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */ 00086 xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */ 00087 xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */ 00088 xmit_spi((BYTE)arg); /* Argument[7..0] */ 00089 n = 0x01; /* Dummy CRC + Stop */ 00090 if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */ 00091 if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */ 00092 xmit_spi(n); 00093 00094 /* Receive a command response */ 00095 n = 10; /* Wait for a valid response in timeout of 10 attempts */ 00096 do { 00097 res = rcv_spi(); 00098 } while ((res & 0x80) && --n); 00099 00100 return res; /* Return with the response value */ 00101 } 00102 00103 00104 00105 /*-------------------------------------------------------------------------- 00106 00107 Public Functions 00108 00109 ---------------------------------------------------------------------------*/ 00110 00111 00112 /*-----------------------------------------------------------------------*/ 00113 /* Initialize Disk Drive */ 00114 /*-----------------------------------------------------------------------*/ 00115 00116 DSTATUS disk_initialize (void) { 00117 BYTE n, cmd, ty, ocr[4]; 00118 WORD tmr; 00119 00120 DESELECT(); 00121 device.format(8); 00122 device.frequency(SPI_FREQ); 00123 00124 #if _WRITE_FUNC 00125 if (MMC_SEL) disk_writep(0, 0); /* Finalize write process if it is in progress */ 00126 #endif 00127 for (n = 100; n; n--) rcv_spi(); /* Dummy clocks */ 00128 00129 ty = 0; 00130 if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ 00131 if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ 00132 for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); /* Get trailing return value of R7 resp */ 00133 if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ 00134 for (tmr = 12000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) ; /* Wait for leaving idle state (ACMD41 with HCS bit) */ 00135 if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ 00136 for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); 00137 ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ 00138 } 00139 } 00140 } else { /* SDv1 or MMCv3 */ 00141 if (send_cmd(ACMD41, 0) <= 1) { 00142 ty = CT_SD1; 00143 cmd = ACMD41; /* SDv1 */ 00144 } else { 00145 ty = CT_MMC; 00146 cmd = CMD1; /* MMCv3 */ 00147 } 00148 for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr--) ; /* Wait for leaving idle state */ 00149 if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ 00150 ty = 0; 00151 } 00152 } 00153 CardType = ty; 00154 release_spi(); 00155 00156 return ty ? 0 : STA_NOINIT; 00157 } 00158 00159 00160 00161 /*-----------------------------------------------------------------------*/ 00162 /* Read partial sector */ 00163 /*-----------------------------------------------------------------------*/ 00164 00165 DRESULT disk_readp ( 00166 BYTE *buff, /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */ 00167 DWORD lba, /* Sector number (LBA) */ 00168 WORD ofs, /* Byte offset to read from (0..511) */ 00169 WORD cnt /* Number of bytes to read (ofs + cnt mus be <= 512) */ 00170 ) { 00171 DRESULT res; 00172 BYTE rc; 00173 WORD bc; 00174 00175 00176 if (!(CardType & CT_BLOCK)) lba *= 512; /* Convert to byte address if needed */ 00177 00178 res = RES_ERROR; 00179 if (send_cmd(CMD17, lba) == 0) { /* READ_SINGLE_BLOCK */ 00180 00181 bc = 30000; 00182 do { /* Wait for data packet in timeout of 100ms */ 00183 rc = rcv_spi(); 00184 } while (rc == 0xFF && --bc); 00185 00186 if (rc == 0xFE) { /* A data packet arrived */ 00187 bc = 514 - ofs - cnt; 00188 00189 /* Skip leading bytes */ 00190 if (ofs) { 00191 do { 00192 rcv_spi(); 00193 } while (--ofs); 00194 } 00195 00196 /* Receive a part of the sector */ 00197 if (buff) { /* Store data to the memory */ 00198 do { 00199 *buff++ = rcv_spi(); 00200 } while (--cnt); 00201 } else { /* Forward data to the outgoing stream (depends on the project) */ 00202 do { 00203 rcv_spi(); 00204 } while (--cnt); 00205 } 00206 00207 /* Skip trailing bytes and CRC */ 00208 do rcv_spi(); 00209 while (--bc); 00210 00211 res = RES_OK; 00212 } 00213 } 00214 00215 release_spi(); 00216 00217 return res; 00218 } 00219 00220 00221 00222 /*-----------------------------------------------------------------------*/ 00223 /* Write partial sector */ 00224 /*-----------------------------------------------------------------------*/ 00225 #if _WRITE_FUNC 00226 00227 DRESULT disk_writep ( 00228 const BYTE *buff, /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */ 00229 DWORD sa /* Number of bytes to send, Sector number (LBA) or zero */ 00230 ) { 00231 DRESULT res; 00232 WORD bc; 00233 static WORD wc; 00234 00235 00236 res = RES_ERROR; 00237 00238 if (buff) { /* Send data bytes */ 00239 bc = (WORD)sa; 00240 while (bc && wc) { /* Send data bytes to the card */ 00241 xmit_spi(*buff++); 00242 wc--; 00243 bc--; 00244 } 00245 res = RES_OK; 00246 } else { 00247 if (sa) { /* Initiate sector write process */ 00248 if (!(CardType & CT_BLOCK)) sa *= 512; /* Convert to byte address if needed */ 00249 if (send_cmd(CMD24, sa) == 0) { /* WRITE_SINGLE_BLOCK */ 00250 xmit_spi(0xFF); 00251 xmit_spi(0xFE); /* Data block header */ 00252 wc = 512; /* Set byte counter */ 00253 res = RES_OK; 00254 } 00255 } else { /* Finalize sector write process */ 00256 bc = wc + 2; 00257 while (bc--) xmit_spi(0); /* Fill left bytes and CRC with zeros */ 00258 if ((rcv_spi() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 300ms */ 00259 for (bc = 65000; rcv_spi() != 0xFF && bc; bc--) ; /* Wait ready */ 00260 if (bc) res = RES_OK; 00261 } 00262 release_spi(); 00263 } 00264 } 00265 00266 return res; 00267 } 00268 #endif
Generated on Mon Jul 18 2022 15:07:54 by
1.7.2