1 | /*#######################################################################################
|
2 | Connect AVR to MMC/SD
|
3 |
|
4 | Copyright (C) 2004 Ulrich Radig
|
5 |
|
6 | Bei Fragen und Verbesserungen wendet euch per EMail an
|
7 |
|
8 | mail@ulrichradig.de
|
9 |
|
10 | oder im Forum meiner Web Page : www.ulrichradig.de
|
11 |
|
12 | Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
|
13 | GNU General Public License, wie von der Free Software Foundation veröffentlicht,
|
14 | weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
|
15 | (nach Ihrer Option) jeder späteren Version.
|
16 |
|
17 | Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
|
18 | daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
|
19 | sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
|
20 | FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
|
21 |
|
22 | Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
|
23 | Programm erhalten haben.
|
24 | Falls nicht, schreiben Sie an die Free Software Foundation,
|
25 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
26 | #######################################################################################*/
|
27 |
|
28 | #include "mmc.h"
|
29 |
|
30 | //############################################################################
|
31 | //Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
|
32 | unsigned char mmc_init ()
|
33 | //############################################################################
|
34 | {
|
35 | unsigned int Timeout = 0;
|
36 |
|
37 | //Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
|
38 | MMC_Direction_REG &=~(1<<SPI_DI); //Setzen von Pin MMC_DI auf Input
|
39 | MMC_Direction_REG |= (1<<SPI_Clock); //Setzen von Pin MMC_Clock auf Output
|
40 | MMC_Direction_REG |= (1<<SPI_DO); //Setzen von Pin MMC_DO auf Output
|
41 | MMC_Direction_REG |= (1<<MMC_Chip_Select); //Setzen von Pin MMC_Chip_Select auf Output
|
42 | MMC_Direction_REG |= (1<<SPI_SSSD);
|
43 | MMC_Write |= (1<<MMC_Chip_Select); //Setzt den Pin MMC_Chip_Select auf High Pegel
|
44 |
|
45 | for(unsigned char a=0;a<200;a++){
|
46 | nop();
|
47 | }; //Wartet eine kurze Zeit
|
48 |
|
49 | #if SPI_Mode
|
50 | //Aktiviren des SPI - Bus, Clock = Idel LOW
|
51 | //SPI Clock teilen durch 128
|
52 | SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode
|
53 | SPSR = (0<<SPI2X);
|
54 | #endif
|
55 |
|
56 | //Initialisiere MMC/SD-Karte in den SPI-Mode
|
57 | for (unsigned char b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte
|
58 | {
|
59 | mmc_write_byte(0xff);
|
60 | }
|
61 |
|
62 | //Sendet Commando CMD0 an MMC/SD-Karte
|
63 | unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
|
64 | while(mmc_write_command (CMD) !=1)
|
65 | {
|
66 | if (Timeout++ > 200)
|
67 | {
|
68 | MMC_Disable();
|
69 | return(1); //Abbruch bei Commando1 (Return Code1)
|
70 | }
|
71 | }
|
72 | //Sendet Commando CMD1 an MMC/SD-Karte
|
73 | Timeout = 0;
|
74 | CMD[0] = 0x41;//Commando 1
|
75 | CMD[5] = 0xFF;
|
76 | while( mmc_write_command (CMD) !=0)
|
77 | {
|
78 | if (Timeout++ > 400)
|
79 | {
|
80 | MMC_Disable();
|
81 | return(2); //Abbruch bei Commando2 (Return Code2)
|
82 | }
|
83 | }
|
84 | #if SPI_Mode
|
85 | //SPI Bus auf max Geschwindigkeit
|
86 | SPCR &= ~((1<<SPR0) | (1<<SPR1));
|
87 | SPSR = SPSR|(1<<SPI2X);
|
88 | #endif
|
89 |
|
90 | //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
91 | MMC_Disable();
|
92 | return(0);
|
93 | }
|
94 |
|
95 | //############################################################################
|
96 | //Sendet ein Commando an die MMC/SD-Karte
|
97 | unsigned char mmc_write_command (unsigned char *cmd)
|
98 | //############################################################################
|
99 | {
|
100 | unsigned char tmp = 0xff;
|
101 | unsigned int Timeout = 0;
|
102 |
|
103 | //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
104 | MMC_Disable();
|
105 |
|
106 | //sendet 8 Clock Impulse
|
107 | mmc_write_byte(0xFF);
|
108 |
|
109 | //set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
|
110 | MMC_Enable();
|
111 |
|
112 | //sendet 6 Byte Commando
|
113 | for (unsigned char a = 0;a<0x06;a++) //sendet 6 Byte Commando zur MMC/SD-Karte
|
114 | {
|
115 | mmc_write_byte(*cmd++);
|
116 | }
|
117 |
|
118 | //Wartet auf ein gültige Antwort von der MMC/SD-Karte
|
119 | while (tmp == 0xff)
|
120 | {
|
121 | tmp = mmc_read_byte();
|
122 | if (Timeout++ > 500)
|
123 | {
|
124 | break; //Abbruch da die MMC/SD-Karte nicht Antwortet
|
125 | }
|
126 | }
|
127 | return(tmp);
|
128 | }
|
129 |
|
130 | //############################################################################
|
131 | //Routine zum Empfangen eines Bytes von der MMC-Karte
|
132 | unsigned char mmc_read_byte (void)
|
133 | //############################################################################
|
134 | {
|
135 | unsigned char Byte = 0;
|
136 | #if SPI_Mode //Routine für Hardware SPI
|
137 | SPDR = 0xff;
|
138 | while(!(SPSR & (1<<SPIF))){};
|
139 | Byte = SPDR;
|
140 |
|
141 | #else //Routine für Software SPI
|
142 | for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First
|
143 | {
|
144 | MMC_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)
|
145 |
|
146 | if (bit_is_set(MMC_Read,SPI_DI) > 0) //Lesen des Pegels von MMC_DI
|
147 | {
|
148 | Byte |= (1<<(a-1));
|
149 | }
|
150 | else
|
151 | {
|
152 | Byte &=~(1<<(a-1));
|
153 | }
|
154 | MMC_Write |=(1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)
|
155 | }
|
156 | #endif
|
157 | return (Byte);
|
158 | }
|
159 |
|
160 |
|
161 | //############################################################################
|
162 | //Routine zum Senden eines Bytes zur MMC-Karte
|
163 | void mmc_write_byte (unsigned char Byte)
|
164 | //############################################################################
|
165 | {
|
166 | #if SPI_Mode //Routine für Hardware SPI
|
167 | SPDR = Byte; //Sendet ein Byte
|
168 | while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde
|
169 | {
|
170 | }
|
171 | #else //Routine für Software SPI
|
172 | for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First
|
173 | {
|
174 | if (bit_is_set(Byte,(a-1))>0) //Ist Bit a in Byte gesetzt
|
175 | {
|
176 | MMC_Write |= (1<<SPI_DO); //Set Output High
|
177 | }
|
178 | else
|
179 | {
|
180 | MMC_Write &= ~(1<<SPI_DO); //Set Output Low
|
181 | }
|
182 | MMC_Write &= ~(1<<SPI_Clock); //erzeugt ein Clock Impuls (LOW)
|
183 |
|
184 | MMC_Write |= (1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)
|
185 | }
|
186 | MMC_Write |= (1<<SPI_DO); //setzt Output wieder auf High
|
187 | #endif
|
188 | }
|
189 |
|
190 | //############################################################################
|
191 | //Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
|
192 | unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
|
193 | //############################################################################
|
194 | {
|
195 | unsigned char tmp;
|
196 | //Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
|
197 | unsigned char cmd[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
|
198 |
|
199 | /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
|
200 | addr wird von Blocks zu Bytes umgerechnet danach werden
|
201 | diese in das Commando eingefügt*/
|
202 |
|
203 | addr = addr << 9; //addr = addr * 512
|
204 |
|
205 | cmd[1] = ((addr & 0xFF000000) >>24 );
|
206 | cmd[2] = ((addr & 0x00FF0000) >>16 );
|
207 | cmd[3] = ((addr & 0x0000FF00) >>8 );
|
208 |
|
209 | //Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes)
|
210 | tmp = mmc_write_command (cmd);
|
211 | if (tmp != 0)
|
212 | {
|
213 | return(tmp);
|
214 | }
|
215 |
|
216 | //Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte
|
217 | for (unsigned char a=0;a<100;a++)
|
218 | {
|
219 | mmc_read_byte();
|
220 | }
|
221 |
|
222 | //Sendet Start Byte an MMC/SD-Karte
|
223 | mmc_write_byte(0xFE);
|
224 |
|
225 | //Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
|
226 | for (unsigned int a=0;a<512;a++)
|
227 | {
|
228 | mmc_write_byte(*Buffer++);
|
229 | }
|
230 |
|
231 | //CRC-Byte schreiben
|
232 | mmc_write_byte(0xFF); //Schreibt Dummy CRC
|
233 | mmc_write_byte(0xFF); //CRC Code wird nicht benutzt
|
234 |
|
235 | //Fehler beim schreiben? (Data Response XXX00101 = OK)
|
236 | if((mmc_read_byte()&0x1F) != 0x05) return(1);
|
237 |
|
238 | //Wartet auf MMC/SD-Karte Bussy
|
239 | while (mmc_read_byte() != 0xff){};
|
240 |
|
241 | //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
242 | MMC_Disable();
|
243 |
|
244 | return(0);
|
245 | }
|
246 |
|
247 | //############################################################################
|
248 | //Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
|
249 | void mmc_read_block(unsigned char *cmd,unsigned char *Buffer,unsigned int Bytes)
|
250 | //############################################################################
|
251 | {
|
252 | //Sendet Commando cmd an MMC/SD-Karte
|
253 | if (mmc_write_command (cmd) != 0)
|
254 | {
|
255 | return;
|
256 | }
|
257 |
|
258 | //Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
|
259 |
|
260 | while (mmc_read_byte() != 0xfe){};
|
261 |
|
262 | //Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte
|
263 | for (unsigned int a=0;a<Bytes;a++)
|
264 | {
|
265 | *Buffer++ = mmc_read_byte();
|
266 | }
|
267 | //CRC-Byte auslesen
|
268 | mmc_read_byte();//CRC - Byte wird nicht ausgewertet
|
269 | mmc_read_byte();//CRC - Byte wird nicht ausgewertet
|
270 |
|
271 | //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
272 | MMC_Disable();
|
273 |
|
274 | return;
|
275 | }
|
276 |
|
277 | //############################################################################
|
278 | //Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
|
279 | unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
|
280 | //############################################################################
|
281 | {
|
282 | //Commando 16 zum lesen eines Blocks von der MMC/SD - Karte
|
283 | unsigned char cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
|
284 |
|
285 | /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
|
286 | addr wird von Blocks zu Bytes umgerechnet danach werden
|
287 | diese in das Commando eingefügt*/
|
288 |
|
289 | addr = addr << 9; //addr = addr * 512
|
290 |
|
291 | cmd[1] = ((addr & 0xFF000000) >>24 );
|
292 | cmd[2] = ((addr & 0x00FF0000) >>16 );
|
293 | cmd[3] = ((addr & 0x0000FF00) >>8 );
|
294 |
|
295 | mmc_read_block(cmd,Buffer,512);
|
296 |
|
297 | return(0);
|
298 | }
|
299 |
|
300 | //############################################################################
|
301 | //Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
|
302 | unsigned char mmc_read_cid (unsigned char *Buffer)
|
303 | //############################################################################
|
304 | {
|
305 | //Commando zum lesen des CID Registers
|
306 | unsigned char cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
|
307 |
|
308 | mmc_read_block(cmd,Buffer,16);
|
309 |
|
310 | return(0);
|
311 | }
|
312 |
|
313 | //############################################################################
|
314 | //Routine zum lesen des CSD Registers von der MMC/SD-Karte (16Bytes)
|
315 | unsigned char mmc_read_csd (unsigned char *Buffer)
|
316 | //############################################################################
|
317 | {
|
318 | //Commando zum lesen des CSD Registers
|
319 | unsigned char cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
|
320 |
|
321 | mmc_read_block(cmd,Buffer,16);
|
322 |
|
323 | return(0);
|
324 | }
|