1 /*-----------------------------------------------------------------------*/
2 /* MMC/SDC (in SPI mode) control module (C)ChaN, 2007 */
3 /*-----------------------------------------------------------------------*/
4 /* Only rcvr_spi(), xmit_spi(), disk_timerproc() and some macros */
5 /* are platform dependent. */
6 /*-----------------------------------------------------------------------*/
7
8 /*
9 * This file was modified from a sample available from the FatFs
10 * web site. It was modified to work with a Luminary Micro
11 * EK-LM3S6965 evaluation board.
12 *
13 * Note that the SSI port is shared with the osram display. The code
14 * in this file does not attempt to share the SSI port with the osram,
15 * it assumes the osram is not being used.
16 */
17 #include <rtthread.h>
18
19 #include <inc/hw_types.h>
20 #include <inc/hw_memmap.h>
21 #include <driverlib/ssi.h>
22 #include <driverlib/gpio.h>
23 #include <driverlib/sysctl.h>
24
25 /* Status of Disk Functions */
26 typedef rt_uint8_t DSTATUS;
27
28 /* Results of Disk Functions */
29 typedef enum {
30 RES_OK = 0, /* 0: Successful */
31 RES_ERROR, /* 1: R/W Error */
32 RES_WRPRT, /* 2: Write Protected */
33 RES_NOTRDY, /* 3: Not Ready */
34 RES_PARERR /* 4: Invalid Parameter */
35 } DRESULT;
36
37 /* Disk Status Bits (DSTATUS) */
38
39 #define STA_NOINIT 0x01 /* Drive not initialized */
40 #define STA_NODISK 0x02 /* No medium in the drive */
41 #define STA_PROTECT 0x04 /* Write protected */
42
43 /* Definitions for MMC/SDC command */
44 #define CMD0 (0x40+0) /* GO_IDLE_STATE */
45 #define CMD1 (0x40+1) /* SEND_OP_COND */
46 #define CMD8 (0x40+8) /* SEND_IF_COND */
47 #define CMD9 (0x40+9) /* SEND_CSD */
48 #define CMD10 (0x40+10) /* SEND_CID */
49 #define CMD12 (0x40+12) /* STOP_TRANSMISSION */
50 #define CMD16 (0x40+16) /* SET_BLOCKLEN */
51 #define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
52 #define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
53 #define CMD23 (0x40+23) /* SET_BLOCK_COUNT */
54 #define CMD24 (0x40+24) /* WRITE_BLOCK */
55 #define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
56 #define CMD41 (0x40+41) /* SEND_OP_COND (ACMD) */
57 #define CMD55 (0x40+55) /* APP_CMD */
58 #define CMD58 (0x40+58) /* READ_OCR */
59
60 /* Command code for disk_ioctrl() */
61
62 /* Generic command */
63 #define CTRL_SYNC 0 /* Mandatory for write functions */
64 #define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */
65 #define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */
66 #define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */
67 #define CTRL_POWER 4
68 #define CTRL_LOCK 5
69 #define CTRL_EJECT 6
70 /* MMC/SDC command */
71 #define MMC_GET_TYPE 10
72 #define MMC_GET_CSD 11
73 #define MMC_GET_CID 12
74 #define MMC_GET_OCR 13
75 #define MMC_GET_SDSTAT 14
76 /* ATA/CF command */
77 #define ATA_GET_REV 20
78 #define ATA_GET_MODEL 21
79 #define ATA_GET_SN 22
80
81 /* Peripheral definitions for EK-LM3S6965 board */
82 // SSI port
83 #define SDC_SSI_BASE SSI0_BASE
84 #define SDC_SSI_SYSCTL_PERIPH SYSCTL_PERIPH_SSI0
85
86 // GPIO for SSI pins
87 #define SDC_GPIO_PORT_BASE GPIO_PORTA_BASE
88 #define SDC_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOA
89 #define SDC_SSI_CLK GPIO_PIN_2
90 #define SDC_SSI_TX GPIO_PIN_5
91 #define SDC_SSI_RX GPIO_PIN_4
92 #define SDC_SSI_FSS GPIO_PIN_3
93 #define SDC_SSI_PINS (SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK)
94
95 // GPIO for card chip select
96 #define SDC_CS_GPIO_PORT_BASE GPIO_PORTG_BASE
97 #define SDC_CS_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOG
98 #define SDC_CS GPIO_PIN_0
99
100 // asserts the CS pin to the card
101 static
SELECT(void)102 void SELECT (void)
103 {
104 GPIOPinWrite(SDC_CS_GPIO_PORT_BASE, SDC_CS, 0);
105 }
106
107 // de-asserts the CS pin to the card
108 static
DESELECT(void)109 void DESELECT (void)
110 {
111 GPIOPinWrite(SDC_CS_GPIO_PORT_BASE, SDC_CS, SDC_CS);
112 }
113
114
115 /*--------------------------------------------------------------------------
116
117 Module Private Functions
118
119 ---------------------------------------------------------------------------*/
120
121 static volatile
122 DSTATUS Stat = STA_NOINIT; /* Disk status */
123
124 static volatile
125 rt_uint8_t Timer1, Timer2; /* 100Hz decrement timer */
126
127 static
128 rt_uint8_t CardType; /* b0:MMC, b1:SDC, b2:Block addressing */
129
130 static
131 rt_uint8_t PowerFlag = 0; /* indicates if "power" is on */
132
133 /*-----------------------------------------------------------------------*/
134 /* Transmit a byte to MMC via SPI (Platform dependent) */
135 /*-----------------------------------------------------------------------*/
136
137 static
xmit_spi(rt_uint8_t dat)138 void xmit_spi (rt_uint8_t dat)
139 {
140 rt_uint32_t rcvdat;
141
142 SSIDataPut(SDC_SSI_BASE, dat); /* Write the data to the tx fifo */
143
144 SSIDataGet(SDC_SSI_BASE, &rcvdat); /* flush data read during the write */
145 }
146
147
148 /*-----------------------------------------------------------------------*/
149 /* Receive a byte from MMC via SPI (Platform dependent) */
150 /*-----------------------------------------------------------------------*/
151
152 static
rcvr_spi(void)153 rt_uint8_t rcvr_spi (void)
154 {
155 rt_uint32_t rcvdat;
156
157 SSIDataPut(SDC_SSI_BASE, 0xFF); /* write dummy data */
158
159 SSIDataGet(SDC_SSI_BASE, &rcvdat); /* read data frm rx fifo */
160
161 return (rt_uint8_t)rcvdat;
162 }
163
164
165 static
rcvr_spi_m(rt_uint8_t * dst)166 void rcvr_spi_m (rt_uint8_t *dst)
167 {
168 *dst = rcvr_spi();
169 }
170
171 /*-----------------------------------------------------------------------*/
172 /* Wait for card ready */
173 /*-----------------------------------------------------------------------*/
174
175 static
wait_ready(void)176 rt_uint8_t wait_ready (void)
177 {
178 rt_uint8_t res;
179
180
181 Timer2 = 50; /* Wait for ready in timeout of 500ms */
182 rcvr_spi();
183 do
184 res = rcvr_spi();
185 while ((res != 0xFF) && Timer2);
186
187 return res;
188 }
189
190 /*-----------------------------------------------------------------------*/
191 /* Send 80 or so clock transitions with CS and DI held high. This is */
192 /* required after card power up to get it into SPI mode */
193 /*-----------------------------------------------------------------------*/
194 static
send_initial_clock_train(void)195 void send_initial_clock_train(void)
196 {
197 unsigned int i;
198 rt_uint32_t dat;
199
200 /* Ensure CS is held high. */
201 DESELECT();
202
203 /* Switch the SSI TX line to a GPIO and drive it high too. */
204 GPIOPinTypeGPIOOutput(SDC_GPIO_PORT_BASE, SDC_SSI_TX);
205 GPIOPinWrite(SDC_GPIO_PORT_BASE, SDC_SSI_TX, SDC_SSI_TX);
206
207 /* Send 10 bytes over the SSI. This causes the clock to wiggle the */
208 /* required number of times. */
209 for(i = 0 ; i < 10 ; i++)
210 {
211 /* Write DUMMY data. SSIDataPut() waits until there is room in the */
212 /* FIFO. */
213 SSIDataPut(SDC_SSI_BASE, 0xFF);
214
215 /* Flush data read during data write. */
216 SSIDataGet(SDC_SSI_BASE, &dat);
217 }
218
219 /* Revert to hardware control of the SSI TX line. */
220 GPIOPinTypeSSI(SDC_GPIO_PORT_BASE, SDC_SSI_TX);
221 }
222
223 /*-----------------------------------------------------------------------*/
224 /* Power Control (Platform dependent) */
225 /*-----------------------------------------------------------------------*/
226 /* When the target system does not support socket power control, there */
227 /* is nothing to do in these functions and chk_power always returns 1. */
228
229 static
power_on(void)230 void power_on (void)
231 {
232 /*
233 * This doesn't really turn the power on, but initializes the
234 * SSI port and pins needed to talk to the card.
235 */
236
237 /* Enable the peripherals used to drive the SDC on SSI, and the CS */
238 SysCtlPeripheralEnable(SDC_SSI_SYSCTL_PERIPH);
239 SysCtlPeripheralEnable(SDC_GPIO_SYSCTL_PERIPH);
240 SysCtlPeripheralEnable(SDC_CS_GPIO_SYSCTL_PERIPH);
241
242 /* Configure the appropriate pins to be SSI instead of GPIO */
243 GPIOPinTypeSSI(SDC_GPIO_PORT_BASE, SDC_SSI_PINS);
244 GPIOPinTypeGPIOOutput(SDC_CS_GPIO_PORT_BASE, SDC_CS);
245 GPIOPadConfigSet(SDC_GPIO_PORT_BASE, SDC_SSI_PINS, GPIO_STRENGTH_4MA,
246 GPIO_PIN_TYPE_STD_WPU);
247 GPIOPadConfigSet(SDC_CS_GPIO_PORT_BASE, SDC_CS, GPIO_STRENGTH_4MA,
248 GPIO_PIN_TYPE_STD_WPU);
249
250 /* Deassert the SSI0 chip select */
251 GPIOPinWrite(SDC_CS_GPIO_PORT_BASE, SDC_CS, SDC_CS);
252
253 /* Configure the SSI0 port */
254 SSIConfigSetExpClk(SDC_SSI_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
255 SSI_MODE_MASTER, 400000, 8);
256 SSIEnable(SDC_SSI_BASE);
257
258 /* Set DI and CS high and apply more than 74 pulses to SCLK for the card */
259 /* to be able to accept a native command. */
260 send_initial_clock_train();
261
262 PowerFlag = 1;
263 }
264
265 // set the SSI speed to the max setting
266 static
set_max_speed(void)267 void set_max_speed(void)
268 {
269 unsigned long i;
270
271 /* Disable the SSI */
272 SSIDisable(SDC_SSI_BASE);
273
274 /* Set the maximum speed as half the system clock, with a max of 12.5 MHz. */
275 i = SysCtlClockGet() / 2;
276 if(i > 12500000)
277 {
278 i = 12500000;
279 }
280
281 /* Configure the SSI0 port */
282 SSIConfigSetExpClk(SDC_SSI_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
283 SSI_MODE_MASTER, i, 8);
284
285 /* Enable the SSI */
286 SSIEnable(SDC_SSI_BASE);
287 }
288
289 static
power_off(void)290 void power_off (void)
291 {
292 PowerFlag = 0;
293 }
294
295 static
chk_power(void)296 int chk_power(void) /* Socket power state: 0=off, 1=on */
297 {
298 return PowerFlag;
299 }
300
301
302
303 /*-----------------------------------------------------------------------*/
304 /* Receive a data packet from MMC */
305 /*-----------------------------------------------------------------------*/
306
307 static
rcvr_datablock(rt_uint8_t * buff,unsigned int btr)308 rt_bool_t rcvr_datablock (
309 rt_uint8_t *buff, /* Data buffer to store received data */
310 unsigned int btr /* Byte count (must be even number) */
311 )
312 {
313 rt_uint8_t token;
314
315
316 Timer1 = 10;
317 do { /* Wait for data packet in timeout of 100ms */
318 token = rcvr_spi();
319 } while ((token == 0xFF) && Timer1);
320 if(token != 0xFE) return RT_FALSE; /* If not valid data token, retutn with error */
321
322 do { /* Receive the data block into buffer */
323 rcvr_spi_m(buff++);
324 rcvr_spi_m(buff++);
325 } while (btr -= 2);
326 rcvr_spi(); /* Discard CRC */
327 rcvr_spi();
328
329 return RT_TRUE; /* Return with success */
330 }
331
332
333
334 /*-----------------------------------------------------------------------*/
335 /* Send a data packet to MMC */
336 /*-----------------------------------------------------------------------*/
337
338 #if _READONLY == 0
339 static
xmit_datablock(const rt_uint8_t * buff,rt_uint8_t token)340 rt_bool_t xmit_datablock (
341 const rt_uint8_t *buff, /* 512 byte data block to be transmitted */
342 rt_uint8_t token /* Data/Stop token */
343 )
344 {
345 rt_uint8_t resp, wc;
346
347
348 if (wait_ready() != 0xFF) return RT_FALSE;
349
350 xmit_spi(token); /* Xmit data token */
351 if (token != 0xFD) { /* Is data token */
352 wc = 0;
353 do { /* Xmit the 512 byte data block to MMC */
354 xmit_spi(*buff++);
355 xmit_spi(*buff++);
356 } while (--wc);
357 xmit_spi(0xFF); /* CRC (Dummy) */
358 xmit_spi(0xFF);
359 resp = rcvr_spi(); /* Reveive data response */
360 if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
361 return RT_FALSE;
362 }
363
364 return RT_TRUE;
365 }
366 #endif /* _READONLY */
367
368
369
370 /*-----------------------------------------------------------------------*/
371 /* Send a command packet to MMC */
372 /*-----------------------------------------------------------------------*/
373
374 static
send_cmd(rt_uint8_t cmd,rt_uint32_t arg)375 rt_uint8_t send_cmd (
376 rt_uint8_t cmd, /* Command byte */
377 rt_uint32_t arg /* Argument */
378 )
379 {
380 rt_uint8_t n, res;
381
382
383 if (wait_ready() != 0xFF) return 0xFF;
384
385 /* Send command packet */
386 xmit_spi(cmd); /* Command */
387 xmit_spi((rt_uint8_t)(arg >> 24)); /* Argument[31..24] */
388 xmit_spi((rt_uint8_t)(arg >> 16)); /* Argument[23..16] */
389 xmit_spi((rt_uint8_t)(arg >> 8)); /* Argument[15..8] */
390 xmit_spi((rt_uint8_t)arg); /* Argument[7..0] */
391 n = 0;
392 if (cmd == CMD0) n = 0x95; /* CRC for CMD0(0) */
393 if (cmd == CMD8) n = 0x87; /* CRC for CMD8(0x1AA) */
394 xmit_spi(n);
395
396 /* Receive command response */
397 if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
398 n = 10; /* Wait for a valid response in timeout of 10 attempts */
399 do
400 res = rcvr_spi();
401 while ((res & 0x80) && --n);
402
403 return res; /* Return with the response value */
404 }
405
406
407
408 /*--------------------------------------------------------------------------
409
410 Public Functions
411
412 ---------------------------------------------------------------------------*/
413
414
415 /*-----------------------------------------------------------------------*/
416 /* Initialize Disk Drive */
417 /*-----------------------------------------------------------------------*/
418 static
sdcard_initialize(rt_uint8_t drv)419 DSTATUS sdcard_initialize (
420 rt_uint8_t drv /* Physical drive nmuber (0) */
421 )
422 {
423 rt_uint8_t n, ty, ocr[4];
424
425
426 if (drv) return STA_NOINIT; /* Supports only single drive */
427 if (Stat & STA_NODISK) return Stat; /* No card in the socket */
428
429 power_on(); /* Force socket power on */
430 send_initial_clock_train();
431
432 SELECT(); /* CS = L */
433 ty = 0;
434 if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
435 Timer1 = 100; /* Initialization timeout of 1000 msec */
436 if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
437 for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
438 if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
439 do {
440 if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
441 } while (Timer1);
442 if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */
443 for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
444 ty = (ocr[0] & 0x40) ? 6 : 2;
445 }
446 }
447 } else { /* SDC Ver1 or MMC */
448 ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
449 do {
450 if (ty == 2) {
451 if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* ACMD41 */
452 } else {
453 if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */
454 }
455 } while (Timer1);
456 if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Select R/W block length */
457 ty = 0;
458 }
459 }
460 CardType = ty;
461 DESELECT(); /* CS = H */
462 rcvr_spi(); /* Idle (Release DO) */
463
464 if (ty) { /* Initialization succeded */
465 Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
466 set_max_speed();
467 } else { /* Initialization failed */
468 power_off();
469 }
470
471 return Stat;
472 }
473
474 /*-----------------------------------------------------------------------*/
475 /* Read Sector(s) */
476 /*-----------------------------------------------------------------------*/
477 static
sdcard_read(rt_uint8_t drv,rt_uint8_t * buff,rt_uint32_t sector,rt_uint8_t count)478 DRESULT sdcard_read (
479 rt_uint8_t drv, /* Physical drive nmuber (0) */
480 rt_uint8_t *buff, /* Pointer to the data buffer to store read data */
481 rt_uint32_t sector, /* Start sector number (LBA) */
482 rt_uint8_t count /* Sector count (1..255) */
483 )
484 {
485 if (drv || !count) return RES_PARERR;
486 if (Stat & STA_NOINIT) return RES_NOTRDY;
487
488 if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
489
490 SELECT(); /* CS = L */
491
492 if (count == 1) { /* Single block read */
493 if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
494 && rcvr_datablock(buff, 512))
495 count = 0;
496 }
497 else { /* Multiple block read */
498 if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
499 do {
500 if (!rcvr_datablock(buff, 512)) break;
501 buff += 512;
502 } while (--count);
503 send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
504 }
505 }
506
507 DESELECT(); /* CS = H */
508 rcvr_spi(); /* Idle (Release DO) */
509
510 return count ? RES_ERROR : RES_OK;
511 }
512
513
514
515 /*-----------------------------------------------------------------------*/
516 /* Write Sector(s) */
517 /*-----------------------------------------------------------------------*/
518
519 #if _READONLY == 0
520 static
sdcard_write(rt_uint8_t drv,const rt_uint8_t * buff,rt_uint32_t sector,rt_uint8_t count)521 DRESULT sdcard_write (
522 rt_uint8_t drv, /* Physical drive nmuber (0) */
523 const rt_uint8_t *buff, /* Pointer to the data to be written */
524 rt_uint32_t sector, /* Start sector number (LBA) */
525 rt_uint8_t count /* Sector count (1..255) */
526 )
527 {
528 if (drv || !count) return RES_PARERR;
529 if (Stat & STA_NOINIT) return RES_NOTRDY;
530 if (Stat & STA_PROTECT) return RES_WRPRT;
531
532 if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
533
534 SELECT(); /* CS = L */
535
536 if (count == 1) { /* Single block write */
537 if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
538 && xmit_datablock(buff, 0xFE))
539 count = 0;
540 }
541 else { /* Multiple block write */
542 if (CardType & 2) {
543 send_cmd(CMD55, 0); send_cmd(CMD23, count); /* ACMD23 */
544 }
545 if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
546 do {
547 if (!xmit_datablock(buff, 0xFC)) break;
548 buff += 512;
549 } while (--count);
550 if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
551 count = 1;
552 }
553 }
554
555 DESELECT(); /* CS = H */
556 rcvr_spi(); /* Idle (Release DO) */
557
558 return count ? RES_ERROR : RES_OK;
559 }
560 #endif /* _READONLY */
561
562
563
564 /*-----------------------------------------------------------------------*/
565 /* Miscellaneous Functions */
566 /*-----------------------------------------------------------------------*/
567 static
sdcard_ioctl(rt_uint8_t drv,rt_uint8_t ctrl,void * buff)568 DRESULT sdcard_ioctl (
569 rt_uint8_t drv, /* Physical drive nmuber (0) */
570 rt_uint8_t ctrl, /* Control code */
571 void *buff /* Buffer to send/receive control data */
572 )
573 {
574 DRESULT res;
575 rt_uint8_t n, csd[16], *ptr = buff;
576 rt_uint16_t csize;
577
578
579 if (drv) return RES_PARERR;
580
581 res = RES_ERROR;
582
583 if (ctrl == CTRL_POWER) {
584 switch (*ptr) {
585 case 0: /* Sub control code == 0 (POWER_OFF) */
586 if (chk_power())
587 power_off(); /* Power off */
588 res = RES_OK;
589 break;
590 case 1: /* Sub control code == 1 (POWER_ON) */
591 power_on(); /* Power on */
592 res = RES_OK;
593 break;
594 case 2: /* Sub control code == 2 (POWER_GET) */
595 *(ptr+1) = (rt_uint8_t)chk_power();
596 res = RES_OK;
597 break;
598 default :
599 res = RES_PARERR;
600 }
601 }
602 else {
603 if (Stat & STA_NOINIT) return RES_NOTRDY;
604
605 SELECT(); /* CS = L */
606
607 switch (ctrl) {
608 case GET_SECTOR_COUNT : /* Get number of sectors on the disk (rt_uint32_t) */
609 if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
610 if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
611 csize = csd[9] + ((rt_uint16_t)csd[8] << 8) + 1;
612 *(rt_uint32_t*)buff = (rt_uint32_t)csize << 10;
613 } else { /* MMC or SDC ver 1.XX */
614 n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
615 csize = (csd[8] >> 6) + ((rt_uint16_t)csd[7] << 2) + ((rt_uint16_t)(csd[6] & 3) << 10) + 1;
616 *(rt_uint32_t*)buff = (rt_uint32_t)csize << (n - 9);
617 }
618 res = RES_OK;
619 }
620 break;
621
622 case GET_SECTOR_SIZE : /* Get sectors on the disk (rt_uint16_t) */
623 *(rt_uint16_t*)buff = 512;
624 res = RES_OK;
625 break;
626
627 case CTRL_SYNC : /* Make sure that data has been written */
628 if (wait_ready() == 0xFF)
629 res = RES_OK;
630 break;
631
632 case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
633 if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
634 && rcvr_datablock(ptr, 16))
635 res = RES_OK;
636 break;
637
638 case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
639 if (send_cmd(CMD10, 0) == 0 /* READ_CID */
640 && rcvr_datablock(ptr, 16))
641 res = RES_OK;
642 break;
643
644 case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
645 if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
646 for (n = 0; n < 4; n++)
647 *ptr++ = rcvr_spi();
648 res = RES_OK;
649 }
650
651 // case MMC_GET_TYPE : /* Get card type flags (1 byte) */
652 // *ptr = CardType;
653 // res = RES_OK;
654 // break;
655
656 default:
657 res = RES_PARERR;
658 }
659
660 DESELECT(); /* CS = H */
661 rcvr_spi(); /* Idle (Release DO) */
662 }
663
664 return res;
665 }
666
667 /*
668 * RT-Thread SD Card Driver
669 * 20090705 Yi.Qiu
670 */
671 #include <rtthread.h>
672 #include <dfs_fs.h>
673
674 struct rt_device sdcard_device;
675 struct dfs_partition part;
676
677 /* RT-Thread Device Driver Interface */
rt_sdcard_init(rt_device_t dev)678 static rt_err_t rt_sdcard_init(rt_device_t dev)
679 {
680 return RT_EOK;
681 }
682
rt_sdcard_open(rt_device_t dev,rt_uint16_t oflag)683 static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
684 {
685
686 return RT_EOK;
687 }
688
rt_sdcard_close(rt_device_t dev)689 static rt_err_t rt_sdcard_close(rt_device_t dev)
690 {
691 return RT_EOK;
692 }
693
rt_sdcard_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)694 static rt_ssize_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
695 {
696 DRESULT status;
697
698 status = sdcard_read(0, buffer, part.offset + pos, size);
699 if (status != RES_OK)
700 {
701 rt_kprintf("sd card read failed\n");
702 return 0;
703 }
704
705 return size;
706 }
707
rt_sdcard_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)708 static rt_ssize_t rt_sdcard_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
709 {
710 DRESULT status;
711
712 status = sdcard_write(0, buffer, part.offset + pos, size);
713 if (status != RES_OK)
714 {
715 rt_kprintf("sd card write failed\n");
716 return 0;
717 }
718
719 return size;
720 }
721
rt_sdcard_control(rt_device_t dev,int cmd,void * args)722 static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
723 {
724 return RT_EOK;
725 }
726
rt_hw_sdcard_init(void)727 void rt_hw_sdcard_init(void)
728 {
729 if (sdcard_initialize(0) == RES_OK)
730 {
731 DRESULT status;
732 rt_uint8_t *sector;
733
734 /* get the first sector to read partition table */
735 sector = (rt_uint8_t*) rt_malloc (512);
736 if (sector == RT_NULL)
737 {
738 rt_kprintf("allocate partition sector buffer failed\n");
739 return;
740 }
741 status = sdcard_read(0, sector, 0, 1);
742 if (status == RES_OK)
743 {
744 /* get the first partition */
745 if (dfs_filesystem_get_partition(&part, sector, 0) != 0)
746 {
747 /* there is no partition */
748 part.offset = 0;
749 part.size = 0;
750 }
751 }
752 else
753 {
754 /* there is no partition table */
755 part.offset = 0;
756 part.size = 0;
757 }
758
759 /* release sector buffer */
760 rt_free(sector);
761
762 /* register sdcard device */
763 sdcard_device.type = RT_Device_Class_Block;
764 sdcard_device.init = rt_sdcard_init;
765 sdcard_device.open = rt_sdcard_open;
766 sdcard_device.close = rt_sdcard_close;
767 sdcard_device.read = rt_sdcard_read;
768 sdcard_device.write = rt_sdcard_write;
769 sdcard_device.control = rt_sdcard_control;
770
771 /* no private */
772 sdcard_device.user_data = RT_NULL;
773
774 rt_device_register(&sdcard_device, "sd0",
775 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
776
777 return;
778 }
779 rt_kprintf("sdcard init failed\n");
780 }
781
782