diff options
author | px4dev <px4@purgatory.org> | 2013-09-01 13:22:14 -0700 |
---|---|---|
committer | px4dev <px4@purgatory.org> | 2013-09-01 13:22:14 -0700 |
commit | db966877698d63a58a28f5fa32a2ecbda640d290 (patch) | |
tree | 62a673cb2b4455dedc42503949626c90c078306c /nuttx/arch/arm/src | |
parent | 83f0ace158abf8eda7b8561d8fc9e947f1ba3e34 (diff) | |
download | px4-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/arch/arm/src')
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_sdio.c | 108 |
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 |