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