PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Dependents: YATTT sd_map_test cPong SnowDemo ... more
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 11:20:33 by 1.7.2