summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpx4dev <px4@purgatory.org>2013-09-01 13:22:14 -0700
committerpx4dev <px4@purgatory.org>2013-09-01 13:22:14 -0700
commitdb966877698d63a58a28f5fa32a2ecbda640d290 (patch)
tree62a673cb2b4455dedc42503949626c90c078306c /nuttx
parent83f0ace158abf8eda7b8561d8fc9e947f1ba3e34 (diff)
downloadpx4-nuttx-db966877698d63a58a28f5fa32a2ecbda640d290.tar.gz
px4-nuttx-db966877698d63a58a28f5fa32a2ecbda640d290.tar.bz2
px4-nuttx-db966877698d63a58a28f5fa32a2ecbda640d290.zip
Teach the STM32 SDIO driver how to determine whether a transfer can be performed safely using DMA.
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_sdio.c108
1 files changed, 61 insertions, 47 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_sdio.c b/nuttx/arch/arm/src/stm32/stm32_sdio.c
index 7265808ae..e110b0a7a 100644
--- a/nuttx/arch/arm/src/stm32/stm32_sdio.c
+++ b/nuttx/arch/arm/src/stm32/stm32_sdio.c
@@ -2470,7 +2470,6 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
uint32_t dblocksize;
- int ret = -EINVAL;
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
@@ -2481,39 +2480,47 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
/* Wide bus operation is required for DMA */
- if (priv->widebus)
+ if (!priv->widebus)
{
- stm32_sampleinit();
- stm32_sample(priv, SAMPLENDX_BEFORE_SETUP);
+ return -EINVAL;
+ }
+
+ /* DMA must be possible to the buffer */
+
+ if (!stm32_dmacapable((uintptr_t)buffer, (buflen + 3) >> 2, SDIO_RXDMA32_CONFIG))
+ {
+ return -EFAULT;
+ }
+
+ stm32_sampleinit();
+ stm32_sample(priv, SAMPLENDX_BEFORE_SETUP);
- /* Save the destination buffer information for use by the interrupt handler */
+ /* Save the destination buffer information for use by the interrupt handler */
- priv->buffer = (uint32_t*)buffer;
- priv->remaining = buflen;
- priv->dmamode = true;
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = buflen;
+ priv->dmamode = true;
- /* Then set up the SDIO data path */
+ /* Then set up the SDIO data path */
- dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
- stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize|SDIO_DCTRL_DTDIR);
+ dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
+ stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize|SDIO_DCTRL_DTDIR);
- /* Configure the RX DMA */
+ /* Configure the RX DMA */
- stm32_configxfrints(priv, SDIO_DMARECV_MASK);
+ stm32_configxfrints(priv, SDIO_DMARECV_MASK);
- putreg32(1, SDIO_DCTRL_DMAEN_BB);
- stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32_t)buffer,
- (buflen + 3) >> 2, SDIO_RXDMA32_CONFIG);
-
- /* Start the DMA */
+ putreg32(1, SDIO_DCTRL_DMAEN_BB);
+ stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32_t)buffer,
+ (buflen + 3) >> 2, SDIO_RXDMA32_CONFIG);
- stm32_sample(priv, SAMPLENDX_BEFORE_ENABLE);
- stm32_dmastart(priv->dma, stm32_dmacallback, priv, false);
- stm32_sample(priv, SAMPLENDX_AFTER_SETUP);
- ret = OK;
- }
+ /* Start the DMA */
- return ret;
+ stm32_sample(priv, SAMPLENDX_BEFORE_ENABLE);
+ stm32_dmastart(priv->dma, stm32_dmacallback, priv, false);
+ stm32_sample(priv, SAMPLENDX_AFTER_SETUP);
+
+ return OK;
}
#endif
@@ -2553,43 +2560,50 @@ static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
/* Wide bus operation is required for DMA */
- if (priv->widebus)
+ if (!priv->widebus)
{
- stm32_sampleinit();
- stm32_sample(priv, SAMPLENDX_BEFORE_SETUP);
+ return -EINVAL;
+ }
- /* Save the source buffer information for use by the interrupt handler */
+ /* DMA must be possible to the buffer */
- priv->buffer = (uint32_t*)buffer;
- priv->remaining = buflen;
- priv->dmamode = true;
+ if (!stm32_dmacapable((uintptr_t)buffer, (buflen + 3) >> 2, SDIO_TXDMA32_CONFIG))
+ {
+ return -EFAULT;
+ }
- /* Then set up the SDIO data path */
+ stm32_sampleinit();
+ stm32_sample(priv, SAMPLENDX_BEFORE_SETUP);
- dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
- stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize);
+ /* Save the source buffer information for use by the interrupt handler */
- /* Configure the TX DMA */
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = buflen;
+ priv->dmamode = true;
- stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32_t)buffer,
- (buflen + 3) >> 2, SDIO_TXDMA32_CONFIG);
+ /* Then set up the SDIO data path */
- stm32_sample(priv, SAMPLENDX_BEFORE_ENABLE);
- putreg32(1, SDIO_DCTRL_DMAEN_BB);
+ dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
+ stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize);
- /* Start the DMA */
+ /* Configure the TX DMA */
- stm32_dmastart(priv->dma, stm32_dmacallback, priv, false);
- stm32_sample(priv, SAMPLENDX_AFTER_SETUP);
+ stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32_t)buffer,
+ (buflen + 3) >> 2, SDIO_TXDMA32_CONFIG);
- /* Enable TX interrrupts */
+ stm32_sample(priv, SAMPLENDX_BEFORE_ENABLE);
+ putreg32(1, SDIO_DCTRL_DMAEN_BB);
- stm32_configxfrints(priv, SDIO_DMASEND_MASK);
+ /* Start the DMA */
- ret = OK;
- }
+ stm32_dmastart(priv->dma, stm32_dmacallback, priv, false);
+ stm32_sample(priv, SAMPLENDX_AFTER_SETUP);
- return ret;
+ /* Enable TX interrrupts */
+
+ stm32_configxfrints(priv, SDIO_DMASEND_MASK);
+
+ return OK;
}
#endif