From c6a480f8ff542312fdd4dd3ca2d29f1b35417ecb Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 24 Oct 2018 18:15:17 -0600 Subject: [PATCH] arch/arm/src/lpc54xx/lpc54_sdmmc.c: Ported the last of Dave Marples fixes to the LPC54. Not yet verified. --- arch/arm/src/lpc43xx/Kconfig | 1 - arch/arm/src/lpc54xx/lpc54_sdmmc.c | 80 +++++++++++++------------- configs/lpcxpresso-lpc54628/README.txt | 3 + 3 files changed, 43 insertions(+), 41 deletions(-) diff --git a/arch/arm/src/lpc43xx/Kconfig b/arch/arm/src/lpc43xx/Kconfig index a33e4154be..71d2e13743 100644 --- a/arch/arm/src/lpc43xx/Kconfig +++ b/arch/arm/src/lpc43xx/Kconfig @@ -256,7 +256,6 @@ config LPC43_SDMMC default n select ARCH_HAVE_SDIO select SDIO_BLOCKSETUP - depends on EXPERIMENTAL config LPC43_SPI bool "SPI" diff --git a/arch/arm/src/lpc54xx/lpc54_sdmmc.c b/arch/arm/src/lpc54xx/lpc54_sdmmc.c index 0d0e760f45..3b51f6a0e4 100644 --- a/arch/arm/src/lpc54xx/lpc54_sdmmc.c +++ b/arch/arm/src/lpc54xx/lpc54_sdmmc.c @@ -128,10 +128,10 @@ # error "Driver requires CONFIG_SDIO_BLOCKSETUP to be set" #endif -/* Timing */ +/* Timing : 100mS short timeout, 2 seconds for long one */ -#define SDCARD_CMDTIMEOUT (10000) -#define SDCARD_LONGTIMEOUT (0x7fffffff) +#define SDCARD_CMDTIMEOUT MSEC2TICK(100) +#define SDCARD_LONGTIMEOUT MSEC2TICK(2000) /* Type of Card Bus Size */ @@ -621,28 +621,36 @@ static inline void lpc54_sdcard_clock(bool enable) * arg - The argument to use with the command. * * Returned Value: - * None + * Returns zero on success. One will be returned on a timeout. * ****************************************************************************/ static int lpc54_ciu_sendcmd(uint32_t cmd, uint32_t arg) { - volatile int32_t tmo = SDCARD_CMDTIMEOUT; + clock_t watchtime; mcinfo("cmd=%04lx arg=%04lx\n", (unsigned long)cmd, (unsigned long)arg); + DEBUGASSERT((lpc54_getreg(LPC54_SDMMC_CMD) & SDMMC_CMD_STARTCMD) == 0); /* Set command arg reg */ lpc54_putreg(arg, LPC54_SDMMC_CMDARG); lpc54_putreg(SDMMC_CMD_STARTCMD | cmd, LPC54_SDMMC_CMD); - /* Poll until command is accepted by the CIU */ + /* Poll until command is accepted by the CIU, or we timeout */ - while (--tmo > 0 && (lpc54_getreg(LPC54_SDMMC_CMD) & SDMMC_CMD_STARTCMD) != 0) + watchtime = clock_systimer(); + + while ((lpc54_getreg(LPC54_SDMMC_CMD) & SDMMC_CMD_STARTCMD) != 0) { + if (watchtime - clock_systimer() > SDCARD_CMDTIMEOUT) + { + mcerr("TMO Timed out (%08X)\n",lpc54_getreg(LPC54_SDMMC_CMD)); + return 1; + } } - return (tmo < 1) ? 1 : 0; + return 0; } /**************************************************************************** @@ -1031,7 +1039,6 @@ static int lpc54_sdmmc_interrupt(int irq, void *context, FAR void *arg) /* Transfer data to the TX FIFO */ - mcinfo("Write FIFO\n"); DEBUGASSERT(priv->wrdir); for (status = lpc54_getreg(LPC54_SDMMC_STATUS); @@ -1043,20 +1050,6 @@ static int lpc54_sdmmc_interrupt(int irq, void *context, FAR void *arg) priv->buffer++; priv->remaining -= 4; } - - /* If all of the data has been transferred to the FIFO, then - * disable further TX data requests and wait for the data end - * event. - */ - - if (priv->remaining <= 0) - { - uint32_t intmask = lpc54_getreg(LPC54_SDMMC_INTMASK); - intmask &= ~SDMMC_INT_TXDR; - lpc54_putreg(intmask, LPC54_SDMMC_INTMASK); - - priv->xfrmask &= ~SDMMC_INT_TXDR; - } } else if ((pending & SDMMC_INT_RXDR) != 0) { @@ -1064,7 +1057,6 @@ static int lpc54_sdmmc_interrupt(int irq, void *context, FAR void *arg) /* Transfer data from the RX FIFO */ - mcinfo("Read from FIFO\n"); DEBUGASSERT(!priv->wrdir); for (status = lpc54_getreg(LPC54_SDMMC_STATUS); @@ -1076,18 +1068,6 @@ static int lpc54_sdmmc_interrupt(int irq, void *context, FAR void *arg) priv->buffer++; priv->remaining -= 4; } - - /* If all of the data has been transferred to the FIFO, then - * just force DTO event processing (the DTO interrupt is not - * actually even enabled in this use case). - */ - - if (priv->remaining <= 0) - { - /* Force the DTO event */ - - pending |= SDMMC_INT_DTO; - } } /* Check for transfer errors */ @@ -1348,7 +1328,7 @@ static void lpc54_reset(FAR struct sdio_dev_s *dev) /* Define MAX Timeout */ - lpc54_putreg(SDCARD_LONGTIMEOUT, LPC54_SDMMC_TMOUT); + lpc54_putreg(0x7fffffff, LPC54_SDMMC_TMOUT); /* Disable clock to CIU (needs latch) */ @@ -1763,6 +1743,10 @@ static int lpc54_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, lpc54_putreg(regval, LPC54_SDMMC_CTRL); #endif + /* Flush ints before we start */ + + lpc54_putreg(SDCARD_TRANSFER_ALL, LPC54_SDMMC_RINTSTS); + /* Configure the transfer interrupts */ lpc54_config_xfrints(priv, SDCARD_RECV_MASK); @@ -1827,6 +1811,10 @@ static int lpc54_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer lpc54_putreg(regval, LPC54_SDMMC_CTRL); #endif + /* Flush ints before we start */ + + lpc54_putreg(SDCARD_TRANSFER_ALL, LPC54_SDMMC_RINTSTS); + /* Configure the transfer interrupts */ lpc54_config_xfrints(priv, SDCARD_SEND_MASK); @@ -1894,6 +1882,7 @@ static int lpc54_cancel(FAR struct sdio_dev_s *dev) static int lpc54_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd) { volatile int32_t timeout; + clock_t watchtime; uint32_t events; mcinfo("cmd=%04x\n", cmd); @@ -1933,13 +1922,15 @@ static int lpc54_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd) /* Then wait for the response (or timeout or error) */ + watchtime = clock_systimer(); while ((lpc54_getreg(LPC54_SDMMC_RINTSTS) & events) != events) { - if (--timeout <= 0) + if (clock_systimer() - watchtime > timeout) { mcerr("ERROR: Timeout cmd: %04x events: %04x STA: %08x RINTSTS: %08x\n", cmd, events, lpc54_getreg(LPC54_SDMMC_STATUS), lpc54_getreg(LPC54_SDMMC_RINTSTS)); + return -ETIMEDOUT; } else if ((lpc54_getreg(LPC54_SDMMC_RINTSTS) & SDCARD_INT_RESPERR) != 0) @@ -1947,6 +1938,7 @@ static int lpc54_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd) mcerr("ERROR: SDMMC failure cmd: %04x events: %04x STA: %08x RINTSTS: %08x\n", cmd, events, lpc54_getreg(LPC54_SDMMC_STATUS), lpc54_getreg(LPC54_SDMMC_RINTSTS)); + return -EIO; } } @@ -2545,7 +2537,11 @@ static int lpc54_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, lpc54_putreg((uint32_t)&g_sdmmc_dmadd[0], LPC54_SDMMC_DBADDR); - /* Enable internal DMA, burst size of 4, fixed burst */ + /* Flush ints before we start */ + + lpc54_putreg(SDCARD_TRANSFER_ALL, LPC54_SDMMC_RINTSTS); + + /* Enable internal DMA, burst size of 4, fixed burst */ regval = lpc54_getreg(LPC54_SDMMC_CTRL); regval |= SDMMC_CTRL_INTDMA; @@ -2691,7 +2687,11 @@ static int lpc54_dmasendsetup(FAR struct sdio_dev_s *dev, lpc54_putreg((uint32_t) &g_sdmmc_dmadd[0], LPC54_SDMMC_DBADDR); - /* Enable internal DMA, burst size of 4, fixed burst */ + /* Flush ints before we start */ + + lpc54_putreg(SDCARD_TRANSFER_ALL, LPC54_SDMMC_RINTSTS); + + /* Enable internal DMA, burst size of 4, fixed burst */ regval = lpc54_getreg(LPC54_SDMMC_CTRL); regval |= SDMMC_CTRL_INTDMA; diff --git a/configs/lpcxpresso-lpc54628/README.txt b/configs/lpcxpresso-lpc54628/README.txt index b4e7fef3aa..a871113e96 100644 --- a/configs/lpcxpresso-lpc54628/README.txt +++ b/configs/lpcxpresso-lpc54628/README.txt @@ -112,6 +112,9 @@ STATUS of the time. I still get CRC errors when writing and I have not successfully written to the SD card. It is closer but more TLC is needed. + 2018-10-24: Dave Marples now has the LPC43 SD/MMC working reliably. I + have ported all of Dave's change to the LPC54 but have done no further + testing as of this writing. The feature is still marked EXPERIMENTAL. There is still no support for the Accelerometer, SPIFI, or USB. There is a complete but not entirely functional SD card driver and and tested SPI