/[projet1]/public/oric/hardware/cumulus/fw/sd-mmc.c
Defence Force logotype

Contents of /public/oric/hardware/cumulus/fw/sd-mmc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 427 - (show annotations)
Tue Feb 8 06:27:16 2011 UTC (9 years, 3 months ago) by retromaster
File MIME type: text/plain
File size: 11846 byte(s)
Added support for 6610 LCDs with Epson controllers.
Added bootloader support.
Misc fixes and cleanups.
1 /* Cumulus 18F46K20 Firmware
2 * SD Card Access Routines.
3 * Copyright 2010 Retromaster.
4 *
5 * This file is part of Cumulus Firmware.
6 *
7 * Cumulus Firmware is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License,
10 * or any later version.
11 *
12 * Cumulus Firmware is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Cumulus Firmware. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "global.h"
22
23 #include "sd-mmc.h"
24 #include "6610.h"
25
26
27 #define SPIDI 6
28 #define SPIDO 5
29 #define SPICLK 7
30 #define SPICS 4
31
32 uint8_t card_type;
33
34 /* SPI Send/Receive byte */
35 static uint8_t SPI(uint8_t d)
36 {
37 char received = 0;
38
39 SSPBUF = d;
40 while (SSPSTATbits.BF != 1);
41 received = SSPBUF;
42
43 return received;
44 }
45
46 //static inline void spi_read_block(uint8_t* buffer)
47 void spi_read_block(uint8_t* buffer)
48 {
49 char received = 0;
50 uint8_t* buffer_end = buffer + 511;
51
52 /* Get the first byte */
53 SSPBUF = 0xFF;
54 while (SSPSTATbits.BF != 1);
55 received = SSPBUF;
56
57 while (1)
58 {
59 SSPBUF = 0xFF;
60 *buffer++ = received;
61 if (buffer == buffer_end)
62 break;
63 while (SSPSTATbits.BF != 1);
64 received = SSPBUF;
65 }
66
67 while (SSPSTATbits.BF != 1);
68 *buffer = SSPBUF;
69 }
70
71 void spi_write_block(uint8_t* buffer)
72 {
73 uint8_t dummy;
74 uint16_t i = 512;
75
76 while (1)
77 {
78 SSPBUF = *buffer++;
79 i --;
80 if (i <= 0)
81 break;
82 while (SSPSTATbits.BF != 1);
83 dummy = SSPBUF;
84 }
85
86 while (SSPSTATbits.BF != 1);
87 dummy = SSPBUF;
88 }
89
90 /* Send a command to SD/MMC */
91 uint8_t card_command(uint8_t cmd, uint16_t addrH, uint16_t addrL, uint8_t crc)
92 {
93 SPI(0xFF);
94 SPI(cmd);
95 SPI((uint8_t) (addrH >> 8));
96 SPI((uint8_t) addrH);
97 SPI((uint8_t) (addrL >> 8));
98 SPI((uint8_t) addrL);
99 SPI(crc);
100 SPI(0xFF);
101 return SPI(0xFF); // return the last received character
102 }
103
104 uint8_t card_set_block_length(uint16_t block_length)
105 {
106 uint16_t timeout_cntr = 0;
107
108 /* Send CMD16 to set block length */
109 uint8_t result = card_command(0x50, 0, block_length, 0xFF);
110 while (result != 0)
111 {
112 result = SPI(0xFF);
113 timeout_cntr ++;
114 if (timeout_cntr > 2000)
115 return 0;
116 }
117
118 /* Done */
119 return 1;
120 }
121
122 /* Initalize SD/MMC Card */
123 uint8_t card_init(void)
124 {
125 uint8_t i;
126 uint16_t timeout_cntr;
127
128 /* Slow clock during card identification */
129 TRISCbits.TRISC3 = 0;
130 TRISCbits.TRISC5 = 0;
131 SSPCON1bits.SSPEN = 0;
132 SSPCON1 = 0x12; // CKP High, SPI Master, clock = Fosc/64
133 SSPSTATbits.SMP = 0;
134 //SSPSTATbits.SMP = 1;
135 SSPSTATbits.CKE = 0;
136 SSPCON1bits.SSPEN = 1;
137
138 /* Raise Chip Select */
139 TRISCbits.TRISC2 = 0;
140 PORTCbits.RC2 = 1;
141
142 /* Switch card to SPI Mode */
143 for(i = 0; i < 10; i ++)
144 SPI(0xFF);
145
146 /* Lower Chip Select */
147 PORTCbits.RC2 = 0;
148
149 /* Send CMD0 */
150 if (card_command(0x40, 0x0000, 0x0000, 0x95) != 0x01)
151 return 0;
152
153 card_type = CARD_TYPE_SD;
154 if ((card_command(0x48, 0x0000, 0x1AA, 0x87) & 4) == 0)
155 {
156 SPI(0xFF);
157 SPI(0xFF);
158 if ((SPI(0xFF) & 1) == 0)
159 return 0;
160 if (SPI(0xFF) != 0xAA)
161 return 0;
162
163 /* Send ACMD41 */
164 timeout_cntr = 0;
165 while (1)
166 {
167 uint8_t result;
168
169 card_command(0x77, 0x0000, 0x0000, 0xFF);
170 result = card_command(0x69, 0x4000, 0x0000, 0xFF);
171 if (result == 0x00)
172 break;
173
174 timeout_cntr ++;
175 if (timeout_cntr > 20000)
176 return 0;
177 }
178
179 /* Send CMD58 */
180 if (card_command(0x7A, 0x0000, 0x0000, 0xFF))
181 return 0;
182
183 if(SPI(0xFF) & 0x40)
184 card_type = CARD_TYPE_SDHC;
185
186 SPI(0xFF);
187 SPI(0xFF);
188 SPI(0xFF);
189 }
190 else
191 {
192 /* Send CMD1 */
193 timeout_cntr = 0;
194 while (card_command(0x41, 0x0000, 0x0000, 0xFF) != 0x00)
195 {
196 timeout_cntr ++;
197 if (timeout_cntr > 20000)
198 return 0;
199 }
200 }
201
202 /* Set default block length of 512 */
203 if (!card_set_block_length(512))
204 return 0;
205
206 /* Raise Chip Select */
207 PORTCbits.RC2 = 1;
208
209 /* Speed up the clock */
210 SSPCON1bits.SSPEN = 0;
211 //SSPCON1 = 0x11; // CKP High, SPI Master, clock = Fosc/16
212 SSPCON1 = 0x10; // CKP High, SPI Master, clock = Fosc/4
213 SSPSTATbits.SMP = 0;
214 //SSPSTATbits.SMP = 1;
215 SSPSTATbits.CKE = 0;
216 SSPCON1bits.SSPEN = 1;
217
218 return 1;
219 }
220
221 /* Reads one sector of 512 bytes from the card */
222 uint8_t card_read(uint32_t sector, uint8_t* buffer)
223 {
224 uint16_t i;
225 uint8_t result;
226 uint16_t timeout_cntr;
227 uint8_t card_response;
228
229 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
230
231 /* Lower Chip Select */
232 PORTCbits.RC2 = 0;
233
234 /* Send CMD17 */
235 timeout_cntr = 0;
236 result = card_command(0x51, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
237
238 while (result != 0)
239 {
240 result = SPI(0xFF);
241 timeout_cntr ++;
242 if (timeout_cntr > 48000)
243 return 0;
244 }
245
246 /* Wait until 0xFE is received */
247 timeout_cntr = 0;
248 while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF)
249 {
250 timeout_cntr ++;
251 if (timeout_cntr > 48000)
252 return 0;
253 }
254
255 if (card_response != 0xFE)
256 return 0;
257
258 /* Read data */
259 for(i = 0; i < 512; i ++)
260 buffer[i] = SPI(0xFF);
261
262 /* Receive CRC */
263 SPI(0xFF);
264 SPI(0xFF);
265
266 /* Let the card finish */
267 SPI(0xFF);
268
269 return 1;
270 }
271
272 /* Verifies one sector of 512 bytes on the card */
273 uint8_t card_verify(uint32_t sector, uint8_t* buffer)
274 {
275 uint16_t i;
276 uint8_t result;
277 uint16_t timeout_cntr;
278 uint8_t card_response;
279 uint8_t match;
280
281 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
282
283 /* Lower Chip Select */
284 PORTCbits.RC2 = 0;
285
286 /* Send CMD17 */
287 timeout_cntr = 0;
288 result = card_command(0x51, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
289
290 while (result != 0)
291 {
292 result = SPI(0xFF);
293 timeout_cntr ++;
294 if (timeout_cntr > 48000)
295 return 0;
296 }
297
298 /* Wait until 0xFE is received */
299 timeout_cntr = 0;
300 while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF)
301 {
302 timeout_cntr ++;
303 if (timeout_cntr > 48000)
304 return 0;
305 }
306
307 if (card_response != 0xFE)
308 return 0;
309
310 /* Read data */
311 match = 1;
312 for(i = 0; i < 512; i ++)
313 if (buffer[i] != SPI(0xFF))
314 match = 0;
315
316 /* Receive CRC */
317 SPI(0xFF);
318 SPI(0xFF);
319
320 /* Let the card finish */
321 SPI(0xFF);
322
323 return match;
324 }
325
326 /* Reads part of one sector from the card */
327 uint8_t card_read_sub(uint32_t sector, uint16_t offset, uint16_t length, uint8_t* buffer)
328 {
329 uint16_t i;
330 uint8_t dummy;
331 uint8_t result;
332 uint16_t timeout_cntr;
333 uint8_t card_response;
334
335 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
336
337 /* Send CMD17 */
338 timeout_cntr = 0;
339 result = card_command(0x51, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
340
341 while (result != 0)
342 {
343 result = SPI(0xFF);
344 timeout_cntr ++;
345 if (timeout_cntr > 48000)
346 return 0;
347 }
348
349 /* Wait until 0xFE is received */
350 timeout_cntr = 0;
351 while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF)
352 {
353 timeout_cntr ++;
354 if (timeout_cntr > 48000)
355 return 0;
356 }
357
358 if (card_response != 0xFE)
359 return 0;
360
361 /* Discard bytes until offset */
362 for(i = 0; i < offset; i ++)
363 dummy = SPI(0xFF);
364
365 /* Read data */
366 for(i = 0; i < length; i ++)
367 buffer[i] = SPI(0xFF);
368
369 /* Discard the rest */
370 for(i = offset + length; i < 512; i ++)
371 dummy = SPI(0xFF);
372
373 /* Receive CRC */
374 SPI(0xFF);
375 SPI(0xFF);
376
377 /* Let the card finish */
378 SPI(0xFF);
379
380 return 1;
381 }
382
383 /* Reads multiple sectors of 512 bytes from the card */
384 uint8_t card_read_multi(uint32_t sector, uint8_t* buffer, uint8_t count)
385 {
386 uint8_t result;
387 uint16_t timeout_cntr;
388 uint8_t card_response;
389
390 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
391
392 /* Send CMD18 */
393 timeout_cntr = 0;
394 result = card_command(0x52, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
395
396 while (result != 0)
397 {
398 result = SPI(0xFF);
399 timeout_cntr ++;
400 if (timeout_cntr > 48000)
401 return 0;
402 }
403
404 while (count)
405 {
406 /* Wait until 0xFE is received */
407 timeout_cntr = 0;
408 while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF)
409 {
410 timeout_cntr ++;
411 if (timeout_cntr > 48000)
412 return 0;
413 }
414
415 if (card_response != 0xFE)
416 return 0;
417
418 /* Read data */
419 /*for(uint8_t i = 0; i < 512; i ++)
420 buffer[i] = SPI(0xFF); */
421 spi_read_block(buffer);
422
423 /* Receive CRC */
424 SPI(0xFF);
425 SPI(0xFF);
426
427 /* Let the card finish */
428 SPI(0xFF);
429
430 buffer += 512;
431 count --;
432 }
433
434 /* Send CMD12 */
435 result = card_command(0x4C, 0, 0, 0xFF);
436 while (result != 0)
437 {
438 result = SPI(0xFF);
439 timeout_cntr ++;
440 if (timeout_cntr > 48000)
441 return 0;
442 }
443
444 /* Wait until the MMC is no longer busy */
445 while(SPI(0xFF) != 0xFF);
446
447 return 1;
448 }
449
450 /* Writes one sector of 512 bytes to the card */
451 uint8_t card_write(uint32_t sector, uint8_t* buffer)
452 {
453 uint16_t i;
454 uint8_t result;
455 uint16_t timeout_cntr;
456 uint8_t card_response;
457
458 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
459
460 /* Send CMD24 */
461 timeout_cntr = 0;
462 result = card_command(0x58, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
463
464 while (result != 0)
465 {
466 result = SPI(0xFF);
467 timeout_cntr ++;
468 if (timeout_cntr > 48000)
469 return 0;
470 }
471
472 SPI(0xFF);
473 SPI(0xFF);
474 SPI(0xFE);
475
476 /* Send data */
477 for (i = 0; i < 512; i ++)
478 SPI(buffer[i]);
479
480 /* Send 2 dummy bytes */
481 SPI(0xFF);
482 SPI(0xFF);
483
484 card_response = SPI(0xFF);
485 card_response &= 0x1F;
486 if (card_response != 0x05)
487 {
488 /* Write error */
489 return 0;
490 }
491
492 /* Wait until the MMC is no longer busy */
493 while(SPI(0xFF) != 0xFF);
494
495 return 1;
496 }
497
498 /* Writes multiple sectors of 512 bytes to the card */
499 uint8_t card_write_multi(uint32_t sector, uint8_t* buffer, uint8_t count)
500 {
501 uint8_t result;
502 uint16_t timeout_cntr;
503 uint8_t card_response;
504
505 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
506
507 /* Send CMD25 */
508 timeout_cntr = 0;
509 result = card_command(0x59, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
510
511 while (result != 0)
512 {
513 result = SPI(0xFF);
514 timeout_cntr ++;
515 if (timeout_cntr > 48000)
516 return 0;
517 }
518
519 while (count)
520 {
521 /* Start of block */
522 SPI(0xFC);
523
524 /* Send data */
525 /*for (i = 0; i < 512; i ++)
526 SPI(buffer[i]);*/
527 spi_write_block(buffer);
528
529 /* Send 2 dummy bytes */
530 SPI(0xFF);
531 SPI(0xFF);
532
533 card_response = SPI(0xFF);
534 card_response &= 0x1F;
535 if (card_response != 0x05)
536 {
537 /* Write error */
538 return 0;
539 }
540
541 /* Wait until the MMC is no longer busy */
542 while(SPI(0xFF) != 0xFF);
543
544 /* Extra 8 bits */
545 SPI(0xFF);
546 count --;
547 buffer += 512;
548 }
549
550 /* Send CMD12 */
551 result = card_command(0x4C, 0, 0, 0xFF);
552 while (result != 0)
553 {
554 result = SPI(0xFF);
555 timeout_cntr ++;
556 if (timeout_cntr > 48000)
557 return 0;
558 }
559
560 /* Wait until the MMC is no longer busy */
561 while(SPI(0xFF) != 0xFF);
562
563 /* Send CMD13 */
564 result = card_command(0x4D, 0, 0, 0xFF);
565 while (result != 0)
566 {
567 result = SPI(0xFF);
568 timeout_cntr ++;
569 if (timeout_cntr > 48000)
570 return 0;
571 }
572 SPI(0xFF); // Second byte.
573 SPI(0xFF);
574
575 return 1;
576
577 }
578

  ViewVC Help
Powered by ViewVC 1.1.26