From dbcccb2455d759b789d549d25e1fbf489b2d3c83 Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Wed, 7 Jan 2015 17:43:31 -1000 Subject: backport SDIO Fix - no busy waiting --- nuttx/arch/arm/src/stm32/stm32_sdio.c | 79 ++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) mode change 100644 => 100755 nuttx/arch/arm/src/stm32/stm32_sdio.c (limited to 'nuttx/arch') diff --git a/nuttx/arch/arm/src/stm32/stm32_sdio.c b/nuttx/arch/arm/src/stm32/stm32_sdio.c old mode 100644 new mode 100755 index 01663d0a5..61ed1c1f6 --- a/nuttx/arch/arm/src/stm32/stm32_sdio.c +++ b/nuttx/arch/arm/src/stm32/stm32_sdio.c @@ -399,6 +399,9 @@ static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupeven /* Interrupt Handling *******************************************************/ static int stm32_interrupt(int irq, void *context); +#ifdef CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE +static int stm32_rdyinterrupt(int irq, void *context); +#endif /* SDIO interface methods ***************************************************/ @@ -611,12 +614,40 @@ static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask, sdio_eventset_t wkupevent) { irqstate_t flags; +#ifdef CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE + int pinset; +#endif /* Save all of the data and set the new interrupt mask in one, atomic * operation. */ - flags = irqsave(); + +#ifdef CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE + if ((waitmask & SDIOWAIT_WRCOMPLETE) != 0) + { + + /* Do not use this in STM32_SDIO_MASK register */ + + waitmask &= !SDIOWAIT_WRCOMPLETE; + + pinset = GPIO_SDIO_D0 & (GPIO_PORT_MASK|GPIO_PIN_MASK); + pinset |= (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI); + + /* Arm the SDIO_D Ready and install Isr */ + + stm32_gpiosetevent(pinset, true, false, false, stm32_rdyinterrupt); + } + + /* Disarm SDIO_D ready */ + + if ((wkupevent & SDIOWAIT_WRCOMPLETE) != 0) + { + stm32_gpiosetevent(GPIO_SDIO_D0, false, false, false , NULL); + stm32_configgpio(GPIO_SDIO_D0); + + } +#endif priv->waitevents = waitevents; priv->wkupevent = wkupevent; priv->waitmask = waitmask; @@ -1229,7 +1260,28 @@ static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupeven /**************************************************************************** * Interrrupt Handling ****************************************************************************/ +#ifdef CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE +/**************************************************************************** + * Name: stm32_rdyinterrupt + * + * Description: + * SDIO ready interrupt handler + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * None + * + ****************************************************************************/ +static int stm32_rdyinterrupt(int irq, void *context) +{ + struct stm32_dev_s *priv = &g_sdiodev; + stm32_endwait(priv, SDIOWAIT_WRCOMPLETE); + return OK; +} +#endif /**************************************************************************** * Name: stm32_interrupt * @@ -2228,6 +2280,14 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev, * interrupts. */ +#if defined(CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE) + if ((eventset & SDIOWAIT_WRCOMPLETE) != 0) + { + waitmask = SDIOWAIT_WRCOMPLETE; + } + else + { +#endif waitmask = 0; if ((eventset & SDIOWAIT_CMDDONE) != 0) { @@ -2247,6 +2307,9 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev, /* Enable event-related interrupts */ putreg32(SDIO_WAITALL_ICR, STM32_SDIO_ICR); +#if defined(CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE) + } +#endif stm32_configwaitints(priv, waitmask, eventset, 0); } @@ -2316,6 +2379,20 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, } } +#if defined(CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE) + if ((priv->waitevents & SDIOWAIT_WRCOMPLETE) != 0) + { + + /* Atomically read pin to see if ready (true) and determine if ISR fired + * If Pin is ready and if ISR did NOT fire end the wait here + */ + + if (stm32_gpioread(GPIO_SDIO_D0) && ((priv->wkupevent & SDIOWAIT_WRCOMPLETE) == 0)) + { + stm32_endwait(priv, SDIOWAIT_WRCOMPLETE); + } + } +#endif /* Loop until the event (or the timeout occurs). Race conditions are avoided * by calling stm32_waitenable prior to triggering the logic that will cause * the wait to terminate. Under certain race conditions, the waited-for -- cgit v1.2.3