mirror of
https://github.com/apache/nuttx.git
synced 2026-05-21 13:03:30 +08:00
Fixes race condition in event wait logic of SDMMC driver.
This change makes it so that the timeout is set as part of the SDIO_WAITENABLE call instead of the SDIO_EVENTWAIT call. By doing so, you eliminate all opportunity for a race condition. stm32h7:sdmmc Check if busy ended early
This commit is contained in:
committed by
Xiang Xiao
parent
cd08694698
commit
b21cb3308a
@@ -398,9 +398,8 @@ static int cxd56_sdio_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void cxd56_sdio_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void cxd56_sdio_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int cxd56_sdio_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2494,7 +2493,7 @@ static int cxd56_sdio_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void cxd56_sdio_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct cxd56_sdiodev_s *priv = (struct cxd56_sdiodev_s *)dev;
|
||||
uint32_t waitints;
|
||||
@@ -2523,6 +2522,32 @@ static void cxd56_sdio_waitenable(FAR struct sdio_dev_s *dev,
|
||||
/* Enable event-related interrupts */
|
||||
|
||||
cxd56_configwaitints(priv, waitints, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a corner case */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
cxd56_eventtimeout, (wdparm_t)priv);
|
||||
if (ret != OK)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2546,8 +2571,7 @@ static void cxd56_sdio_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct cxd56_sdiodev_s *priv = (struct cxd56_sdiodev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2561,30 +2585,6 @@ static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev,
|
||||
DEBUGASSERT((priv->waitevents != 0 && priv->wkupevent == 0) ||
|
||||
(priv->waitevents == 0 && priv->wkupevent != 0));
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a corner case */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
return SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
cxd56_eventtimeout, (wdparm_t)priv);
|
||||
if (ret != OK)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling cxd56_waitenable prior to triggering the logic that
|
||||
* will cause the wait to terminate. Under certain race conditions, the
|
||||
|
||||
@@ -350,9 +350,8 @@ static int imxrt_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void imxrt_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t imxrt_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t imxrt_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void imxrt_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int imxrt_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2627,7 +2626,7 @@ static int imxrt_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void imxrt_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct imxrt_dev_s *priv = (struct imxrt_dev_s *)dev;
|
||||
uint32_t waitints;
|
||||
@@ -2660,6 +2659,33 @@ static void imxrt_waitenable(FAR struct sdio_dev_s *dev,
|
||||
/* Enable event-related interrupts */
|
||||
|
||||
imxrt_configwaitints(priv, waitints, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a corner case */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
imxrt_eventtimeout, (wdparm_t)priv);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2683,8 +2709,7 @@ static void imxrt_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t imxrt_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t imxrt_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct imxrt_dev_s *priv = (struct imxrt_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0; int ret;
|
||||
@@ -2698,31 +2723,6 @@ static sdio_eventset_t imxrt_eventwait(FAR struct sdio_dev_s *dev,
|
||||
DEBUGASSERT((priv->waitevents != 0 && priv->wkupevent == 0) ||
|
||||
(priv->waitevents == 0 && priv->wkupevent != 0));
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a corner case */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
return SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
imxrt_eventtimeout, (wdparm_t)priv);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling imxrt_waitenable prior to triggering the logic
|
||||
* that will cause the wait to terminate. Under certain race
|
||||
|
||||
@@ -329,9 +329,8 @@ static int kinetis_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void kinetis_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
kinetis_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t kinetis_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void kinetis_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int kinetis_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2430,7 +2429,7 @@ static int kinetis_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void kinetis_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev;
|
||||
uint32_t waitints;
|
||||
@@ -2459,6 +2458,32 @@ static void kinetis_waitenable(FAR struct sdio_dev_s *dev,
|
||||
/* Enable event-related interrupts */
|
||||
|
||||
kinetis_configwaitints(priv, waitints, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a corner case */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
kinetis_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2482,8 +2507,7 @@ static void kinetis_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t kinetis_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t kinetis_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2497,30 +2521,6 @@ static sdio_eventset_t kinetis_eventwait(FAR struct sdio_dev_s *dev,
|
||||
DEBUGASSERT((priv->waitevents != 0 && priv->wkupevent == 0) ||
|
||||
(priv->waitevents == 0 && priv->wkupevent != 0));
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a corner case */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
return SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
kinetis_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling kinetis_waitenable prior to triggering the logic
|
||||
* that will cause the wait to terminate. Under certain race conditions,
|
||||
|
||||
@@ -384,9 +384,8 @@ static int lpc17_40_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void lpc17_40_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
lpc17_40_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t lpc17_40_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void lpc17_40_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int lpc17_40_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2237,10 +2236,11 @@ static int lpc17_40_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void lpc17_40_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct lpc17_40_dev_s *priv = (struct lpc17_40_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
@@ -2272,6 +2272,33 @@ static void lpc17_40_waitenable(FAR struct sdio_dev_s *dev,
|
||||
|
||||
putreg32(SDCARD_WAITALL_ICR, LPC17_40_SDCARD_CLEAR);
|
||||
lpc17_40_configwaitints(priv, waitmask, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
lpc17_40_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2295,8 +2322,7 @@ static void lpc17_40_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t lpc17_40_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t lpc17_40_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct lpc17_40_dev_s *priv = (struct lpc17_40_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2311,35 +2337,6 @@ static sdio_eventset_t lpc17_40_eventwait(FAR struct sdio_dev_s *dev,
|
||||
flags = enter_critical_section();
|
||||
DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
/* Then just tell the caller that we already timed out */
|
||||
|
||||
wkupevent = SDIOWAIT_TIMEOUT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
lpc17_40_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling lpc17_40_waitenable prior to triggering the logic
|
||||
* that will cause the wait to terminate. Under certain race conditions,
|
||||
@@ -2388,7 +2385,6 @@ static sdio_eventset_t lpc17_40_eventwait(FAR struct sdio_dev_s *dev,
|
||||
priv->xfrflags = 0;
|
||||
#endif
|
||||
|
||||
errout:
|
||||
leave_critical_section(flags);
|
||||
lpc17_40_dumpsamples(priv);
|
||||
return wkupevent;
|
||||
|
||||
@@ -325,9 +325,8 @@ static int lpc43_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void lpc43_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
lpc43_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t lpc43_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void lpc43_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static void lpc43_callback(struct lpc43_dev_s *priv);
|
||||
@@ -2194,7 +2193,7 @@ static int lpc43_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void lpc43_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct lpc43_dev_s *priv = (struct lpc43_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
@@ -2229,6 +2228,34 @@ static void lpc43_waitenable(FAR struct sdio_dev_s *dev,
|
||||
/* Enable event-related interrupts */
|
||||
|
||||
lpc43_config_waitints(priv, waitmask, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
lpc43_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2252,8 +2279,7 @@ static void lpc43_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t lpc43_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t lpc43_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct lpc43_dev_s *priv = (struct lpc43_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2270,35 +2296,6 @@ static sdio_eventset_t lpc43_eventwait(FAR struct sdio_dev_s *dev,
|
||||
flags = enter_critical_section();
|
||||
DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
/* Then just tell the caller that we already timed out */
|
||||
|
||||
wkupevent = SDIOWAIT_TIMEOUT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
lpc43_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling lpc43_waitenable prior to triggering the logic that
|
||||
* will cause the wait to terminate. Under certain race conditions, the
|
||||
|
||||
@@ -324,9 +324,8 @@ static int lpc54_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void lpc54_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
lpc54_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t lpc54_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void lpc54_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static void lpc54_callback(struct lpc54_dev_s *priv);
|
||||
@@ -2189,7 +2188,7 @@ static int lpc54_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void lpc54_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct lpc54_dev_s *priv = (struct lpc54_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
@@ -2224,6 +2223,34 @@ static void lpc54_waitenable(FAR struct sdio_dev_s *dev,
|
||||
/* Enable event-related interrupts */
|
||||
|
||||
lpc54_config_waitints(priv, waitmask, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
lpc54_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2247,8 +2274,7 @@ static void lpc54_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t lpc54_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t lpc54_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct lpc54_dev_s *priv = (struct lpc54_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2265,35 +2291,6 @@ static sdio_eventset_t lpc54_eventwait(FAR struct sdio_dev_s *dev,
|
||||
flags = enter_critical_section();
|
||||
DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
/* Then just tell the caller that we already timed out */
|
||||
|
||||
wkupevent = SDIOWAIT_TIMEOUT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
lpc54_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling lpc54_waitenable prior to triggering the logic that
|
||||
* will cause the wait to terminate. Under certain race conditions, the
|
||||
|
||||
@@ -489,9 +489,8 @@ static int sam_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
sam_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void sam_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int sam_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2233,7 +2232,7 @@ static int sam_recvnotimpl(FAR struct sdio_dev_s *dev,
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
@@ -2268,6 +2267,32 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*/
|
||||
|
||||
sam_configwaitints(priv, waitmask, eventset);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a cornercase */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
sam_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2291,8 +2316,7 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2310,35 +2334,6 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
||||
|
||||
sam_enableints(priv);
|
||||
|
||||
/* There is a race condition here... the event may have completed before
|
||||
* we get here. In this case waitevents will be zero, but wkupevents will
|
||||
* be non-zero (and, hopefully, the semaphore count will also be non-zero).
|
||||
*/
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
return SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
sam_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling sam_waitenable prior to triggering the logic that
|
||||
* will cause the wait to terminate. Under certain race conditions, the
|
||||
|
||||
@@ -572,9 +572,8 @@ static int sam_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
sam_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void sam_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int sam_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2651,7 +2650,7 @@ static int sam_recvnotimpl(FAR struct sdio_dev_s *dev,
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
@@ -2686,6 +2685,41 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*/
|
||||
|
||||
sam_configwaitints(priv, waitmask, eventset);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a cornercase */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer. I am not sure why this is, but I am
|
||||
* currently seeing some additional delays when DMA is used.
|
||||
*/
|
||||
|
||||
if (priv->txbusy)
|
||||
{
|
||||
/* TX transfers can be VERY long in the worst case */
|
||||
|
||||
timeout = MAX(5000, timeout);
|
||||
}
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
sam_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
lcderr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2709,8 +2743,7 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2728,44 +2761,6 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
||||
|
||||
sam_enableints(priv);
|
||||
|
||||
/* There is a race condition here... the event may have completed before
|
||||
* we get here. In this case waitevents will be zero, but wkupevent will
|
||||
* be non-zero (and, hopefully, the semaphore count will also be non-zero).
|
||||
*/
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
return SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer. I am not sure why this is, but I am
|
||||
* currently seeing some additional delays when DMA is used.
|
||||
*/
|
||||
|
||||
if (priv->txbusy)
|
||||
{
|
||||
/* TX transfers can be VERY long in the worst case */
|
||||
|
||||
timeout = MAX(5000, timeout);
|
||||
}
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
sam_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
lcderr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling sam_waitenable prior to triggering the logic that
|
||||
* will cause the wait to terminate. Under certain race conditions, the
|
||||
|
||||
@@ -344,9 +344,8 @@ static int sam_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void sam_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int sam_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2831,7 +2830,7 @@ static int sam_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||
uint32_t waitints;
|
||||
@@ -2864,6 +2863,33 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
/* Enable event-related interrupts */
|
||||
|
||||
sam_configwaitints(priv, waitints, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a corner case */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
sam_eventtimeout, (wdparm_t)priv);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2887,11 +2913,10 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0; int ret;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
|
||||
/* There is a race condition here... the event may have completed before
|
||||
* we get here. In this case waitevents will be zero, but wkupevents
|
||||
@@ -2902,31 +2927,6 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
||||
DEBUGASSERT((priv->waitevents != 0 && priv->wkupevent == 0) ||
|
||||
(priv->waitevents == 0 && priv->wkupevent != 0));
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a corner case */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
return SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
sam_eventtimeout, (wdparm_t)priv);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling sam_waitenable prior to triggering the logic
|
||||
* that will cause the wait to terminate. Under certain race
|
||||
|
||||
@@ -507,9 +507,8 @@ static int sam_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
sam_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void sam_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int sam_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2696,7 +2695,7 @@ static int sam_recvnotimpl(FAR struct sdio_dev_s *dev,
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
@@ -2731,6 +2730,41 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*/
|
||||
|
||||
sam_configwaitints(priv, waitmask, eventset);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a cornercase */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer. I am not sure why this is, but I am
|
||||
* currently seeing some additional delays when DMA is used.
|
||||
*/
|
||||
|
||||
if (priv->txbusy)
|
||||
{
|
||||
/* TX transfers can be VERY long in the worst case */
|
||||
|
||||
timeout = MAX(5000, timeout);
|
||||
}
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
sam_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2754,8 +2788,7 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2776,44 +2809,6 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
||||
|
||||
sam_enableints(priv);
|
||||
|
||||
/* There is a race condition here... the event may have completed before
|
||||
* we get here. In this case waitevents will be zero, but wkupevent will
|
||||
* be non-zero (and, hopefully, the semaphore count will also be non-zero).
|
||||
*/
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase */
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
return SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer. I am not sure why this is, but I am
|
||||
* currently seeing some additional delays when DMA is used.
|
||||
*/
|
||||
|
||||
if (priv->txbusy)
|
||||
{
|
||||
/* TX transfers can be VERY long in the worst case */
|
||||
|
||||
timeout = MAX(5000, timeout);
|
||||
}
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
sam_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until the event (or the timeout occurs). Race conditions are
|
||||
* avoided by calling sam_waitenable prior to triggering the logic that
|
||||
* will cause the wait to terminate. Under certain race conditions, the
|
||||
|
||||
@@ -473,9 +473,8 @@ static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
stm32_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void stm32_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int stm32_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2429,7 +2428,7 @@ static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
@@ -2474,6 +2473,34 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
}
|
||||
|
||||
stm32_configwaitints(priv, waitmask, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
stm32_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2497,8 +2524,7 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2527,35 +2553,6 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
|
||||
#endif
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
/* Then just tell the caller that we already timed out */
|
||||
|
||||
wkupevent = SDIOWAIT_TIMEOUT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
stm32_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
if ((priv->waitevents & SDIOWAIT_WRCOMPLETE) != 0)
|
||||
{
|
||||
@@ -2620,7 +2617,6 @@ errout_with_waitints:
|
||||
priv->xfrflags = 0;
|
||||
#endif
|
||||
|
||||
errout:
|
||||
leave_critical_section(flags);
|
||||
stm32_dumpsamples(priv);
|
||||
return wkupevent;
|
||||
|
||||
@@ -547,9 +547,8 @@ static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
stm32_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void stm32_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int stm32_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2689,7 +2688,7 @@ static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
@@ -2734,6 +2733,34 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
}
|
||||
|
||||
stm32_configwaitints(priv, waitmask, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
stm32_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2757,8 +2784,7 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2787,35 +2813,6 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
|
||||
#endif
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
/* Then just tell the caller that we already timed out */
|
||||
|
||||
wkupevent = SDIOWAIT_TIMEOUT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
stm32_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
if ((priv->waitevents & SDIOWAIT_WRCOMPLETE) != 0)
|
||||
{
|
||||
@@ -2880,7 +2877,6 @@ errout_with_waitints:
|
||||
priv->xfrflags = 0;
|
||||
#endif
|
||||
|
||||
errout:
|
||||
leave_critical_section(flags);
|
||||
stm32_dumpsamples(priv);
|
||||
return wkupevent;
|
||||
|
||||
@@ -489,9 +489,8 @@ static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
stm32_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void stm32_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int stm32_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2744,10 +2743,10 @@ static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
uint32_t waitmask = 0;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
@@ -2762,12 +2761,20 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
if ((eventset & SDIOWAIT_WRCOMPLETE) != 0)
|
||||
{
|
||||
waitmask = SDIOWAIT_WRCOMPLETE;
|
||||
/* Read pin to see if ready (true) skip timeout */
|
||||
|
||||
if (stm32_gpioread(priv->d0_gpio))
|
||||
{
|
||||
eventset &= ~SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
waitmask = SDIOWAIT_WRCOMPLETE;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
waitmask = 0;
|
||||
if ((eventset & SDIOWAIT_CMDDONE) != 0)
|
||||
{
|
||||
waitmask |= STM32_SDMMC_CMDDONE_MASK;
|
||||
@@ -2789,6 +2796,34 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
}
|
||||
|
||||
stm32_configwaitints(priv, waitmask, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
stm32_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < OK)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2812,8 +2847,7 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2842,35 +2876,6 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
|
||||
#endif
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
/* Then just tell the caller that we already timed out */
|
||||
|
||||
wkupevent = SDIOWAIT_TIMEOUT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
stm32_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < OK)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
if ((priv->waitevents & SDIOWAIT_WRCOMPLETE) != 0)
|
||||
{
|
||||
@@ -2932,7 +2937,6 @@ errout_with_waitints:
|
||||
|
||||
stm32_configwaitints(priv, 0, 0, 0);
|
||||
|
||||
errout:
|
||||
leave_critical_section(flags);
|
||||
stm32_dumpsamples(priv);
|
||||
return wkupevent;
|
||||
|
||||
@@ -500,9 +500,8 @@ static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
/* EVENT handler */
|
||||
|
||||
static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static sdio_eventset_t
|
||||
stm32_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
sdio_eventset_t eventset, uint32_t timeout);
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev);
|
||||
static void stm32_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
static int stm32_registercallback(FAR struct sdio_dev_s *dev,
|
||||
@@ -2510,7 +2509,7 @@ static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset)
|
||||
sdio_eventset_t eventset, uint32_t timeout)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
uint32_t waitmask;
|
||||
@@ -2555,6 +2554,34 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
}
|
||||
|
||||
stm32_configwaitints(priv, waitmask, eventset, 0);
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
priv->wkupevent = SDIOWAIT_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
stm32_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -2578,8 +2605,7 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
uint32_t timeout)
|
||||
static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
sdio_eventset_t wkupevent = 0;
|
||||
@@ -2608,35 +2634,6 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
|
||||
#endif
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
|
||||
{
|
||||
int delay;
|
||||
|
||||
/* Yes.. Handle a cornercase: The user request a timeout event but
|
||||
* with timeout == 0?
|
||||
*/
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
/* Then just tell the caller that we already timed out */
|
||||
|
||||
wkupevent = SDIOWAIT_TIMEOUT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
|
||||
delay = MSEC2TICK(timeout);
|
||||
ret = wd_start(&priv->waitwdog, delay,
|
||||
stm32_eventtimeout, (wdparm_t)priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
mcerr("ERROR: wd_start failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
if ((priv->waitevents & SDIOWAIT_WRCOMPLETE) != 0)
|
||||
{
|
||||
@@ -2701,7 +2698,6 @@ errout_with_waitints:
|
||||
priv->xfrflags = 0;
|
||||
#endif
|
||||
|
||||
errout:
|
||||
leave_critical_section(flags);
|
||||
stm32_dumpsamples(priv);
|
||||
return wkupevent;
|
||||
|
||||
+33
-27
@@ -178,7 +178,7 @@ static int mmcsd_verifystate(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
static bool mmcsd_wrprotected(FAR struct mmcsd_state_s *priv);
|
||||
static int mmcsd_eventwait(FAR struct mmcsd_state_s *priv,
|
||||
sdio_eventset_t failevents, uint32_t timeout);
|
||||
sdio_eventset_t failevents);
|
||||
static int mmcsd_transferready(FAR struct mmcsd_state_s *priv);
|
||||
#ifndef CONFIG_MMCSD_MULTIBLOCK_DISABLE
|
||||
static int mmcsd_stoptransmission(FAR struct mmcsd_state_s *priv);
|
||||
@@ -486,8 +486,8 @@ static int mmsd_get_scr(FAR struct mmcsd_state_s *priv, uint32_t scr[2])
|
||||
SDIO_RECVSETUP(priv->dev, (FAR uint8_t *)scr, 8);
|
||||
|
||||
SDIO_WAITENABLE(priv->dev,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT |
|
||||
SDIOWAIT_ERROR);
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_SCR_DATADELAY);
|
||||
|
||||
/* Send CMD55 APP_CMD with argument as card's RCA */
|
||||
|
||||
@@ -496,6 +496,7 @@ static int mmsd_get_scr(FAR struct mmcsd_state_s *priv, uint32_t scr[2])
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: RECVR1 for CMD55 failed: %d\n", ret);
|
||||
SDIO_CANCEL(priv->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -512,8 +513,7 @@ static int mmsd_get_scr(FAR struct mmcsd_state_s *priv, uint32_t scr[2])
|
||||
|
||||
/* Wait for data to be transferred */
|
||||
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_SCR_DATADELAY);
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: mmcsd_eventwait for READ DATA failed: %d\n", ret);
|
||||
@@ -1153,13 +1153,13 @@ static bool mmcsd_wrprotected(FAR struct mmcsd_state_s *priv)
|
||||
****************************************************************************/
|
||||
|
||||
static int mmcsd_eventwait(FAR struct mmcsd_state_s *priv,
|
||||
sdio_eventset_t failevents, uint32_t timeout)
|
||||
sdio_eventset_t failevents)
|
||||
{
|
||||
sdio_eventset_t wkupevent;
|
||||
|
||||
/* Wait for the set of events enabled by SDIO_EVENTENABLE. */
|
||||
|
||||
wkupevent = SDIO_EVENTWAIT(priv->dev, timeout);
|
||||
wkupevent = SDIO_EVENTWAIT(priv->dev);
|
||||
|
||||
/* SDIO_EVENTWAIT returns the event set containing the event(s) that ended
|
||||
* the wait. It should always be non-zero, but may contain failure as
|
||||
@@ -1228,8 +1228,7 @@ static int mmcsd_transferready(FAR struct mmcsd_state_s *priv)
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_BLOCK_WDATADELAY);
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: mmcsd_eventwait for transfer ready failed: %d\n", ret);
|
||||
@@ -1440,7 +1439,8 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, priv->blocksize, 1);
|
||||
SDIO_WAITENABLE(priv->dev,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_BLOCK_RDATADELAY);
|
||||
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
if ((priv->caps & SDIO_CAPS_DMASUPPORTED) != 0)
|
||||
@@ -1449,6 +1449,7 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv,
|
||||
if (ret != OK)
|
||||
{
|
||||
finfo("SDIO_DMARECVSETUP: error %d\n", ret);
|
||||
SDIO_CANCEL(priv->dev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1475,8 +1476,7 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
/* Then wait for the data transfer to complete */
|
||||
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_BLOCK_RDATADELAY);
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: CMD17 transfer failed: %d\n", ret);
|
||||
@@ -1576,7 +1576,8 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, priv->blocksize, nblocks);
|
||||
SDIO_WAITENABLE(priv->dev,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
nblocks * MMCSD_BLOCK_RDATADELAY);
|
||||
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
if ((priv->caps & SDIO_CAPS_DMASUPPORTED) != 0)
|
||||
@@ -1585,6 +1586,7 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
|
||||
if (ret != OK)
|
||||
{
|
||||
finfo("SDIO_DMARECVSETUP: error %d\n", ret);
|
||||
SDIO_CANCEL(priv->dev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1609,8 +1611,7 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
nblocks * MMCSD_BLOCK_RDATADELAY);
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: CMD18 transfer failed: %d\n", ret);
|
||||
@@ -1798,7 +1799,8 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, priv->blocksize, 1);
|
||||
SDIO_WAITENABLE(priv->dev,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_BLOCK_WDATADELAY);
|
||||
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
if ((priv->caps & SDIO_CAPS_DMASUPPORTED) != 0)
|
||||
@@ -1807,6 +1809,7 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
|
||||
if (ret != OK)
|
||||
{
|
||||
finfo("SDIO_DMASENDSETUP: error %d\n", ret);
|
||||
SDIO_CANCEL(priv->dev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1834,9 +1837,7 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
||||
ret = mmcsd_eventwait(priv,
|
||||
SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_BLOCK_WDATADELAY);
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: CMD24 transfer failed: %d\n", ret);
|
||||
@@ -1852,7 +1853,8 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
/* Arm the write complete detection with timeout */
|
||||
|
||||
SDIO_WAITENABLE(priv->dev, SDIOWAIT_WRCOMPLETE | SDIOWAIT_TIMEOUT);
|
||||
SDIO_WAITENABLE(priv->dev, SDIOWAIT_WRCOMPLETE | SDIOWAIT_TIMEOUT,
|
||||
MMCSD_BLOCK_WDATADELAY);
|
||||
#endif
|
||||
|
||||
/* On success, return the number of blocks written */
|
||||
@@ -2003,7 +2005,8 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, priv->blocksize, nblocks);
|
||||
SDIO_WAITENABLE(priv->dev,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
nblocks * MMCSD_BLOCK_WDATADELAY);
|
||||
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
if ((priv->caps & SDIO_CAPS_DMASUPPORTED) != 0)
|
||||
@@ -2012,6 +2015,7 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
|
||||
if (ret != OK)
|
||||
{
|
||||
finfo("SDIO_DMASENDSETUP: error %d\n", ret);
|
||||
SDIO_CANCEL(priv->dev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -2041,8 +2045,7 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
||||
evret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
nblocks * MMCSD_BLOCK_WDATADELAY);
|
||||
evret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
if (evret != OK)
|
||||
{
|
||||
ferr("ERROR: CMD25 transfer failed: %d\n", evret);
|
||||
@@ -2077,7 +2080,8 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
/* Arm the write complete detection with timeout */
|
||||
|
||||
SDIO_WAITENABLE(priv->dev, SDIOWAIT_WRCOMPLETE | SDIOWAIT_TIMEOUT);
|
||||
SDIO_WAITENABLE(priv->dev, SDIOWAIT_WRCOMPLETE | SDIOWAIT_TIMEOUT,
|
||||
nblocks * MMCSD_BLOCK_WDATADELAY);
|
||||
#endif
|
||||
|
||||
/* On success, return the number of blocks written */
|
||||
@@ -2845,7 +2849,8 @@ static int mmcsd_read_csd(FAR struct mmcsd_state_s *priv)
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, 512, 1);
|
||||
SDIO_WAITENABLE(priv->dev,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_BLOCK_RDATADELAY);
|
||||
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
if ((priv->caps & SDIO_CAPS_DMASUPPORTED) != 0)
|
||||
@@ -2854,6 +2859,7 @@ static int mmcsd_read_csd(FAR struct mmcsd_state_s *priv)
|
||||
if (ret != OK)
|
||||
{
|
||||
finfo("SDIO_DMARECVSETUP: error %d\n", ret);
|
||||
SDIO_CANCEL(priv->dev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -2873,13 +2879,13 @@ static int mmcsd_read_csd(FAR struct mmcsd_state_s *priv)
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: Could not get MMC extended CSD register: %d\n", ret);
|
||||
SDIO_CANCEL(priv->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Then wait for the data transfer to complete */
|
||||
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_BLOCK_RDATADELAY);
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: CMD17 transfer failed: %d\n", ret);
|
||||
|
||||
@@ -229,7 +229,8 @@ int sdio_io_rw_extended(FAR struct sdio_dev_s *dev, bool write,
|
||||
|
||||
SDIO_BLOCKSETUP(dev, blocklen, nblocks);
|
||||
SDIO_WAITENABLE(dev,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
SDIO_CMD53_TIMEOUT_MS);
|
||||
|
||||
if (write)
|
||||
{
|
||||
@@ -242,7 +243,7 @@ int sdio_io_rw_extended(FAR struct sdio_dev_s *dev, bool write,
|
||||
SDIO_DMASENDSETUP(dev, buf, blocklen * nblocks);
|
||||
SDIO_SENDCMD(dev, SD_ACMD53, arg.value);
|
||||
|
||||
wkupevent = SDIO_EVENTWAIT(dev, SDIO_CMD53_TIMEOUT_MS);
|
||||
wkupevent = SDIO_EVENTWAIT(dev);
|
||||
ret = SDIO_RECVR5(dev, SD_ACMD53, &data);
|
||||
}
|
||||
else
|
||||
@@ -251,7 +252,7 @@ int sdio_io_rw_extended(FAR struct sdio_dev_s *dev, bool write,
|
||||
ret = SDIO_RECVR5(dev, SD_ACMD53, &data);
|
||||
|
||||
SDIO_DMASENDSETUP(dev, buf, blocklen * nblocks);
|
||||
wkupevent = SDIO_EVENTWAIT(dev, SDIO_CMD53_TIMEOUT_MS);
|
||||
wkupevent = SDIO_EVENTWAIT(dev);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -260,7 +261,7 @@ int sdio_io_rw_extended(FAR struct sdio_dev_s *dev, bool write,
|
||||
SDIO_DMARECVSETUP(dev, buf, blocklen * nblocks);
|
||||
SDIO_SENDCMD(dev, SD_ACMD53, arg.value);
|
||||
|
||||
wkupevent = SDIO_EVENTWAIT(dev, SDIO_CMD53_TIMEOUT_MS);
|
||||
wkupevent = SDIO_EVENTWAIT(dev);
|
||||
ret = SDIO_RECVR5(dev, SD_ACMD53, &data);
|
||||
}
|
||||
|
||||
|
||||
@@ -683,7 +683,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define SDIO_WAITENABLE(dev,eventset) ((dev)->waitenable(dev,eventset))
|
||||
#define SDIO_WAITENABLE(dev,eventset,timeout) ((dev)->waitenable(dev,eventset,timeout))
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_EVENTWAIT
|
||||
@@ -706,7 +706,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define SDIO_EVENTWAIT(dev,timeout) ((dev)->eventwait(dev,timeout))
|
||||
#define SDIO_EVENTWAIT(dev) ((dev)->eventwait(dev))
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_CALLBACKENABLE
|
||||
@@ -920,8 +920,9 @@ struct sdio_dev_s
|
||||
|
||||
/* Event/Callback support */
|
||||
|
||||
void (*waitenable)(FAR struct sdio_dev_s *dev, sdio_eventset_t eventset);
|
||||
sdio_eventset_t (*eventwait)(FAR struct sdio_dev_s *dev, uint32_t timeout);
|
||||
void (*waitenable)(FAR struct sdio_dev_s *dev, sdio_eventset_t eventset,
|
||||
uint32_t timeout);
|
||||
sdio_eventset_t (*eventwait)(FAR struct sdio_dev_s *dev);
|
||||
void (*callbackenable)(FAR struct sdio_dev_s *dev,
|
||||
sdio_eventset_t eventset);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user