MMCSD SDIO: Add support for a new SDWAIT_WRCOMPLETE condition. The previous logic used a busy-wait loop to pool the card R1 start to determine when the card was ready for the next transfer. That busy-wait can be quite long -- hundreds of milliseconds. And alternative is to look the the SD D0 pin which will change state when the card is no longer busy.

This logic implements a change the avoids the busy-wait poll by reconfiguring the SD D0 pin as a GPIO interrupt, then waiting for the card to becom ready without taking up CPU cycles.

This change is conditioned on CONFIG_MMCSD_SDIOWATI_WRCOMPLETE and is currenlty only implemented for the STM32 SDIO driver.

From David Sidrane
This commit is contained in:
Gregory Nutt
2015-01-08 06:23:42 -06:00
parent 1f10c56dd0
commit 1842525cc2
4 changed files with 146 additions and 16 deletions
Regular → Executable
+17
View File
@@ -38,6 +38,23 @@ config MMCSD_HAVECARDDETECT
SDIO driver card detection is
100% accurate
config MMCSD_SDIOWAIT_WRCOMPLETE
bool "Use SDIO_D Busy to detect Write Complete"
default n
---help---
SDIO driver will use SDIO_D Busy signalling to detect Write Complete.
This option when selected, will enable the MMCSD driver to use the
underlying (stm32_sdio only) drivers implementation of the SD specs
SDIO_D Busy signalling to detect Write Complete. This will avoid
potentially very long (600Ms+) busy waiting in the MMCSD driver.
To implement SDIO_D Busy signalling, the underlying driver must
be capable of switching the GPIO_SDIO_D0 to be a rising edge sensitive
interrupt pin. It must then, condition that pin to detect the rising edge
on receipt of SDWAIT_WRCOMPLETE in the SDIO_WAITENABLE call and
return it back to regular SDIO mode, when either the ISR fires or pin is
found to be high in the SDIO_EVENTWAIT call.
config MMCSD_SPI
bool "MMC/SD SPI transfer support"
default y
Regular → Executable
+15
View File
@@ -1150,6 +1150,15 @@ static int mmcsd_transferready(FAR struct mmcsd_state_s *priv)
* the TRANSFER state when the card completes the WRITE operation.
*/
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR,
MMCSD_BLOCK_WDATADELAY);
if (ret != OK)
{
fdbg("ERROR: mmcsd_eventwait for transfer ready failed: %d\n", ret);
}
#endif
starttime = clock_systimer();
do
{
@@ -1721,6 +1730,12 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
return ret;
}
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
/* Arm the write complete detection with timeout */
SDIO_WAITENABLE(priv->dev, SDIOWAIT_WRCOMPLETE|SDIOWAIT_TIMEOUT);
#endif
/* On success, return the number of blocks written */
return 1;