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.
Fork of PokittoLib by
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 #include "PokittoDisk.h " 00011 00012 /* Definitions for MMC/SDC command */ 00013 #define CMD0 (0x40+0) /* GO_IDLE_STATE */ 00014 #define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */ 00015 #define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */ 00016 #define CMD8 (0x40+8) /* SEND_IF_COND */ 00017 #define CMD16 (0x40+16) /* SET_BLOCKLEN */ 00018 #define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */ 00019 #define CMD24 (0x40+24) /* WRITE_BLOCK */ 00020 #define CMD55 (0x40+55) /* APP_CMD */ 00021 #define CMD58 (0x40+58) /* READ_OCR */ 00022 00023 00024 00025 /* Port Controls (Platform dependent) */ 00026 #define SELECT() CLR_SD_CS //mmccs.write(0) /* MMC CS = L */ 00027 #define DESELECT() SET_SD_CS // mmccs.write(1) /* MMC CS = H */ 00028 #define MMC_SEL !GET_SD_CS // !mmccs.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 //__attribute__((section(".SD_Code"))) 00117 DSTATUS disk_initialize (void) { 00118 BYTE n, cmd, ty, ocr[4]; 00119 WORD tmr; 00120 00121 DESELECT(); 00122 device.frequency(SPI_FREQ); 00123 device.format(8); 00124 // device.frequency(SPI_FREQ); // hangs if this is after format 00125 00126 #if _WRITE_FUNC 00127 if (MMC_SEL) disk_writep(0, 0); /* Finalize write process if it is in progress */ 00128 #endif 00129 for (n = 100; n; n--) rcv_spi(); /* Dummy clocks */ 00130 00131 ty = 0; 00132 if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ 00133 if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ 00134 for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); /* Get trailing return value of R7 resp */ 00135 if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ 00136 for (tmr = 12000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) ; /* Wait for leaving idle state (ACMD41 with HCS bit) */ 00137 if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ 00138 for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); 00139 ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ 00140 } 00141 } 00142 } else { /* SDv1 or MMCv3 */ 00143 if (send_cmd(ACMD41, 0) <= 1) { 00144 ty = CT_SD1; 00145 cmd = ACMD41; /* SDv1 */ 00146 } else { 00147 ty = CT_MMC; 00148 cmd = CMD1; /* MMCv3 */ 00149 } 00150 for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr--) ; /* Wait for leaving idle state */ 00151 if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ 00152 ty = 0; 00153 } 00154 } 00155 CardType = ty; 00156 release_spi(); 00157 00158 return ty ? 0 : STA_NOINIT; 00159 } 00160 00161 00162 00163 /*-----------------------------------------------------------------------*/ 00164 /* Read partial sector */ 00165 /*-----------------------------------------------------------------------*/ 00166 00167 DRESULT disk_readp ( 00168 BYTE *buff, /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */ 00169 DWORD lba, /* Sector number (LBA) */ 00170 WORD ofs, /* Byte offset to read from (0..511) */ 00171 WORD cnt /* Number of bytes to read (ofs + cnt mus be <= 512) */ 00172 ) { 00173 DRESULT res; 00174 BYTE rc; 00175 WORD bc; 00176 00177 00178 if (!(CardType & CT_BLOCK)) lba *= 512; /* Convert to byte address if needed */ 00179 00180 res = RES_ERROR; 00181 if (send_cmd(CMD17, lba) == 0) { /* READ_SINGLE_BLOCK */ 00182 00183 bc = 30000; 00184 do { /* Wait for data packet in timeout of 100ms */ 00185 rc = rcv_spi(); 00186 } while (rc == 0xFF && --bc); 00187 00188 if (rc == 0xFE) { /* A data packet arrived */ 00189 bc = 514 - ofs - cnt; 00190 00191 /* Skip leading bytes */ 00192 if (ofs) { 00193 do { 00194 rcv_spi(); 00195 } while (--ofs); 00196 } 00197 00198 /* Receive a part of the sector */ 00199 if (buff) { /* Store data to the memory */ 00200 do { 00201 *buff++ = rcv_spi(); 00202 } while (--cnt); 00203 } else { /* Forward data to the outgoing stream (depends on the project) */ 00204 do { 00205 rcv_spi(); 00206 } while (--cnt); 00207 } 00208 00209 /* Skip trailing bytes and CRC */ 00210 do rcv_spi(); 00211 while (--bc); 00212 00213 res = RES_OK; 00214 } 00215 } 00216 00217 release_spi(); 00218 00219 return res; 00220 } 00221 00222 00223 00224 /*-----------------------------------------------------------------------*/ 00225 /* Write partial sector */ 00226 /*-----------------------------------------------------------------------*/ 00227 #if _WRITE_FUNC 00228 00229 DRESULT disk_writep ( 00230 const BYTE *buff, /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */ 00231 DWORD sa /* Number of bytes to send, Sector number (LBA) or zero */ 00232 ) { 00233 DRESULT res; 00234 WORD bc; 00235 static WORD wc; 00236 00237 00238 res = RES_ERROR; 00239 00240 if (buff) { /* Send data bytes */ 00241 bc = (WORD)sa; 00242 while (bc && wc) { /* Send data bytes to the card */ 00243 xmit_spi(*buff++); 00244 wc--; 00245 bc--; 00246 } 00247 res = RES_OK; 00248 } else { 00249 if (sa) { /* Initiate sector write process */ 00250 if (!(CardType & CT_BLOCK)) sa *= 512; /* Convert to byte address if needed */ 00251 if (send_cmd(CMD24, sa) == 0) { /* WRITE_SINGLE_BLOCK */ 00252 xmit_spi(0xFF); 00253 xmit_spi(0xFE); /* Data block header */ 00254 wc = 512; /* Set byte counter */ 00255 res = RES_OK; 00256 } 00257 } else { /* Finalize sector write process */ 00258 bc = wc + 2; 00259 while (bc--) xmit_spi(0); /* Fill left bytes and CRC with zeros */ 00260 if ((rcv_spi() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 300ms */ 00261 for (bc = 65000; rcv_spi() != 0xFF && bc; bc--) ; /* Wait ready */ 00262 if (bc) res = RES_OK; 00263 } 00264 release_spi(); 00265 } 00266 } 00267 00268 return res; 00269 } 00270 #endif 00271
Generated on Tue Jul 12 2022 18:08:12 by
1.7.2
