This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 46c0aaf7080 arch/arm: Bound SDMMC/SDIO command response wait by time
46c0aaf7080 is described below
commit 46c0aaf7080f98f0c8849c39681e717b1fdb9684
Author: Swatantra Yadav <[email protected]>
AuthorDate: Fri Oct 23 02:55:41 2026 +0530
arch/arm: Bound SDMMC/SDIO command response wait by time
Follow up on commit 62b41ad9b4 to fix the same SDMMC/SDIO polling
timeout starvation issue across the remaining STM32 families and clone
architectures (stm32f7, stm32h5, stm32h7, stm32l4, at32, gd32f4).
The command waitresponse functions previously polled the status register
bounded only by an iteration counter (up to 0x7fffffff iterations).
If the card clock stops or the peripheral freezes, the hardware CTIMEOUT
flag is never generated and the loop spins for INT32_MAX iterations
while holding the filesystem lock, causing high CPU load and starving
lower-priority threads.
Bound the wait by time using clock_systime_ticks(): 250 ms for
response-bearing commands (the maximum timeout allowed by the SD
physical layer specification) and 10 ms for no-response/R3/R7 commands.
Fixes #19792
Signed-off-by: Swatantra Yadav <[email protected]>
---
arch/arm/src/at32/at32_sdio.c | 106 +++++++++--------
arch/arm/src/gd32f4/gd32f4xx_sdio.c | 216 ++++++++++++++++++-----------------
arch/arm/src/stm32f7/stm32_sdmmc.c | 17 +--
arch/arm/src/stm32h5/stm32_sdmmc.c | 17 +--
arch/arm/src/stm32h7/stm32_sdmmc.c | 17 +--
arch/arm/src/stm32l4/stm32l4_sdmmc.c | 17 +--
6 files changed, 207 insertions(+), 183 deletions(-)
diff --git a/arch/arm/src/at32/at32_sdio.c b/arch/arm/src/at32/at32_sdio.c
index 087ba435fbe..67d01a015ea 100644
--- a/arch/arm/src/at32/at32_sdio.c
+++ b/arch/arm/src/at32/at32_sdio.c
@@ -170,8 +170,8 @@
/* Timing */
-#define SDIO_CMDTIMEOUT (100000)
-#define SDIO_LONGTIMEOUT (0x7fffffff)
+#define SDIO_CMDTIMEOUT_MS (10)
+#define SDIO_LONGTIMEOUT_MS (250)
/* DTIMER setting */
@@ -878,9 +878,10 @@ static void at32_dumpsamples(struct at32_dev_s *priv)
static void at32_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg)
{
struct at32_dev_s *priv = (struct at32_dev_s *)arg;
- DEBUGASSERT(priv->dmamode);
sdio_eventset_t result;
+ DEBUGASSERT(priv->dmamode);
+
/* In the normal case, SDIO appears to handle the End-Of-Transfer interrupt
* first with the End-Of-DMA event occurring significantly later. On
* transfer errors, however, the DMA error will occur before the End-of-
@@ -1142,7 +1143,7 @@ static void at32_recvfifo(struct at32_dev_s *priv)
for (i = 0; i < (int)priv->remaining; i++)
{
- *ptr++ = data.b[i];
+ *ptr++ = data.b[i];
}
/* Now the transfer is finished */
@@ -1694,6 +1695,7 @@ static sdio_capset_t at32_capabilities(struct sdio_dev_s
*dev)
static sdio_statset_t at32_status(struct sdio_dev_s *dev)
{
struct at32_dev_s *priv = (struct at32_dev_s *)dev;
+
return priv->cdstatus;
}
@@ -1717,6 +1719,7 @@ static sdio_statset_t at32_status(struct sdio_dev_s *dev)
static void at32_widebus(struct sdio_dev_s *dev, bool wide)
{
struct at32_dev_s *priv = (struct at32_dev_s *)dev;
+
priv->widebus = wide;
}
@@ -1856,23 +1859,23 @@ static int at32_sendcmd(struct sdio_dev_s *dev,
uint32_t cmd,
switch (cmd & MMCSD_RESPONSE_MASK)
{
- case MMCSD_NO_RESPONSE:
- regval |= SDIO_CMD_NORESPONSE;
- break;
-
- case MMCSD_R1_RESPONSE:
- case MMCSD_R1B_RESPONSE:
- case MMCSD_R3_RESPONSE:
- case MMCSD_R4_RESPONSE:
- case MMCSD_R5_RESPONSE:
- case MMCSD_R6_RESPONSE:
- case MMCSD_R7_RESPONSE:
- regval |= SDIO_CMD_SHORTRESPONSE;
- break;
-
- case MMCSD_R2_RESPONSE:
- regval |= SDIO_CMD_LONGRESPONSE;
- break;
+ case MMCSD_NO_RESPONSE:
+ regval |= SDIO_CMD_NORESPONSE;
+ break;
+
+ case MMCSD_R1_RESPONSE:
+ case MMCSD_R1B_RESPONSE:
+ case MMCSD_R3_RESPONSE:
+ case MMCSD_R4_RESPONSE:
+ case MMCSD_R5_RESPONSE:
+ case MMCSD_R6_RESPONSE:
+ case MMCSD_R7_RESPONSE:
+ regval |= SDIO_CMD_SHORTRESPONSE;
+ break;
+
+ case MMCSD_R2_RESPONSE:
+ regval |= SDIO_CMD_LONGRESPONSE;
+ break;
}
/* Set CPSMEN and the command index */
@@ -2126,41 +2129,44 @@ static int at32_cancel(struct sdio_dev_s *dev)
static int at32_waitresponse(struct sdio_dev_s *dev, uint32_t cmd)
{
- int32_t timeout;
+ clock_t timeout;
+ clock_t start;
uint32_t events;
switch (cmd & MMCSD_RESPONSE_MASK)
{
- case MMCSD_NO_RESPONSE:
- events = SDIO_CMDDONE_STA;
- timeout = SDIO_CMDTIMEOUT;
- break;
-
- case MMCSD_R1_RESPONSE:
- case MMCSD_R1B_RESPONSE:
- case MMCSD_R2_RESPONSE:
- case MMCSD_R4_RESPONSE:
- case MMCSD_R5_RESPONSE:
- case MMCSD_R6_RESPONSE:
- events = SDIO_RESPDONE_STA;
- timeout = SDIO_LONGTIMEOUT;
- break;
-
- case MMCSD_R3_RESPONSE:
- case MMCSD_R7_RESPONSE:
- events = SDIO_RESPDONE_STA;
- timeout = SDIO_CMDTIMEOUT;
- break;
-
- default:
- return -EINVAL;
+ case MMCSD_NO_RESPONSE:
+ events = SDIO_CMDDONE_STA;
+ timeout = MSEC2TICK(SDIO_CMDTIMEOUT_MS);
+ break;
+
+ case MMCSD_R1_RESPONSE:
+ case MMCSD_R1B_RESPONSE:
+ case MMCSD_R2_RESPONSE:
+ case MMCSD_R4_RESPONSE:
+ case MMCSD_R5_RESPONSE:
+ case MMCSD_R6_RESPONSE:
+ events = SDIO_RESPDONE_STA;
+ timeout = MSEC2TICK(SDIO_LONGTIMEOUT_MS);
+ break;
+
+ case MMCSD_R3_RESPONSE:
+ case MMCSD_R7_RESPONSE:
+ events = SDIO_RESPDONE_STA;
+ timeout = MSEC2TICK(SDIO_CMDTIMEOUT_MS);
+ break;
+
+ default:
+ return -EINVAL;
}
/* Then wait for the response (or timeout) */
+ start = clock_systime_ticks();
+
while ((getreg32(AT32_SDIO_STA) & events) == 0)
{
- if (--timeout <= 0)
+ if (clock_systime_ticks() - start > timeout)
{
mcerr("ERROR: Timeout cmd: %08" PRIx32 " events: %08" PRIx32
" STA: %08" PRIx32 "\n",
@@ -2956,10 +2962,10 @@ static void at32_callback(void *arg)
{
/* Yes.. queue it */
- mcinfo("Queuing callback to %p(%p)\n",
- priv->callback, priv->cbarg);
- work_queue(HPWORK, &priv->cbwork, priv->callback,
- priv->cbarg, 0);
+ mcinfo("Queuing callback to %p(%p)\n",
+ priv->callback, priv->cbarg);
+ work_queue(HPWORK, &priv->cbwork, priv->callback,
+ priv->cbarg, 0);
}
else
{
diff --git a/arch/arm/src/gd32f4/gd32f4xx_sdio.c
b/arch/arm/src/gd32f4/gd32f4xx_sdio.c
index 53c96924393..fc38df67674 100644
--- a/arch/arm/src/gd32f4/gd32f4xx_sdio.c
+++ b/arch/arm/src/gd32f4/gd32f4xx_sdio.c
@@ -149,8 +149,8 @@
/* Timing */
-#define SDIO_CMDTIMEOUT (100000)
-#define SDIO_LONGTIMEOUT (0x7fffffff)
+#define SDIO_CMDTIMEOUT_MS (10)
+#define SDIO_LONGTIMEOUT_MS (250)
/* DTIMER setting */
@@ -506,18 +506,20 @@ static void gd32_sdio_clock_set(periph_enum type)
switch (type)
{
- default:
- return;
- case ENABLE:
- rcu_en = RCU_APB2EN_SDIOEN;
- regaddr = GD32_RCU_APB2EN;
- modifyreg32(regaddr, 0, rcu_en);
- break;
- case DISABLE:
- rcu_en = RCU_APB2EN_SDIOEN;
- regaddr = GD32_RCU_APB2EN;
- modifyreg32(regaddr, rcu_en, 0);
- break;
+ case ENABLE:
+ rcu_en = RCU_APB2EN_SDIOEN;
+ regaddr = GD32_RCU_APB2EN;
+ modifyreg32(regaddr, 0, rcu_en);
+ break;
+
+ case DISABLE:
+ rcu_en = RCU_APB2EN_SDIOEN;
+ regaddr = GD32_RCU_APB2EN;
+ modifyreg32(regaddr, rcu_en, 0);
+ break;
+
+ default:
+ return;
}
}
@@ -889,9 +891,10 @@ static void gd32_dumpsamples(struct gd32_dev_s *priv)
static void gd32_dmacallback(DMA_HANDLE handle, uint16_t status, void *arg)
{
struct gd32_dev_s *priv = (struct gd32_dev_s *)arg;
- DEBUGASSERT(priv->dmamode);
sdio_eventset_t result;
+ DEBUGASSERT(priv->dmamode);
+
/* In the normal case, SDIO appears to handle the End-Of-Transfer interrupt
* first with the End-Of-DMA event occurring significantly later. On
* transfer errors, however, the DMA error will occur before the End-of-
@@ -1159,7 +1162,7 @@ static void gd32_recv_fifo(struct gd32_dev_s *priv)
for (i = 0; i < (int)priv->remaining; i++)
{
- *ptr++ = data.b[i];
+ *ptr++ = data.b[i];
}
/* Now the transfer is finished */
@@ -1206,7 +1209,7 @@ static void gd32_event_timeout(wdparm_t arg)
{
/* Yes.. wake up any waiting threads */
- gd32_end_wait(priv, SDIOWAIT_TIMEOUT);
+ gd32_end_wait(priv, SDIOWAIT_TIMEOUT);
mcerr("Timeout: remaining: %d\n", priv->remaining);
}
@@ -1659,6 +1662,7 @@ static sdio_capset_t gd32_capabilities(struct sdio_dev_s
*dev)
static sdio_statset_t gd32_status(struct sdio_dev_s *dev)
{
struct gd32_dev_s *priv = (struct gd32_dev_s *)dev;
+
return priv->cdstatus;
}
@@ -1682,6 +1686,7 @@ static sdio_statset_t gd32_status(struct sdio_dev_s *dev)
static void gd32_widebus(struct sdio_dev_s *dev, bool wide)
{
struct gd32_dev_s *priv = (struct gd32_dev_s *)dev;
+
priv->widebus = wide;
}
@@ -1704,45 +1709,45 @@ static void gd32_clock(struct sdio_dev_s *dev, enum
sdio_clock_e rate)
{
uint32_t clkctl;
- switch (rate)
- {
- /* Disable clocking (with default ID mode divisor) */
+ switch (rate)
+ {
+ /* Disable clocking (with default ID mode divisor) */
- default:
- case CLOCK_SDIO_DISABLED:
- clkctl = GD32_CLCKCTL_INIT;
- break;
+ default:
+ case CLOCK_SDIO_DISABLED:
+ clkctl = GD32_CLCKCTL_INIT;
+ break;
- /* Enable in initial ID mode clocking (<400KHz) */
+ /* Enable in initial ID mode clocking (<400KHz) */
- case CLOCK_IDMODE:
- clkctl = (GD32_CLCKCTL_INIT | SDIO_CLKCTL_CLKEN);
- break;
+ case CLOCK_IDMODE:
+ clkctl = (GD32_CLCKCTL_INIT | SDIO_CLKCTL_CLKEN);
+ break;
- /* Enable in MMC normal operation clocking */
+ /* Enable in MMC normal operation clocking */
- case CLOCK_MMC_TRANSFER:
- clkctl = (SDIO_CLKCTL_MMCXFR | SDIO_CLKCTL_CLKEN);
- break;
+ case CLOCK_MMC_TRANSFER:
+ clkctl = (SDIO_CLKCTL_MMCXFR | SDIO_CLKCTL_CLKEN);
+ break;
- /* SD normal operation clocking (wide 4-bit mode) */
+ /* SD normal operation clocking (wide 4-bit mode) */
- case CLOCK_SD_TRANSFER_4BIT:
+ case CLOCK_SD_TRANSFER_4BIT:
#ifndef CONFIG_GD32_SDIO_WIDTH_D1_ONLY
- clkctl = (SDIO_CLKCTL_SDWIDEXFR | SDIO_CLKCTL_CLKEN);
- break;
+ clkctl = (SDIO_CLKCTL_SDWIDEXFR | SDIO_CLKCTL_CLKEN);
+ break;
#endif
- /* SD normal operation clocking (narrow 1-bit mode) */
+ /* SD normal operation clocking (narrow 1-bit mode) */
- case CLOCK_SD_TRANSFER_1BIT:
- clkctl = (SDIO_CLKCTL_SDXFR | SDIO_CLKCTL_CLKEN);
- break;
- }
+ case CLOCK_SD_TRANSFER_1BIT:
+ clkctl = (SDIO_CLKCTL_SDXFR | SDIO_CLKCTL_CLKEN);
+ break;
+ }
- /* Set the new clock frequency along with the clock enable/disable bit */
+ /* Set the new clock frequency along with the clock enable/disable bit */
- gd32_set_clkctl(clkctl);
+ gd32_set_clkctl(clkctl);
}
/****************************************************************************
@@ -1821,23 +1826,23 @@ static int gd32_send_cmd(struct sdio_dev_s *dev,
uint32_t cmd,
switch (cmd & MMCSD_RESPONSE_MASK)
{
- case MMCSD_NO_RESPONSE:
- regval |= SDIO_CMDCTL_NORESPONSE;
- break;
-
- case MMCSD_R1_RESPONSE:
- case MMCSD_R1B_RESPONSE:
- case MMCSD_R3_RESPONSE:
- case MMCSD_R4_RESPONSE:
- case MMCSD_R5_RESPONSE:
- case MMCSD_R6_RESPONSE:
- case MMCSD_R7_RESPONSE:
- regval |= SDIO_CMDCTL_SHORTRESPONSE;
- break;
-
- case MMCSD_R2_RESPONSE:
- regval |= SDIO_CMDCTL_LONGRESPONSE;
- break;
+ case MMCSD_NO_RESPONSE:
+ regval |= SDIO_CMDCTL_NORESPONSE;
+ break;
+
+ case MMCSD_R1_RESPONSE:
+ case MMCSD_R1B_RESPONSE:
+ case MMCSD_R3_RESPONSE:
+ case MMCSD_R4_RESPONSE:
+ case MMCSD_R5_RESPONSE:
+ case MMCSD_R6_RESPONSE:
+ case MMCSD_R7_RESPONSE:
+ regval |= SDIO_CMDCTL_SHORTRESPONSE;
+ break;
+
+ case MMCSD_R2_RESPONSE:
+ regval |= SDIO_CMDCTL_LONGRESPONSE;
+ break;
}
/* Set CPSMEN and the command index */
@@ -2091,41 +2096,44 @@ static int gd32_cancel(struct sdio_dev_s *dev)
static int gd32_wait_response(struct sdio_dev_s *dev, uint32_t cmd)
{
- int32_t timeout;
+ clock_t timeout;
+ clock_t start;
uint32_t events;
switch (cmd & MMCSD_RESPONSE_MASK)
{
- case MMCSD_NO_RESPONSE:
- events = SDIO_CMDDONE_STAT;
- timeout = SDIO_CMDTIMEOUT;
- break;
-
- case MMCSD_R1_RESPONSE:
- case MMCSD_R1B_RESPONSE:
- case MMCSD_R2_RESPONSE:
- case MMCSD_R4_RESPONSE:
- case MMCSD_R5_RESPONSE:
- case MMCSD_R6_RESPONSE:
- events = SDIO_RESPDONE_STAT;
- timeout = SDIO_LONGTIMEOUT;
- break;
-
- case MMCSD_R3_RESPONSE:
- case MMCSD_R7_RESPONSE:
- events = SDIO_RESPDONE_STAT;
- timeout = SDIO_CMDTIMEOUT;
- break;
-
- default:
- return -EINVAL;
+ case MMCSD_NO_RESPONSE:
+ events = SDIO_CMDDONE_STAT;
+ timeout = MSEC2TICK(SDIO_CMDTIMEOUT_MS);
+ break;
+
+ case MMCSD_R1_RESPONSE:
+ case MMCSD_R1B_RESPONSE:
+ case MMCSD_R2_RESPONSE:
+ case MMCSD_R4_RESPONSE:
+ case MMCSD_R5_RESPONSE:
+ case MMCSD_R6_RESPONSE:
+ events = SDIO_RESPDONE_STAT;
+ timeout = MSEC2TICK(SDIO_LONGTIMEOUT_MS);
+ break;
+
+ case MMCSD_R3_RESPONSE:
+ case MMCSD_R7_RESPONSE:
+ events = SDIO_RESPDONE_STAT;
+ timeout = MSEC2TICK(SDIO_CMDTIMEOUT_MS);
+ break;
+
+ default:
+ return -EINVAL;
}
/* Then wait for the response (or timeout) */
+ start = clock_systime_ticks();
+
while ((getreg32(GD32_SDIO_STAT) & events) == 0)
{
- if (--timeout <= 0)
+ if (clock_systime_ticks() - start > timeout)
{
mcerr("ERROR: Timeout cmd: %08" PRIx32 " events: %08" PRIx32
" STAT: %08" PRIx32 "\n",
@@ -2399,27 +2407,25 @@ static void gd32_wait_enable(struct sdio_dev_s *dev,
* interrupts.
*/
+ waitmask = 0;
+ if ((eventset & SDIOWAIT_CMDDONE) != 0)
{
- waitmask = 0;
- if ((eventset & SDIOWAIT_CMDDONE) != 0)
- {
- waitmask |= SDIO_CMDDONE_INTEN;
- }
+ waitmask |= SDIO_CMDDONE_INTEN;
+ }
- if ((eventset & SDIOWAIT_RESPONSEDONE) != 0)
- {
- waitmask |= SDIO_RESPDONE_INTEN;
- }
+ if ((eventset & SDIOWAIT_RESPONSEDONE) != 0)
+ {
+ waitmask |= SDIO_RESPDONE_INTEN;
+ }
- if ((eventset & SDIOWAIT_TRANSFERDONE) != 0)
- {
- waitmask |= SDIO_XFRDONE_INTEN;
- }
+ if ((eventset & SDIOWAIT_TRANSFERDONE) != 0)
+ {
+ waitmask |= SDIO_XFRDONE_INTEN;
+ }
- /* Enable event-related interrupts */
+ /* Enable event-related interrupts */
- putreg32(SDIO_WAITALL_INTC, GD32_SDIO_INTC);
- }
+ putreg32(SDIO_WAITALL_INTC, GD32_SDIO_INTC);
gd32_config_waitints(priv, waitmask, eventset, 0);
@@ -2915,10 +2921,10 @@ static void gd32_callback(void *arg)
{
/* Yes.. queue it */
- mcinfo("Queuing callback to %p(%p)\n",
- priv->callback, priv->cbarg);
- work_queue(HPWORK, &priv->cbwork, priv->callback,
- priv->cbarg, 0);
+ mcinfo("Queuing callback to %p(%p)\n",
+ priv->callback, priv->cbarg);
+ work_queue(HPWORK, &priv->cbwork, priv->callback,
+ priv->cbarg, 0);
}
else
{
diff --git a/arch/arm/src/stm32f7/stm32_sdmmc.c
b/arch/arm/src/stm32f7/stm32_sdmmc.c
index 68872d6fe0e..272a169e6f8 100644
--- a/arch/arm/src/stm32f7/stm32_sdmmc.c
+++ b/arch/arm/src/stm32f7/stm32_sdmmc.c
@@ -226,8 +226,8 @@
/* Timing */
-#define SDMMC_CMDTIMEOUT (100000)
-#define SDMMC_LONGTIMEOUT (0x7fffffff)
+#define SDMMC_CMDTIMEOUT_MS (10)
+#define SDMMC_LONGTIMEOUT_MS (250)
/* DTIMER setting */
@@ -2412,14 +2412,15 @@ static int stm32_cancel(struct sdio_dev_s *dev)
static int stm32_waitresponse(struct sdio_dev_s *dev, uint32_t cmd)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
- int32_t timeout;
+ clock_t timeout;
+ clock_t start;
uint32_t events;
switch (cmd & MMCSD_RESPONSE_MASK)
{
case MMCSD_NO_RESPONSE:
events = STM32_SDMMC_CMDDONE_STA;
- timeout = SDMMC_CMDTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_CMDTIMEOUT_MS);
break;
case MMCSD_R1_RESPONSE:
@@ -2429,13 +2430,13 @@ static int stm32_waitresponse(struct sdio_dev_s *dev,
uint32_t cmd)
case MMCSD_R5_RESPONSE:
case MMCSD_R6_RESPONSE:
events = STM32_SDMMC_RESPDONE_STA;
- timeout = SDMMC_LONGTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_LONGTIMEOUT_MS);
break;
case MMCSD_R3_RESPONSE:
case MMCSD_R7_RESPONSE:
events = STM32_SDMMC_RESPDONE_STA;
- timeout = SDMMC_CMDTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_CMDTIMEOUT_MS);
break;
default:
@@ -2444,9 +2445,11 @@ static int stm32_waitresponse(struct sdio_dev_s *dev,
uint32_t cmd)
/* Then wait for the response (or timeout) */
+ start = clock_systime_ticks();
+
while ((sdmmc_getreg32(priv, STM32_SDMMC_STA_OFFSET) & events) == 0)
{
- if (--timeout <= 0)
+ if (clock_systime_ticks() - start > timeout)
{
mcerr("ERROR: Timeout cmd: %08" PRIx32
" events: %08" PRIx32 " STA: %08" PRIx32 "\n",
diff --git a/arch/arm/src/stm32h5/stm32_sdmmc.c
b/arch/arm/src/stm32h5/stm32_sdmmc.c
index a9faa13e45c..fac7cb88f12 100644
--- a/arch/arm/src/stm32h5/stm32_sdmmc.c
+++ b/arch/arm/src/stm32h5/stm32_sdmmc.c
@@ -228,8 +228,8 @@
/* Timing */
-#define SDMMC_CMDTIMEOUT (100000)
-#define SDMMC_LONGTIMEOUT (0x7fffffff)
+#define SDMMC_CMDTIMEOUT_MS (10)
+#define SDMMC_LONGTIMEOUT_MS (250)
/* DTIMER setting */
@@ -2554,14 +2554,15 @@ static int stm32_cancel(struct sdio_dev_s *dev)
static int stm32_waitresponse(struct sdio_dev_s *dev, uint32_t cmd)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
- int32_t timeout;
+ clock_t timeout;
+ clock_t start;
uint32_t events;
switch (cmd & MMCSD_RESPONSE_MASK)
{
case MMCSD_NO_RESPONSE:
events = STM32_SDMMC_CMDDONE_STA;
- timeout = SDMMC_CMDTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_CMDTIMEOUT_MS);
break;
case MMCSD_R1_RESPONSE:
@@ -2571,13 +2572,13 @@ static int stm32_waitresponse(struct sdio_dev_s *dev,
uint32_t cmd)
case MMCSD_R5_RESPONSE:
case MMCSD_R6_RESPONSE:
events = STM32_SDMMC_RESPDONE_STA;
- timeout = SDMMC_LONGTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_LONGTIMEOUT_MS);
break;
case MMCSD_R3_RESPONSE:
case MMCSD_R7_RESPONSE:
events = STM32_SDMMC_RESPDONE_STA;
- timeout = SDMMC_CMDTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_CMDTIMEOUT_MS);
break;
default:
@@ -2586,9 +2587,11 @@ static int stm32_waitresponse(struct sdio_dev_s *dev,
uint32_t cmd)
/* Then wait for the response (or timeout) */
+ start = clock_systime_ticks();
+
while ((sdmmc_getreg32(priv, STM32_SDMMC_STA_OFFSET) & events) == 0)
{
- if (--timeout <= 0)
+ if (clock_systime_ticks() - start > timeout)
{
mcerr("ERROR: Timeout cmd: %08" PRIx32 " events: %08" PRIx32
" STA: %08" PRIx32 "\n",
diff --git a/arch/arm/src/stm32h7/stm32_sdmmc.c
b/arch/arm/src/stm32h7/stm32_sdmmc.c
index 45ba5e21ab4..d84ced38b2d 100644
--- a/arch/arm/src/stm32h7/stm32_sdmmc.c
+++ b/arch/arm/src/stm32h7/stm32_sdmmc.c
@@ -250,8 +250,8 @@
/* Timing */
-#define SDMMC_CMDTIMEOUT (100000)
-#define SDMMC_LONGTIMEOUT (0x7fffffff)
+#define SDMMC_CMDTIMEOUT_MS (10)
+#define SDMMC_LONGTIMEOUT_MS (250)
/* DTIMER setting */
@@ -2708,14 +2708,15 @@ static int stm32_cancel(struct sdio_dev_s *dev)
static int stm32_waitresponse(struct sdio_dev_s *dev, uint32_t cmd)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
- int32_t timeout;
+ clock_t timeout;
+ clock_t start;
uint32_t events;
switch (cmd & MMCSD_RESPONSE_MASK)
{
case MMCSD_NO_RESPONSE:
events = STM32_SDMMC_CMDDONE_STA;
- timeout = SDMMC_CMDTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_CMDTIMEOUT_MS);
break;
case MMCSD_R1_RESPONSE:
@@ -2725,13 +2726,13 @@ static int stm32_waitresponse(struct sdio_dev_s *dev,
uint32_t cmd)
case MMCSD_R5_RESPONSE:
case MMCSD_R6_RESPONSE:
events = STM32_SDMMC_RESPDONE_STA;
- timeout = SDMMC_LONGTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_LONGTIMEOUT_MS);
break;
case MMCSD_R3_RESPONSE:
case MMCSD_R7_RESPONSE:
events = STM32_SDMMC_RESPDONE_STA;
- timeout = SDMMC_CMDTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_CMDTIMEOUT_MS);
break;
default:
@@ -2740,9 +2741,11 @@ static int stm32_waitresponse(struct sdio_dev_s *dev,
uint32_t cmd)
/* Then wait for the response (or timeout) */
+ start = clock_systime_ticks();
+
while ((sdmmc_getreg32(priv, STM32_SDMMC_STA_OFFSET) & events) == 0)
{
- if (--timeout <= 0)
+ if (clock_systime_ticks() - start > timeout)
{
mcerr("ERROR: Timeout cmd: %08" PRIx32 " events: %08" PRIx32
" STA: %08" PRIx32 "\n",
diff --git a/arch/arm/src/stm32l4/stm32l4_sdmmc.c
b/arch/arm/src/stm32l4/stm32l4_sdmmc.c
index ca252ba7e4a..83281dbd05c 100644
--- a/arch/arm/src/stm32l4/stm32l4_sdmmc.c
+++ b/arch/arm/src/stm32l4/stm32l4_sdmmc.c
@@ -167,8 +167,8 @@
/* Timing */
-#define SDMMC_CMDTIMEOUT (100000)
-#define SDMMC_LONGTIMEOUT (0x7fffffff)
+#define SDMMC_CMDTIMEOUT_MS (10)
+#define SDMMC_LONGTIMEOUT_MS (250)
/* Big DTIMER setting */
@@ -2176,14 +2176,15 @@ static int stm32_cancel(struct sdio_dev_s *dev)
static int stm32_waitresponse(struct sdio_dev_s *dev, uint32_t cmd)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
- int32_t timeout;
+ clock_t timeout;
+ clock_t start;
uint32_t events;
switch (cmd & MMCSD_RESPONSE_MASK)
{
case MMCSD_NO_RESPONSE:
events = STM32_SDMMC_CMDDONE_STA;
- timeout = SDMMC_CMDTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_CMDTIMEOUT_MS);
break;
case MMCSD_R1_RESPONSE:
@@ -2191,7 +2192,7 @@ static int stm32_waitresponse(struct sdio_dev_s *dev,
uint32_t cmd)
case MMCSD_R2_RESPONSE:
case MMCSD_R6_RESPONSE:
events = STM32_SDMMC_RESPDONE_STA;
- timeout = SDMMC_LONGTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_LONGTIMEOUT_MS);
break;
case MMCSD_R4_RESPONSE:
@@ -2201,7 +2202,7 @@ static int stm32_waitresponse(struct sdio_dev_s *dev,
uint32_t cmd)
case MMCSD_R3_RESPONSE:
case MMCSD_R7_RESPONSE:
events = STM32_SDMMC_RESPDONE_STA;
- timeout = SDMMC_CMDTIMEOUT;
+ timeout = MSEC2TICK(SDMMC_CMDTIMEOUT_MS);
break;
default:
@@ -2210,9 +2211,11 @@ static int stm32_waitresponse(struct sdio_dev_s *dev,
uint32_t cmd)
/* Then wait for the response (or timeout) */
+ start = clock_systime_ticks();
+
while ((sdmmc_getreg32(priv, STM32_SDMMC_STA_OFFSET) & events) == 0)
{
- if (--timeout <= 0)
+ if (clock_systime_ticks() - start > timeout)
{
mcerr("ERROR: Timeout cmd: %08" PRIx32
" events: %08" PRIx32 " STA: %08" PRIx32 "\n",