/[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 423 - (show annotations)
Mon Jan 24 12:19:33 2011 UTC (9 years, 4 months ago) by retromaster
File MIME type: text/plain
File size: 13109 byte(s)
Initial add of 18F46K20 firmware sources.
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 {
152 n6610_debug_message((const far rom char*) "Card Init Error (1)");
153 return 0;
154 }
155
156 card_type = CARD_TYPE_SD;
157 if ((card_command(0x48, 0x0000, 0x1AA, 0x87) & 4) == 0)
158 {
159 SPI(0xFF);
160 SPI(0xFF);
161 if ((SPI(0xFF) & 1) == 0)
162 {
163 n6610_debug_message((const far rom char*) "Card Init Error (2)");
164 return 0;
165 }
166 if (SPI(0xFF) != 0xAA)
167 {
168 n6610_debug_message((const far rom char*) "Card Init Error (3)");
169 return 0;
170 }
171
172 /* Send ACMD41 */
173 timeout_cntr = 0;
174 while (1)
175 {
176 uint8_t result;
177
178 card_command(0x77, 0x0000, 0x0000, 0xFF);
179 result = card_command(0x69, 0x4000, 0x0000, 0xFF);
180 if (result == 0x00)
181 break;
182
183 timeout_cntr ++;
184 if (timeout_cntr > 20000)
185 {
186 n6610_debug_message((const far rom char*) "Card Init Error (4)");
187 return 0;
188 }
189 }
190
191 /* Send CMD58 */
192 if (card_command(0x7A, 0x0000, 0x0000, 0xFF))
193 {
194 n6610_debug_message((const far rom char*) "Card Init Error (5)");
195 return 0;
196 }
197
198 if(SPI(0xFF) & 0x40)
199 {
200 n6610_debug_message((const far rom char*) "Card Type SDHC");
201 card_type = CARD_TYPE_SDHC;
202 }
203
204 SPI(0xFF);
205 SPI(0xFF);
206 SPI(0xFF);
207 }
208 else
209 {
210 /* Send CMD1 */
211 timeout_cntr = 0;
212 while (card_command(0x41, 0x0000, 0x0000, 0xFF) != 0x00)
213 {
214 timeout_cntr ++;
215 if (timeout_cntr > 20000)
216 {
217 n6610_debug_message((const far rom char*) "Card Init Error (6)");
218 return 0;
219 }
220 }
221 }
222
223 /* Set default block length of 512 */
224 if (!card_set_block_length(512))
225 {
226 n6610_debug_message((const far rom char*) "Card Init Error (7)");
227 return 0;
228 }
229
230 /* Raise Chip Select */
231 PORTCbits.RC2 = 1;
232
233 /* Speed up the clock */
234 SSPCON1bits.SSPEN = 0;
235 //SSPCON1 = 0x11; // CKP High, SPI Master, clock = Fosc/16
236 SSPCON1 = 0x10; // CKP High, SPI Master, clock = Fosc/4
237 SSPSTATbits.SMP = 0;
238 //SSPSTATbits.SMP = 1;
239 SSPSTATbits.CKE = 0;
240 SSPCON1bits.SSPEN = 1;
241
242 return 1;
243 }
244
245 /* Reads one sector of 512 bytes from the card */
246 uint8_t card_read(uint32_t sector, uint8_t* buffer)
247 {
248 uint16_t i;
249 uint8_t result;
250 uint16_t timeout_cntr;
251 uint8_t card_response;
252
253 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
254
255 /* Lower Chip Select */
256 PORTCbits.RC2 = 0;
257
258 /* Send CMD17 */
259 timeout_cntr = 0;
260 result = card_command(0x51, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
261
262 while (result != 0)
263 {
264 result = SPI(0xFF);
265 timeout_cntr ++;
266 if (timeout_cntr > 48000)
267 {
268 n6610_debug_message((const far rom char*) "Card Read Fail (1)");
269 return 0;
270 }
271 }
272
273 /* Wait until 0xFE is received */
274 timeout_cntr = 0;
275 while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF)
276 {
277 timeout_cntr ++;
278 if (timeout_cntr > 48000)
279 {
280 n6610_debug_message((const far rom char*) "Card Read Fail (2)");
281 return 0;
282 }
283 }
284
285 if (card_response != 0xFE)
286 {
287 n6610_debug_message((const far rom char*) "Card Read Fail (3)");
288 n6610_debug((const far rom char*) "Card Response", card_response);
289 return 0;
290 }
291
292 /* Read data */
293 for(i = 0; i < 512; i ++)
294 buffer[i] = SPI(0xFF);
295
296 /* Receive CRC */
297 SPI(0xFF);
298 SPI(0xFF);
299
300 /* Let the card finish */
301 SPI(0xFF);
302
303 return 1;
304 }
305
306 /* Verifies one sector of 512 bytes on the card */
307 uint8_t card_verify(uint32_t sector, uint8_t* buffer)
308 {
309 uint16_t i;
310 uint8_t result;
311 uint16_t timeout_cntr;
312 uint8_t card_response;
313 uint8_t match;
314
315 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
316
317 /* Lower Chip Select */
318 PORTCbits.RC2 = 0;
319
320 /* Send CMD17 */
321 timeout_cntr = 0;
322 result = card_command(0x51, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
323
324 while (result != 0)
325 {
326 result = SPI(0xFF);
327 timeout_cntr ++;
328 if (timeout_cntr > 48000)
329 {
330 n6610_debug_message((const far rom char*) "Card Read Fail (1)");
331 return 0;
332 }
333 }
334
335 /* Wait until 0xFE is received */
336 timeout_cntr = 0;
337 while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF)
338 {
339 timeout_cntr ++;
340 if (timeout_cntr > 48000)
341 {
342 n6610_debug_message((const far rom char*) "Card Read Fail (2)");
343 return 0;
344 }
345 }
346
347 if (card_response != 0xFE)
348 {
349 n6610_debug_message((const far rom char*) "Card Read Fail (3)");
350 n6610_debug((const far rom char*) "Card Response", card_response);
351 return 0;
352 }
353
354 /* Read data */
355 match = 1;
356 for(i = 0; i < 512; i ++)
357 if (buffer[i] != SPI(0xFF))
358 match = 0;
359
360 /* Receive CRC */
361 SPI(0xFF);
362 SPI(0xFF);
363
364 /* Let the card finish */
365 SPI(0xFF);
366
367 return match;
368 }
369
370 /* Reads part of one sector from the card */
371 uint8_t card_read_sub(uint32_t sector, uint16_t offset, uint16_t length, uint8_t* buffer)
372 {
373 uint16_t i;
374 uint8_t dummy;
375 uint8_t result;
376 uint16_t timeout_cntr;
377 uint8_t card_response;
378
379 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
380
381 /* Send CMD17 */
382 timeout_cntr = 0;
383 result = card_command(0x51, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
384
385 while (result != 0)
386 {
387 result = SPI(0xFF);
388 timeout_cntr ++;
389 if (timeout_cntr > 48000)
390 return 0;
391 }
392
393 /* Wait until 0xFE is received */
394 timeout_cntr = 0;
395 while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF)
396 {
397 timeout_cntr ++;
398 if (timeout_cntr > 48000)
399 return 0;
400 }
401
402 if (card_response != 0xFE)
403 return 0;
404
405 /* Discard bytes until offset */
406 for(i = 0; i < offset; i ++)
407 dummy = SPI(0xFF);
408
409 /* Read data */
410 for(i = 0; i < length; i ++)
411 buffer[i] = SPI(0xFF);
412
413 /* Discard the rest */
414 for(i = offset + length; i < 512; i ++)
415 dummy = SPI(0xFF);
416
417 /* Receive CRC */
418 SPI(0xFF);
419 SPI(0xFF);
420
421 /* Let the card finish */
422 SPI(0xFF);
423
424 return 1;
425 }
426
427 /* Reads multiple sectors of 512 bytes from the card */
428 uint8_t card_read_multi(uint32_t sector, uint8_t* buffer, uint8_t count)
429 {
430 uint8_t result;
431 uint16_t timeout_cntr;
432 uint8_t card_response;
433
434 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
435
436 /* Send CMD18 */
437 timeout_cntr = 0;
438 result = card_command(0x52, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
439
440 while (result != 0)
441 {
442 result = SPI(0xFF);
443 timeout_cntr ++;
444 if (timeout_cntr > 48000)
445 return 0;
446 }
447
448 while (count)
449 {
450 /* Wait until 0xFE is received */
451 timeout_cntr = 0;
452 while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF)
453 {
454 timeout_cntr ++;
455 if (timeout_cntr > 48000)
456 return 0;
457 }
458
459 if (card_response != 0xFE)
460 return 0;
461
462 /* Read data */
463 /*for(uint8_t i = 0; i < 512; i ++)
464 buffer[i] = SPI(0xFF); */
465 spi_read_block(buffer);
466
467 /* Receive CRC */
468 SPI(0xFF);
469 SPI(0xFF);
470
471 /* Let the card finish */
472 SPI(0xFF);
473
474 buffer += 512;
475 count --;
476 }
477
478 /* Send CMD12 */
479 result = card_command(0x4C, 0, 0, 0xFF);
480 while (result != 0)
481 {
482 result = SPI(0xFF);
483 timeout_cntr ++;
484 if (timeout_cntr > 48000)
485 return 0;
486 }
487
488 /* Wait until the MMC is no longer busy */
489 while(SPI(0xFF) != 0xFF);
490
491 return 1;
492 }
493
494 /* Writes one sector of 512 bytes to the card */
495 uint8_t card_write(uint32_t sector, uint8_t* buffer)
496 {
497 uint16_t i;
498 uint8_t result;
499 uint16_t timeout_cntr;
500 uint8_t card_response;
501
502 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
503
504 /* Send CMD24 */
505 timeout_cntr = 0;
506 result = card_command(0x58, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
507
508 while (result != 0)
509 {
510 result = SPI(0xFF);
511 timeout_cntr ++;
512 if (timeout_cntr > 48000)
513 return 0;
514 }
515
516 SPI(0xFF);
517 SPI(0xFF);
518 SPI(0xFE);
519
520 /* Send data */
521 for (i = 0; i < 512; i ++)
522 SPI(buffer[i]);
523
524 /* Send 2 dummy bytes */
525 SPI(0xFF);
526 SPI(0xFF);
527
528 card_response = SPI(0xFF);
529 card_response &= 0x1F;
530 if (card_response != 0x05)
531 {
532 /* Write error */
533 return 0;
534 }
535
536 /* Wait until the MMC is no longer busy */
537 while(SPI(0xFF) != 0xFF);
538
539 return 1;
540 }
541
542 /* Writes multiple sectors of 512 bytes to the card */
543 uint8_t card_write_multi(uint32_t sector, uint8_t* buffer, uint8_t count)
544 {
545 uint8_t result;
546 uint16_t timeout_cntr;
547 uint8_t card_response;
548
549 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
550
551 /* Send CMD25 */
552 timeout_cntr = 0;
553 result = card_command(0x59, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
554
555 while (result != 0)
556 {
557 result = SPI(0xFF);
558 timeout_cntr ++;
559 if (timeout_cntr > 48000)
560 return 0;
561 }
562
563 while (count)
564 {
565 /* Start of block */
566 SPI(0xFC);
567
568 /* Send data */
569 /*for (i = 0; i < 512; i ++)
570 SPI(buffer[i]);*/
571 spi_write_block(buffer);
572
573 /* Send 2 dummy bytes */
574 SPI(0xFF);
575 SPI(0xFF);
576
577 card_response = SPI(0xFF);
578 card_response &= 0x1F;
579 if (card_response != 0x05)
580 {
581 /* Write error */
582 return 0;
583 }
584
585 /* Wait until the MMC is no longer busy */
586 while(SPI(0xFF) != 0xFF);
587
588 /* Extra 8 bits */
589 SPI(0xFF);
590 count --;
591 buffer += 512;
592 }
593
594 /* Send CMD12 */
595 result = card_command(0x4C, 0, 0, 0xFF);
596 while (result != 0)
597 {
598 result = SPI(0xFF);
599 timeout_cntr ++;
600 if (timeout_cntr > 48000)
601 return 0;
602 }
603
604 /* Wait until the MMC is no longer busy */
605 while(SPI(0xFF) != 0xFF);
606
607 /* Send CMD13 */
608 result = card_command(0x4D, 0, 0, 0xFF);
609 while (result != 0)
610 {
611 result = SPI(0xFF);
612 timeout_cntr ++;
613 if (timeout_cntr > 48000)
614 return 0;
615 }
616 SPI(0xFF); // Second byte.
617 SPI(0xFF);
618
619 return 1;
620
621 }
622

  ViewVC Help
Powered by ViewVC 1.1.26