/*-----------------------------------------------------------------------*/
#include "common.h"
-#include <stdbool.h>
+#include <util/atomic.h>
#include "timer.h"
#include "spi.h"
#include "diskio.h"
/* Port Controls (Platform dependent) */
/* SD card socket connections */
-//#define SD_CD_0 SBIT(PORT,) /* Card detect switch */
+/* TODO: config.h cofig macros */
+
+//#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 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 SBIT(PORTB,0) /* Chip select/Card sense 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)
-//#define SD_WP_1 SBIT(PORTG,5) /* Write protect switch */
-#define SD_WP_1_IN SBIT(PING,5)
-#define SD_WP_1_DDR SBIT(DDRG,5)
+#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)
+
+//#define SD_WP_1 SBIT(PORTG,5) /* Write protect switch */
+//#define SD_WP_1_IN SBIT(PING,5)
+//#define SD_WP_1_DDR SBIT(DDRG,5)
-#define SD_CS_1 SBIT(PORTG,4) /* Chip select pin */
-#define SD_CS_1_IN SBIT(PING,4)
+#define SD_CS_1 SBIT(PORTG,4) /* Chip select/Card sense pin */
+//#define SD_CS_1_IN SBIT(PING,4)
#define SD_CS_1_DDR SBIT(DDRG,4)
#define SPI_CLK_SLOW() SPISetMMCInitClock() /* Set slow clock (100k-400k) */
-#define SPI_CLK_FAST() SPISetFastClock() /* Set fast clock (depends on the CSD) */
+#define SPI_CLK_FAST() SPISetFastClock() /* Set fast clock (depends on the CSD) */
/*--------------------------------------------------------------------------
Definitions for MMC/SDC command
static
void deselect(BYTE drv)
{
- //debug("*** enter deselect()\n");
+ //debug("*** enter deselect(%.2x)\n", drv);
if (drv == 0)
SD_CS_0 = 1;
else {
SPI_OFF();
if (drv == 0) {
-#ifndef SD_CD_0
- // SD_CS_0 = 1;
+#ifdef SD_CS_0_IN
+ SD_CS_0_DDR = 0; /* Input */
+ SD_CS_0 = 0; /* No Pullup */
#endif
} else {
-#ifndef SD_CD_1
+#ifdef SD_CS_1_IN
SD_CS_1_DDR = 0;
SD_CS_1 = 0;
#endif
}
- //debug("*** exit deselect()\n");
+ //debug("*** exit deselect(%.2x)\n", drv);
}
/*-----------------------------------------------------------------------*/
static
int select(BYTE drv) /* 1:Successful, 0:Timeout */
{
- //debug("*** enter select()\n");
- if (drv == 0)
+ //debug("*** enter select(%.2x)\n", drv);
+ if (drv == 0) {
+#ifdef SD_CS_0_IN
+ SD_CS_0 = 1;
+ SD_CS_0_DDR = 1;
+#endif
SD_CS_0 = 0;
- else {
-#ifndef SD_CD_1
+ } else {
+#ifdef SD_CS_1_IN
SD_CS_1 = 1;
SD_CS_1_DDR = 1;
#endif
static
void power_on(BYTE drv)
{
- //debug("*** enter power_on()\n");
+ //debug("*** enter power_on(%.2x)\n", drv);
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_WP_0
- SD_WP_0_DDR = 0;
- SD_WP_0 = 1;
-#endif
-#ifdef SD_CD_0
- /* Card detect, input with pullup */
- SD_CD_0_DDR = 0;
- SD_CD_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 */
-
+#endif
+ }
+#if defined SD_PWR_0 || defined SD_PWR_1
for (uint32_t to = get_timer(0); get_timer(to) < 30;)
; /* Wait for 30ms */
#endif
-
-#ifdef SD_WP_1
- SD_WP_1_DDR = 0;
- SD_WP_1 = 1;
-#endif
-#ifdef SD_CD_1
- /* Card detect, input with pullup */
- SD_CD_1_DDR = 0;
- SD_CD_1 = 1;
- SD_CS_1 = 1;
- SD_CS_1_DDR = 1;
-#else
- /* Input, no pullup */
- SD_CS_1 = 0;
- SD_CS_1_DDR = 0;
-#endif
- }
-
- //debug("*** exit power_on()\n");
+ //debug("*** exit power_on(%.2x)\n", drv);
}
static
void power_off(BYTE drv)
{
- //debug("*** enter power_off()\n");
+ //debug("*** enter power_off(%.2x)\n", drv);
select(drv); /* Wait for card ready */
deselect(drv);
SD_PWR_1 = 1; /* Socket power OFF */
#endif
}
- socket[drv].stat |= STA_NOINIT;
- //debug("*** exit power_off()\n");
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ socket[drv].stat |= STA_NOINIT;
+ }
+ //debug("*** exit power_off(%.2x)\n", drv);
}
#if 0
/* Send a data packet to MMC */
/*-----------------------------------------------------------------------*/
-#if _USE_WRITE
static
int xmit_datablock (
const BYTE *buff, /* 512 byte data block to be transmitted */
spi_wait();
return 1;
}
-#endif /* _USE_WRITE */
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
} argtmp;
BYTE n, res;
- //debug("*** send_cmd( %.2x )\n", cmd);
-
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
cmd &= 0x7F;
res = send_cmd(drv, CMD55, 0);
return res;
}
+ //debug("*** send_cmd( %.2x )", cmd);
+
/* Select the card and wait for ready except to stop multiple block read */
if (cmd != CMD12) {
deselect(drv);
- if (!select(drv))
+ if (!select(drv)) {
+ //debug(" == %.2x\n", 0xff);
return 0xFF;
+ }
}
/* Send command packet */
res = spi_rcvr();
while ((res & 0x80) && --n);
+ //debug(" == %.2x\n", res);
return res; /* Return with the response value */
}
---------------------------------------------------------------------------*/
+void setup_mmc(void)
+{
+#ifdef SD_PWR_0
+ SD_PWR_1 = 1; /* Drives PWR pin low */
+ SD_PWR_0_DDR = 1; /* Turns on PWR pin as output */
+#endif
+#ifdef SD_WP_0
+ SD_WP_0_DDR = 0;
+ SD_WP_0 = 1; /* Pullup */
+#endif
+
+#ifdef SD_PWR_1
+ SD_PWR_1 = 1; /* Drives PWR pin low */
+ SD_PWR_1_DDR = 1; /* Turns on PWR pin as output */
+#endif
+#ifdef SD_WP_1
+ SD_WP_1_DDR = 0;
+ SD_WP_1 = 1; /* Pullup */
+#endif
+
+ /* SPI as master */
+ PRR0 &= ~_BV(PRSPI);
+ SPI_DDR = (SPI_DDR & ~(_BV(SPI_MISO) | _BV(SPI_SS)))
+ | _BV(SPI_MOSI) | _BV(SPI_SCK);
+ SPI_PORT = SPI_PORT & ~(_BV(SPI_MOSI) | _BV(SPI_SCK));
+
+#if defined SD_CD_0
+ SD_CD_0_DDR = 0;
+ SD_CD_0 = 1; /* Pullup */
+#elif defined SD_CS_0_IN
+ SD_CS_0_DDR = 0;
+ SD_CS_0 = 0;
+#endif
+#if defined SD_CD_0 || !defined SD_CS_0_IN
+ SD_CS_0 = 1;
+ SD_CS_0_DDR = 1;
+#endif
+
+#if defined SD_CD_1
+ SD_CD_1_DDR = 0;
+ SD_CD_1 = 1; /* Pullup */
+#elif defined SD_CS_1_IN
+ SD_CS_1_DDR = 0;
+ SD_CS_1 = 0; /* No Pullup */
+#endif
+#if defined SD_CD_1 || !defined SD_CS_1_IN
+ SD_CS_1 = 1; /* Set High */
+ SD_CS_1_DDR = 1;
+#endif
+}
+
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
)
{
BYTE n, cmd, ty, ocr[4];
+ DSTATUS res;
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 */
-
+ return STA_NOINIT;
+ res = socket[drv].stat;
+ if (res & STA_NODISK) {
+ return res & STAT_MASK; /* No card in the socket */
+ }
power_on(drv); /* Force socket power on */
- socket[drv].stat &= ~STA_FAST;
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ socket[drv].stat &= ~STA_FAST;
+ }
SPI_CLK_SLOW();
for (n = 10; n; n--)
spi_rcvr(); /* 80 dummy clocks */
if (ty) { /* Initialization succeded */
/* Clear STA_NOINIT */
- socket[drv].stat = (socket[drv].stat & ~STA_NOINIT) | STA_FAST;
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ res = (socket[drv].stat & ~STA_NOINIT) | STA_FAST;
+ socket[drv].stat = res;
+ }
} else { /* Initialization failed */
power_off(drv);
}
- return socket[drv].stat;
+ return socket[drv].stat & STAT_MASK;
}
/*-----------------------------------------------------------------------*/
BYTE drv /* Physical drive nmuber (0) */
)
{
+ DSTATUS res;
+
+ //debug("***** disk_status(%.2x)", drv);
if (drv >= MAX_DRV)
- return STA_NOINIT;
- return socket[drv].stat;
+ res = STA_NOINIT;
+ else
+ res = socket[drv].stat & STAT_MASK;
+
+ //debug(" == %.2x\n", res);
+ return res;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
-#if _USE_WRITE
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0) */
const BYTE *buff, /* Pointer to the data to be written */
UINT count /* Sector count (1..255) */
)
{
+ DSTATUS res;
+
if (drv >= MAX_DRV || !count)
return RES_PARERR;
- if (socket[drv].stat & STA_NOINIT)
+ res = socket[drv].stat;
+ if ( res & STA_NOINIT)
return RES_NOTRDY;
- if (socket[drv].stat & STA_PROTECT)
+ if (res & STA_PROTECT)
return RES_WRPRT;
/* Convert to byte address if needed */
return count ? RES_ERROR : RES_OK;
}
-#endif /* _USE_WRITE */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
-#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0) */
BYTE cmd, /* Control code */
case CTRL_POWER_OFF : /* Power off */
power_off(drv);
- socket[drv].stat |= STA_NOINIT;
res = RES_OK;
break;
return res;
}
-#endif /* _USE_IOCTL */
/*-----------------------------------------------------------------------*/
/* Device Timer Interrupt Procedure (Platform dependent) */
#ifdef SD_WP_0
if (SD_WP_0_IN == 0) /* Write protected */
s |= STA_PROTECT;
- else /* Write enabled */
+ else /* Write enabled */
s &= ~STA_PROTECT;
#endif
-#ifdef SD_CD_0
+
+#if defined SD_CD_0
if (SD_CD_0_IN == 0) /* Card inserted */
s &= ~STA_NODISK;
- else /* Socket empty */
+ else /* Socket empty */
s |= (STA_NODISK | STA_NOINIT);
+#elif defined SD_CS_0_IN
+ if (SD_CS_0_DDR == 0) {
+ if (SD_CS_0_IN == 1) /* Card inserted */
+ s &= ~STA_NODISK;
+ else /* Socket empty */
+ s |= (STA_NODISK | STA_NOINIT);
+ }
#endif
- socket[0].stat = s; /* Update MMC status */
+ 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 */
+ else /* Write enabled */
s &= ~STA_PROTECT;
#endif
-#ifdef SD_CD_1
+
+#if defined SD_CD_1
if (SD_CD_1_IN == 0) /* Card inserted */
s &= ~STA_NODISK;
- else /* Socket empty */
+ else /* Socket empty */
s |= (STA_NODISK | STA_NOINIT);
-#else
+#elif defined SD_CS_1_IN
if (SD_CS_1_DDR == 0) {
- if (SD_CS_1_IN == 1) /* Card inserted */
+ if (SD_CS_1_IN == 1) /* Card inserted */
s &= ~STA_NODISK;
- else /* Socket empty */
+ else /* Socket empty */
s |= (STA_NODISK | STA_NOINIT);
}
#endif