1 /*-----------------------------------------------------------------------*/
2 /* MMCv3/SDv1/SDv2 (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 /*-----------------------------------------------------------------------*/
9 #include "projectconfig.h"
11 #include "core/gpio/gpio.h"
12 #include "core/ssp/ssp.h"
13 #include "core/systick/systick.h"
16 /* Definitions for MMC/SDC command */
17 #define CMD0 (0x40+0) /* GO_IDLE_STATE */
18 #define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
19 #define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
20 #define CMD8 (0x40+8) /* SEND_IF_COND */
21 #define CMD9 (0x40+9) /* SEND_CSD */
22 #define CMD10 (0x40+10) /* SEND_CID */
23 #define CMD12 (0x40+12) /* STOP_TRANSMISSION */
24 #define ACMD13 (0xC0+13) /* SD_STATUS (SDC) */
25 #define CMD16 (0x40+16) /* SET_BLOCKLEN */
26 #define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
27 #define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
28 #define CMD23 (0x40+23) /* SET_BLOCK_COUNT (MMC) */
29 #define ACMD23 (0xC0+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
30 #define CMD24 (0x40+24) /* WRITE_BLOCK */
31 #define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
32 #define CMD55 (0x40+55) /* APP_CMD */
33 #define CMD58 (0x40+58) /* READ_OCR */
36 /* Port Controls (Platform dependent) */
37 #define CS_LOW() gpioSetValue(SSP0_CSPORT, SSP0_CSPIN, 0)
38 #define CS_HIGH() gpioSetValue(SSP0_CSPORT, SSP0_CSPIN, 1)
40 // #define FCLK_SLOW() /* Set slow clock (100k-400k) */
41 // #define FCLK_FAST() /* Set fast clock (depends on the CSD) */
43 #define FDELAY(ms) systickDelay(ms) // Assumes delay = 1ms, ugly
45 /*--------------------------------------------------------------------------
47 Module Private Functions
49 ---------------------------------------------------------------------------*/
52 DSTATUS Stat
= STA_NOINIT
; /* Disk status */
55 BYTE Timer1
, Timer2
; /* 100Hz decrement timer */
58 BYTE CardType
; /* Card type flags */
60 /**************************************************************************/
62 Set SSP clock to slow (400 KHz)
64 /**************************************************************************/
65 static void FCLK_SLOW()
67 /* Divide by 10 (SSPCLKDIV also enables to SSP CLK) */
68 SCB_SSP0CLKDIV
= SCB_SSP0CLKDIV_DIV10
;
70 /* (PCLK / (CPSDVSR * [SCR+1])) = (7,200,000 / (2 x [8 + 1])) = 400 KHz */
71 uint32_t configReg
= ( SSP_SSP0CR0_DSS_8BIT
// Data size = 8-bit
72 | SSP_SSP0CR0_FRF_SPI
// Frame format = SPI
73 | SSP_SSP0CR0_SCR_8
); // Serial clock rate = 8
75 // Set clock polarity (low between frames)
76 // configReg &= ~SSP_SSP0CR0_CPOL_MASK;
77 // configReg |= SSP_SSP0CR0_CPOL_LOW;
79 // Set edge transition (leading edge)
80 // configReg &= ~SSP_SSP0CR0_CPHA_MASK;
81 // configReg |= SSP_SSP0CR0_CPHA_FIRST;
83 // Assign config values to SSP0CR0
84 SSP_SSP0CR0
= configReg
;
86 /* Clock prescale register must be even and at least 2 in master mode */
87 SSP_SSP0CPSR
= SSP_SSP0CPSR_CPSDVSR_DIV2
;
90 /**************************************************************************/
92 Set SSP clock to fast (6.0 MHz)
94 /**************************************************************************/
95 static void FCLK_FAST()
97 /* Divide by 1 (SSPCLKDIV also enables to SSP CLK) */
98 SCB_SSP0CLKDIV
= SCB_SSP0CLKDIV_DIV1
;
100 /* (PCLK / (CPSDVSR * [SCR+1])) = (72,000,000 / (2 * [5 + 1])) = 6.0 MHz */
101 uint32_t configReg
= ( SSP_SSP0CR0_DSS_8BIT
// Data size = 8-bit
102 | SSP_SSP0CR0_FRF_SPI
// Frame format = SPI
103 | SSP_SSP0CR0_SCR_5
); // Serial clock rate = 5
105 // Set clock polarity (low between frames)
106 // configReg &= ~SSP_SSP0CR0_CPOL_MASK;
107 // configReg |= SSP_SSP0CR0_CPOL_LOW;
109 // Set edge transition (leading edge)
110 // configReg &= ~SSP_SSP0CR0_CPHA_MASK;
111 // configReg |= SSP_SSP0CR0_CPHA_FIRST;
113 // Assign config values to SSP0CR0
114 SSP_SSP0CR0
= configReg
;
116 /* Clock prescale register must be even and at least 2 in master mode */
117 SSP_SSP0CPSR
= SSP_SSP0CPSR_CPSDVSR_DIV2
;
120 /*-----------------------------------------------------------------------*/
121 /* Transmit a byte to MMC via SPI (Platform dependent) */
122 /*-----------------------------------------------------------------------*/
124 //#define xmit_spi(dat) (SSPSend((uint8_t*)&(dat), 1))
125 static void xmit_spi(BYTE dat
)
127 sspSend(0, (uint8_t*) &dat
, 1);
131 /*-----------------------------------------------------------------------*/
132 /* Receive a byte from MMC via SPI (Platform dependent) */
133 /*-----------------------------------------------------------------------*/
140 sspReceive(0, &data
, 1);
145 /* Alternative macro to receive data fast */
147 #define rcvr_spi_m(dst) \
149 sspReceive(0, (uint8_t*)(dst), 1); \
155 /*-----------------------------------------------------------------------*/
156 /* Wait for card ready */
157 /*-----------------------------------------------------------------------*/
160 BYTE
wait_ready (void)
165 Timer2
= 50; /* Wait for ready in timeout of 500ms */
169 while ((res
!= 0xFF) && Timer2
);
176 /*-----------------------------------------------------------------------*/
177 /* Deselect the card and release SPI bus */
178 /*-----------------------------------------------------------------------*/
189 /*-----------------------------------------------------------------------*/
190 /* Select the card and wait ready */
191 /*-----------------------------------------------------------------------*/
194 BOOL
select (void) /* TRUE:Successful, FALSE:Timeout */
197 if (wait_ready() != 0xFF) {
206 /*-----------------------------------------------------------------------*/
207 /* Power Control (Platform dependent) */
208 /*-----------------------------------------------------------------------*/
209 /* When the target system does not support socket power control, there */
210 /* is nothing to do in these functions and chk_power always returns 1. */
218 void power_off (void)
223 int chk_power(void) /* Socket power state: 0=off, 1=on */
230 /*-----------------------------------------------------------------------*/
231 /* Receive a data packet from MMC */
232 /*-----------------------------------------------------------------------*/
235 BOOL
rcvr_datablock (
236 BYTE
*buff
, /* Data buffer to store received data */
237 UINT btr
/* Byte count (must be multiple of 4) */
244 do { /* Wait for data packet in timeout of 200ms */
246 } while ((token
== 0xFF) && Timer1
);
247 if(token
!= 0xFE) return FALSE
; /* If not valid data token, retutn with error */
249 do { /* Receive the data block into buffer */
255 rcvr_spi(); /* Discard CRC */
258 return TRUE
; /* Return with success */
263 /*-----------------------------------------------------------------------*/
264 /* Send a data packet to MMC */
265 /*-----------------------------------------------------------------------*/
269 BOOL
xmit_datablock (
270 const BYTE
*buff
, /* 512 byte data block to be transmitted */
271 BYTE token
/* Data/Stop token */
277 if (wait_ready() != 0xFF) return FALSE
;
279 xmit_spi(token
); /* Xmit data token */
280 if (token
!= 0xFD) { /* Is data token */
282 do { /* Xmit the 512 byte data block to MMC */
286 xmit_spi(0xFF); /* CRC (Dummy) */
288 resp
= rcvr_spi(); /* Reveive data response */
289 if ((resp
& 0x1F) != 0x05) /* If not accepted, return with error */
295 #endif /* _READONLY */
299 /*-----------------------------------------------------------------------*/
300 /* Send a command packet to MMC */
301 /*-----------------------------------------------------------------------*/
305 BYTE cmd
, /* Command byte */
306 DWORD arg
/* Argument */
312 if (cmd
& 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
314 res
= send_cmd(CMD55
, 0);
315 if (res
> 1) return res
;
318 /* Select the card and wait for ready */
320 if (!select()) return 0xFF;
322 /* Send command packet */
323 xmit_spi(cmd
); /* Start + Command index */
324 xmit_spi((BYTE
)(arg
>> 24)); /* Argument[31..24] */
325 xmit_spi((BYTE
)(arg
>> 16)); /* Argument[23..16] */
326 xmit_spi((BYTE
)(arg
>> 8)); /* Argument[15..8] */
327 xmit_spi((BYTE
)arg
); /* Argument[7..0] */
328 n
= 0x01; /* Dummy CRC + Stop */
329 if (cmd
== CMD0
) n
= 0x95; /* Valid CRC for CMD0(0) */
330 if (cmd
== CMD8
) n
= 0x87; /* Valid CRC for CMD8(0x1AA) */
333 /* Receive command response */
334 if (cmd
== CMD12
) rcvr_spi(); /* Skip a stuff byte when stop reading */
335 n
= 10; /* Wait for a valid response in timeout of 10 attempts */
338 while ((res
& 0x80) && --n
);
340 return res
; /* Return with the response value */
345 /*--------------------------------------------------------------------------
349 ---------------------------------------------------------------------------*/
352 /*-----------------------------------------------------------------------*/
353 /* Initialize Disk Drive */
354 /*-----------------------------------------------------------------------*/
356 DSTATUS
disk_initialize (
357 BYTE drv
/* Physical drive nmuber (0) */
360 BYTE n
, cmd
, ty
, ocr
[4];
362 // Init SSP (clock low between frames, transition on leading edge)
363 sspInit(0, sspClockPolarity_Low
, sspClockPhase_RisingEdge
);
365 gpioSetDir( SSP0_CSPORT
, SSP0_CSPIN
, gpioDirection_Output
); /* CS */
366 gpioSetDir( CFG_SDCARD_CDPORT
, CFG_SDCARD_CDPIN
, gpioDirection_Input
); /* Card Detect */
367 gpioSetPullup (&IOCON_PIO3_0
, gpioPullupMode_Inactive
);
369 // Wait 20ms for card detect to stabilise
372 if (drv
) return STA_NOINIT
; /* Supports only single drive */
373 if (Stat
& STA_NODISK
) return Stat
; /* No card in the socket */
375 power_on(); /* Force socket power on */
377 for (n
= 100; n
; n
--) rcvr_spi(); /* 80 dummy clocks */
380 if (send_cmd(CMD0
, 0) == 1) { /* Enter Idle state */
381 Timer1
= 100; /* Initialization timeout of 1000 msec */
382 if (send_cmd(CMD8
, 0x1AA) == 1) { /* SDHC */
383 for (n
= 0; n
< 4; n
++) ocr
[n
] = rcvr_spi(); /* Get trailing return value of R7 resp */
384 if (ocr
[2] == 0x01 && ocr
[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
385 while (Timer1
&& send_cmd(ACMD41
, 1UL << 30)); /* Wait for leaving idle state (ACMD41 with HCS bit) */
386 if (Timer1
&& send_cmd(CMD58
, 0) == 0) { /* Check CCS bit in the OCR */
387 for (n
= 0; n
< 4; n
++) ocr
[n
] = rcvr_spi();
388 ty
= (ocr
[0] & 0x40) ? CT_SD2
| CT_BLOCK
: CT_SD2
; /* SDv2 */
391 } else { /* SDSC or MMC */
392 if (send_cmd(ACMD41
, 0) <= 1) {
393 ty
= CT_SD1
; cmd
= ACMD41
; /* SDv1 */
395 ty
= CT_MMC
; cmd
= CMD1
; /* MMCv3 */
397 while (Timer1
&& send_cmd(cmd
, 0)); /* Wait for leaving idle state */
398 if (!Timer1
|| send_cmd(CMD16
, 512) != 0) /* Set R/W block length to 512 */
405 if (ty
) { /* Initialization succeded */
406 Stat
&= ~STA_NOINIT
; /* Clear STA_NOINIT */
408 } else { /* Initialization failed */
417 /*-----------------------------------------------------------------------*/
418 /* Get Disk Status */
419 /*-----------------------------------------------------------------------*/
421 DSTATUS
disk_status (
422 BYTE drv
/* Physical drive nmuber (0) */
425 if (drv
) return STA_NOINIT
; /* Supports only single drive */
431 /*-----------------------------------------------------------------------*/
433 /*-----------------------------------------------------------------------*/
436 BYTE drv
, /* Physical drive nmuber (0) */
437 BYTE
*buff
, /* Pointer to the data buffer to store read data */
438 DWORD sector
, /* Start sector number (LBA) */
439 BYTE count
/* Sector count (1..255) */
442 if (drv
|| !count
) return RES_PARERR
;
443 if (Stat
& STA_NOINIT
) return RES_NOTRDY
;
445 if (!(CardType
& CT_BLOCK
)) sector
*= 512; /* Convert to byte address if needed */
447 if (count
== 1) { /* Single block read */
448 if ((send_cmd(CMD17
, sector
) == 0) /* READ_SINGLE_BLOCK */
449 && rcvr_datablock(buff
, 512))
452 else { /* Multiple block read */
453 if (send_cmd(CMD18
, sector
) == 0) { /* READ_MULTIPLE_BLOCK */
455 if (!rcvr_datablock(buff
, 512)) break;
458 send_cmd(CMD12
, 0); /* STOP_TRANSMISSION */
463 return count
? RES_ERROR
: RES_OK
;
468 /*-----------------------------------------------------------------------*/
469 /* Write Sector(s) */
470 /*-----------------------------------------------------------------------*/
474 BYTE drv
, /* Physical drive nmuber (0) */
475 const BYTE
*buff
, /* Pointer to the data to be written */
476 DWORD sector
, /* Start sector number (LBA) */
477 BYTE count
/* Sector count (1..255) */
480 if (drv
|| !count
) return RES_PARERR
;
481 if (Stat
& STA_NOINIT
) return RES_NOTRDY
;
482 if (Stat
& STA_PROTECT
) return RES_WRPRT
;
484 if (!(CardType
& CT_BLOCK
)) sector
*= 512; /* Convert to byte address if needed */
486 if (count
== 1) { /* Single block write */
487 if ((send_cmd(CMD24
, sector
) == 0) /* WRITE_BLOCK */
488 && xmit_datablock(buff
, 0xFE))
491 else { /* Multiple block write */
492 if (CardType
& CT_SDC
) send_cmd(ACMD23
, count
);
493 if (send_cmd(CMD25
, sector
) == 0) { /* WRITE_MULTIPLE_BLOCK */
495 if (!xmit_datablock(buff
, 0xFC)) break;
498 if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
504 return count
? RES_ERROR
: RES_OK
;
506 #endif /* _READONLY == 0 */
510 /*-----------------------------------------------------------------------*/
511 /* Miscellaneous Functions */
512 /*-----------------------------------------------------------------------*/
516 BYTE drv
, /* Physical drive nmuber (0) */
517 BYTE ctrl
, /* Control code */
518 void *buff
/* Buffer to send/receive control data */
522 BYTE n
, csd
[16], *ptr
= buff
;
526 if (drv
) return RES_PARERR
;
530 if (ctrl
== CTRL_POWER
) {
532 case 0: /* Sub control code == 0 (POWER_OFF) */
534 power_off(); /* Power off */
537 case 1: /* Sub control code == 1 (POWER_ON) */
538 power_on(); /* Power on */
541 case 2: /* Sub control code == 2 (POWER_GET) */
542 *(ptr
+1) = (BYTE
)chk_power();
550 if (Stat
& STA_NOINIT
) return RES_NOTRDY
;
553 case CTRL_SYNC
: /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */
560 case GET_SECTOR_COUNT
: /* Get number of sectors on the disk (DWORD) */
561 if ((send_cmd(CMD9
, 0) == 0) && rcvr_datablock(csd
, 16)) {
562 if ((csd
[0] >> 6) == 1) { /* SDC ver 2.00 */
563 csize
= csd
[9] + ((WORD
)csd
[8] << 8) + 1;
564 *(DWORD
*)buff
= (DWORD
)csize
<< 10;
565 } else { /* SDC ver 1.XX or MMC*/
566 n
= (csd
[5] & 15) + ((csd
[10] & 128) >> 7) + ((csd
[9] & 3) << 1) + 2;
567 csize
= (csd
[8] >> 6) + ((WORD
)csd
[7] << 2) + ((WORD
)(csd
[6] & 3) << 10) + 1;
568 *(DWORD
*)buff
= (DWORD
)csize
<< (n
- 9);
574 case GET_SECTOR_SIZE
: /* Get R/W sector size (WORD) */
579 case GET_BLOCK_SIZE
: /* Get erase block size in unit of sector (DWORD) */
580 if (CardType
& CT_SD2
) { /* SDC ver 2.00 */
581 if (send_cmd(ACMD13
, 0) == 0) { /* Read SD status */
583 if (rcvr_datablock(csd
, 16)) { /* Read partial block */
584 for (n
= 64 - 16; n
; n
--) rcvr_spi(); /* Purge trailing data */
585 *(DWORD
*)buff
= 16UL << (csd
[10] >> 4);
589 } else { /* SDC ver 1.XX or MMC */
590 if ((send_cmd(CMD9
, 0) == 0) && rcvr_datablock(csd
, 16)) { /* Read CSD */
591 if (CardType
& CT_SD1
) { /* SDC ver 1.XX */
592 *(DWORD
*)buff
= (((csd
[10] & 63) << 1) + ((WORD
)(csd
[11] & 128) >> 7) + 1) << ((csd
[13] >> 6) - 1);
594 *(DWORD
*)buff
= ((WORD
)((csd
[10] & 124) >> 2) + 1) * (((csd
[11] & 3) << 3) + ((csd
[11] & 224) >> 5) + 1);
601 case MMC_GET_TYPE
: /* Get card type flags (1 byte) */
606 case MMC_GET_CSD
: /* Receive CSD as a data block (16 bytes) */
607 if (send_cmd(CMD9
, 0) == 0 /* READ_CSD */
608 && rcvr_datablock(ptr
, 16))
612 case MMC_GET_CID
: /* Receive CID as a data block (16 bytes) */
613 if (send_cmd(CMD10
, 0) == 0 /* READ_CID */
614 && rcvr_datablock(ptr
, 16))
618 case MMC_GET_OCR
: /* Receive OCR as an R3 resp (4 bytes) */
619 if (send_cmd(CMD58
, 0) == 0) { /* READ_OCR */
620 for (n
= 4; n
; n
--) *ptr
++ = rcvr_spi();
625 case MMC_GET_SDSTAT
: /* Receive SD statsu as a data block (64 bytes) */
626 if (send_cmd(ACMD13
, 0) == 0) { /* SD_STATUS */
628 if (rcvr_datablock(ptr
, 64))
642 #endif /* _USE_IOCTL != 0 */
645 /*-----------------------------------------------------------------------*/
646 /* Device Timer Interrupt Procedure (Platform dependent) */
647 /*-----------------------------------------------------------------------*/
648 /* This function must be called in period of 10ms */
649 /* Called from SysTick_Handler in systick.c */
651 void disk_timerproc (void)
657 n
= Timer1
; /* 100Hz decrement timer */
664 /* Sample card detect pin */
665 pv
= gpioGetValue(CFG_SDCARD_CDPORT
, CFG_SDCARD_CDPIN
);
667 /* Have contacts stabled? */
672 /* write protect NOT supported */
674 /* check card detect */
675 if (!pv
) /* (Socket empty) */
676 s
|= (STA_NODISK
| STA_NOINIT
);
677 else /* (Card inserted) */