summaryrefslogtreecommitdiff
path: root/avr/mmc.c
diff options
context:
space:
mode:
authorLeo C2014-11-23 00:39:03 +0100
committerLeo C2014-11-23 00:39:03 +0100
commit1222f338a23212010c7e2d0d7c3a2861e42fa8df (patch)
tree63053f327bd7630c679d910211c6a8df2f280473 /avr/mmc.c
parentf82d019db73133acc10754dae8afb44225f9d673 (diff)
downloadz180-stamp-1222f338a23212010c7e2d0d7c3a2861e42fa8df.zip
Multidrive support for mmc.c (working)
Diffstat (limited to 'avr/mmc.c')
-rw-r--r--avr/mmc.c284
1 files changed, 188 insertions, 96 deletions
diff --git a/avr/mmc.c b/avr/mmc.c
index 2592c45..d780fef 100644
--- a/avr/mmc.c
+++ b/avr/mmc.c
@@ -12,10 +12,23 @@
#include "diskio.h"
//#include "debug.h"
+#define MAX_DRV 2
/* Port Controls (Platform dependent) */
/* SD card socket connections */
+//#define SD_CD_0 SBIT(PORT,) /* Card detect switch */
+//#define SD_CD_0_IN SBIT(PIN,)
+//#define SD_CD_0_DDR SBIT(DDR,)
+
+//#define SD_WP_0 SBIT(PORT,) /* Write protect switch */
+//#define SD_WP_0_IN SBIT(PIN,)
+//#define SD_WP_0_DDR SBIT(DDR,)
+
+#define SD_CS_0 SBIT(PORTB,0) /* Chip select pin */
+#define SD_CS_0_IN SBIT(PINB,0)
+#define SD_CS_0_DDR SBIT(DDRB,0)
+
#define SD_CD_1 SBIT(PORTG,3) /* Card detect switch */
#define SD_CD_1_IN SBIT(PING,3)
#define SD_CD_1_DDR SBIT(DDRG,3)
@@ -69,7 +82,7 @@ struct sdsock_stat_s {
static
struct sdsock_stat_s
- socket[2] = {
+ socket[MAX_DRV] = {
{.stat=STA_NOINIT},
{.stat=STA_NOINIT}
};
@@ -98,26 +111,30 @@ int wait_ready (void) /* 1:OK, 0:Timeout */
/*-----------------------------------------------------------------------*/
static
-void deselect (void)
+void deselect(BYTE drv)
{
// debug("*** enter deselect()\n");
- SD_CS_1 = 1;
+ if (drv == 0)
+ SD_CS_0 = 1;
+ else
+ SD_CS_1 = 1;
/* Dummy clock (TODO: force DO hi-z for multiple slave SPI) */
spi_rcvr();
// debug("*** exit deselect()\n");
}
-
-
/*-----------------------------------------------------------------------*/
/* Select the card and wait for ready */
/*-----------------------------------------------------------------------*/
static
-int select (void) /* 1:Successful, 0:Timeout */
+int select(BYTE drv) /* 1:Successful, 0:Timeout */
{
// debug("*** enter select()\n");
- SD_CS_1 = 0;
+ if (drv == 0)
+ SD_CS_0 = 0;
+ else
+ SD_CS_1 = 0;
/* Dummy clock (force DO enabled) */
spi_rcvr();
@@ -125,7 +142,7 @@ int select (void) /* 1:Successful, 0:Timeout */
// debug("*** exit select() == 1\n");
return 1; /* OK */
}
- deselect();
+ deselect(drv);
// debug("*** exit select() == 0\n");
return 0; /* Timeout */
@@ -138,56 +155,92 @@ int select (void) /* 1:Successful, 0:Timeout */
/* is nothing to do in these functions and chk_power always returns 1. */
static
-void power_on(void)
+void power_on(BYTE drv)
{
// debug("*** enter power_on()\n");
+ if (drv == 0) {
+#ifdef SD_PWR_0
+ SD_PWR_0_DDR = 1; /* Turns on PWR pin as output */
+ SD_PWR_0 = 0; /* Drives PWR pin high */
+
+ for (uint32_t to = get_timer(0); get_timer(to) < 30;)
+ ; /* Wait for 30ms */
+#endif
+
+#ifdef SD_CD_0
+ /* Card detect, input with pullup */
+ SD_CD_0_DDR = 0;
+ SD_CD_0 = 1;
+#endif
+#ifdef SD_WP_0
+ SD_WP_0_DDR = 0;
+ SD_WP_0 = 1;
+#endif
+ SD_CS_0 = 1;
+ SD_CS_0_DDR = 1;
+ } else {
#ifdef SD_PWR_1
- SD_PWR_1_DDR = 1; /* Turns on PWR pin as output */
- SD_PWR_1 = 0; /* Drives PWR pin high */
+ SD_PWR_1_DDR = 1; /* Turns on PWR pin as output */
+ SD_PWR_1 = 0; /* Drives PWR pin high */
- for (uint32_t to = get_timer(0); get_timer(to) < 30;)
- ; /* Wait for 30ms */
+ for (uint32_t to = get_timer(0); get_timer(to) < 30;)
+ ; /* Wait for 30ms */
#endif
#ifdef SD_CD_1
- /* Card detect, input with pullup */
- SD_CD_1_DDR = 0;
- SD_CD_1 = 1;
+ /* Card detect, input with pullup */
+ SD_CD_1_DDR = 0;
+ SD_CD_1 = 1;
#endif
#ifdef SD_WP_1
- SD_WP_1_DDR = 0;
- SD_WP_1 = 1;
+ SD_WP_1_DDR = 0;
+ SD_WP_1 = 1;
#endif
- SD_CS_1 = 1;
- SD_CS_1_DDR = 1;
+ SD_CS_1 = 1;
+ SD_CS_1_DDR = 1;
+ }
// debug("*** exit power_on()\n");
}
static
-void power_off (void)
+void power_off(BYTE drv)
{
// debug("*** enter power_off()\n");
- select(); /* Wait for card ready */
- deselect();
+ select(drv); /* Wait for card ready */
+ deselect(drv);
+ if (drv == 0) {
+#ifdef SD_PWR_0
+ SD_PWR_0 = 1; /* Socket power OFF */
+#endif
+ } else {
#ifdef SD_PWR_1
- SD_PWR_1 = 1; /* Socket power OFF */
+ SD_PWR_1 = 1; /* Socket power OFF */
#endif
- socket[0].stat |= STA_NOINIT;
+ }
+ socket[drv].stat |= STA_NOINIT;
// debug("*** exit power_off()\n");
}
#if 0
static
-int chk_power(void) /* Socket power state: 0=off, 1=on */
+int chk_power(BYTE drv) /* Socket power state: 0=off, 1=on */
{
+ if (drv == 0) {
+#ifdef SD_PWR_0
+ return SD_PWR_0 == 0;
+#else
+ return 1;
+#endif /* SD_PWR_PIN */
+ } else {
#ifdef SD_PWR_1
- return SD_PWR_1 == 0;
+ return SD_PWR_1 == 0;
#else
- return 1;
+ return 1;
#endif /* SD_PWR_PIN */
+ }
}
#endif
@@ -267,8 +320,9 @@ int xmit_datablock (
static
BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */
- BYTE cmd, /* Command index */
- DWORD arg /* Argument */
+ BYTE drv, /* Physical drive nmuber (0) */
+ BYTE cmd, /* Command index */
+ DWORD arg /* Argument */
) {
union {
DWORD as32;
@@ -280,15 +334,15 @@ BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
cmd &= 0x7F;
- res = send_cmd(CMD55, 0);
+ res = send_cmd(drv, CMD55, 0);
if (res > 1)
return res;
}
/* Select the card and wait for ready except to stop multiple block read */
if (cmd != CMD12) {
- deselect();
- if (!select())
+ deselect(drv);
+ if (!select(drv))
return 0xFF;
}
@@ -336,53 +390,60 @@ DSTATUS disk_initialize (
{
BYTE n, cmd, ty, ocr[4];
- if (drv)
+ if (drv >= MAX_DRV)
return STA_NOINIT; /* Supports only single drive */
if (socket[drv].stat & STA_NODISK)
return socket[drv].stat; /* No card in the socket */
- power_on(); /* Force socket power on */
+ power_on(drv); /* Force socket power on */
FCLK_SLOW();
for (n = 10; n; n--)
spi_rcvr(); /* 80 dummy clocks */
ty = 0;
- if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
+ if (send_cmd(drv, CMD0, 0) == 1) { /* Enter Idle state */
/* Init timeout timer */
uint32_t timer = get_timer(0);
- if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
- for (n = 0; n < 4; n++) ocr[n] = spi_rcvr(); /* Get trailing return value of R7 resp */
- if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
- while (get_timer(timer) < MMC_INIT_TO && send_cmd(ACMD41, 1UL << 30)); /* Wait for leaving idle state (ACMD41 with HCS bit) */
- if (get_timer(timer) < MMC_INIT_TO && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
- for (n = 0; n < 4; n++) ocr[n] = spi_rcvr();
+ if (send_cmd(drv, CMD8, 0x1AA) == 1) { /* SDv2? */
+ /* Get trailing return value of R7 resp */
+ for (n = 0; n < 4; n++)
+ ocr[n] = spi_rcvr();
+ if (ocr[2] == 0x01 && ocr[3] == 0xAA) {
+ /* The card can work at vdd range of 2.7-3.6V */
+ while (get_timer(timer) < MMC_INIT_TO
+ && send_cmd(drv, ACMD41, 1UL << 30))
+ ; /* Wait for leaving idle state (ACMD41 with HCS bit) */
+ if (get_timer(timer) < MMC_INIT_TO && send_cmd(drv, CMD58, 0) == 0) {
+ /* Check CCS bit in the OCR */
+ for (n = 0; n < 4; n++)
+ ocr[n] = spi_rcvr();
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */
}
}
} else { /* SDv1 or MMCv3 */
- if (send_cmd(ACMD41, 0) <= 1) {
+ if (send_cmd(drv, ACMD41, 0) <= 1) {
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
} else {
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
}
/* Wait for leaving idle state */
- while (get_timer(timer) < MMC_INIT_TO && send_cmd(cmd, 0));
+ while (get_timer(timer) < MMC_INIT_TO && send_cmd(drv, cmd, 0))
+ ;
/* Set R/W block length to 512 */
- if (!(get_timer(timer) < MMC_INIT_TO) || send_cmd(CMD16, 512) != 0)
+ if (!(get_timer(timer) < MMC_INIT_TO) || send_cmd(drv, CMD16, 512) != 0)
ty = 0;
}
}
socket[drv].CardType = ty;
- deselect();
+ deselect(drv);
if (ty) { /* Initialization succeded */
socket[drv].stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
- FCLK_FAST();
} else { /* Initialization failed */
- power_off();
+ power_off(drv);
}
return socket[drv].stat;
@@ -393,10 +454,11 @@ DSTATUS disk_initialize (
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
- BYTE drv /* Physical drive nmuber (0) */
+ BYTE drv /* Physical drive nmuber (0) */
)
{
- if (drv) return STA_NOINIT; /* Supports only single drive */
+ if (drv >= MAX_DRV)
+ return STA_NOINIT;
return socket[drv].stat;
}
@@ -405,30 +467,36 @@ DSTATUS disk_status (
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
- BYTE drv, /* Physical drive nmuber (0) */
- BYTE *buff, /* Pointer to the data buffer to store read data */
- DWORD sector, /* Start sector number (LBA) */
- UINT count /* Sector count (1..255) */
+ BYTE drv, /* Physical drive nmuber (0) */
+ BYTE *buff, /* Pointer to the data buffer to store read data */
+ DWORD sector, /* Start sector number (LBA) */
+ UINT count /* Sector count (1..255) */
)
{
BYTE cmd;
- if (drv || !count) return RES_PARERR;
- if (socket[drv].stat & STA_NOINIT) return RES_NOTRDY;
+ if (drv >= MAX_DRV || !count)
+ return RES_PARERR;
+ if (socket[drv].stat & STA_NOINIT)
+ return RES_NOTRDY;
- if (!(socket[drv].CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
+ /* Convert to byte address if needed */
+ if (!(socket[drv].CardType & CT_BLOCK))
+ sector *= 512;
+ FCLK_FAST();
- cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
- if (send_cmd(cmd, sector) == 0) {
+ /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
+ cmd = count > 1 ? CMD18 : CMD17;
+ if (send_cmd(drv, cmd, sector) == 0) {
do {
if (!rcvr_datablock(buff, 512))
break;
buff += 512;
} while (--count);
if (cmd == CMD18)
- send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
+ send_cmd(drv, CMD12, 0); /* STOP_TRANSMISSION */
}
- deselect();
+ deselect(drv);
return count ? RES_ERROR : RES_OK;
}
@@ -439,35 +507,45 @@ DRESULT disk_read (
#if _USE_WRITE
DRESULT disk_write (
- BYTE drv, /* Physical drive nmuber (0) */
- const BYTE *buff, /* Pointer to the data to be written */
- DWORD sector, /* Start sector number (LBA) */
- UINT count /* Sector count (1..255) */
+ BYTE drv, /* Physical drive nmuber (0) */
+ const BYTE *buff, /* Pointer to the data to be written */
+ DWORD sector, /* Start sector number (LBA) */
+ UINT count /* Sector count (1..255) */
)
{
- if (drv || !count) return RES_PARERR;
- if (socket[drv].stat & STA_NOINIT) return RES_NOTRDY;
- if (socket[drv].stat & STA_PROTECT) return RES_WRPRT;
-
- if (!(socket[drv].CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
-
- if (count == 1) { /* Single block write */
- if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
+ if (drv >= MAX_DRV || !count)
+ return RES_PARERR;
+ if (socket[drv].stat & STA_NOINIT)
+ return RES_NOTRDY;
+ if (socket[drv].stat & STA_PROTECT)
+ return RES_WRPRT;
+
+ /* Convert to byte address if needed */
+ if (!(socket[drv].CardType & CT_BLOCK))
+ sector *= 512;
+ FCLK_FAST();
+
+ if (count == 1) {
+ /* Single block write */
+ if ((send_cmd(drv, CMD24, sector) == 0) /* WRITE_BLOCK */
&& xmit_datablock(buff, 0xFE))
count = 0;
- }
- else { /* Multiple block write */
- if (socket[drv].CardType & CT_SDC) send_cmd(ACMD23, count);
- if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
+ } else {
+ /* Multiple block write */
+ if (socket[drv].CardType & CT_SDC)
+ send_cmd(drv, ACMD23, count);
+ if (send_cmd(drv, CMD25, sector) == 0) {
+ /* WRITE_MULTIPLE_BLOCK */
do {
- if (!xmit_datablock(buff, 0xFC)) break;
+ if (!xmit_datablock(buff, 0xFC))
+ break;
buff += 512;
- }while (--count);
+ } while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
- count = 1;
+ count = 1;
}
}
- deselect();
+ deselect(drv);
return count ? RES_ERROR : RES_OK;
}
@@ -488,21 +566,23 @@ DRESULT disk_ioctl (
BYTE n, csd[16], *ptr = buff;
DWORD csize;
- if (drv)
+ if (drv >= MAX_DRV)
return RES_PARERR;
res = RES_ERROR;
- if (socket[drv].stat & STA_NOINIT) return RES_NOTRDY;
+ if (socket[drv].stat & STA_NOINIT)
+ return RES_NOTRDY;
+ FCLK_FAST();
switch (cmd) {
case CTRL_SYNC : /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */
- if (select())
+ if (select(drv))
res = RES_OK;
break;
case GET_SECTOR_COUNT: /* Get number of sectors on the disk (DWORD) */
- if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
+ if ((send_cmd(drv, CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
*(DWORD*)buff = csize << 10;
@@ -517,7 +597,7 @@ DRESULT disk_ioctl (
case GET_BLOCK_SIZE: /* Get erase block size in unit of sector (DWORD) */
if (socket[drv].CardType & CT_SD2) { /* SDv2? */
- if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
+ if (send_cmd(drv, ACMD13, 0) == 0) { /* Read SD status */
spi_rcvr();
if (rcvr_datablock(csd, 16)) { /* Read partial block */
for (n = 64 - 16; n; n--)
@@ -527,7 +607,7 @@ DRESULT disk_ioctl (
}
}
} else { /* SDv1 or MMCv3 */
- if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
+ if ((send_cmd(drv, CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
if (socket[drv].CardType & CT_SD1) { /* SDv1 */
*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
} else { /* MMCv3 */
@@ -546,19 +626,19 @@ DRESULT disk_ioctl (
break;
case MMC_GET_CSD: /* Receive CSD as a data block (16 bytes) */
- if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
+ if (send_cmd(drv, CMD9, 0) == 0 /* READ_CSD */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_CID: /* Receive CID as a data block (16 bytes) */
- if (send_cmd(CMD10, 0) == 0 /* READ_CID */
+ if (send_cmd(drv, CMD10, 0) == 0 /* READ_CID */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_OCR: /* Receive OCR as an R3 resp (4 bytes) */
- if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
+ if (send_cmd(drv, CMD58, 0) == 0) { /* READ_OCR */
for (n = 4; n; n--)
*ptr++ = spi_rcvr();
res = RES_OK;
@@ -566,7 +646,7 @@ DRESULT disk_ioctl (
break;
case MMC_GET_SDSTAT: /* Receive SD status as a data block (64 bytes) */
- if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
+ if (send_cmd(drv, ACMD13, 0) == 0) { /* SD_STATUS */
spi_rcvr();
if (rcvr_datablock(ptr, 64))
res = RES_OK;
@@ -574,7 +654,7 @@ DRESULT disk_ioctl (
break;
case CTRL_POWER_OFF : /* Power off */
- power_off();
+ power_off(drv);
socket[drv].stat |= STA_NOINIT;
res = RES_OK;
break;
@@ -583,7 +663,7 @@ DRESULT disk_ioctl (
res = RES_PARERR;
}
- deselect();
+ deselect(drv);
return res;
}
@@ -599,20 +679,32 @@ void disk_timerproc (void)
BYTE s;
s = socket[0].stat;
+#ifdef SD_WP_0
+ if (SD_WP_0_IN == 0) /* Write protected */
+ s |= STA_PROTECT;
+ else /* Write enabled */
+ s &= ~STA_PROTECT;
+#endif
+#ifdef SD_CD_0
+ if (SD_CD_0_IN == 0) /* Card inserted */
+ s &= ~STA_NODISK;
+ else /* Socket empty */
+ s |= (STA_NODISK | STA_NOINIT);
+#endif
+ socket[0].stat = s; /* Update MMC status */
+ s = socket[1].stat;
#ifdef SD_WP_1
if (SD_WP_1_IN == 0) /* Write protected */
s |= STA_PROTECT;
else /* Write enabled */
s &= ~STA_PROTECT;
#endif
-
#ifdef SD_CD_1
if (SD_CD_1_IN == 0) /* Card inserted */
s &= ~STA_NODISK;
else /* Socket empty */
s |= (STA_NODISK | STA_NOINIT);
#endif
-
- socket[0].stat = s; /* Update MMC status */
+ socket[1].stat = s; /* Update MMC status */
}