From db966877698d63a58a28f5fa32a2ecbda640d290 Mon Sep 17 00:00:00 2001 From: px4dev Date: Sun, 1 Sep 2013 13:22:14 -0700 Subject: Teach the STM32 SDIO driver how to determine whether a transfer can be performed safely using DMA. --- nuttx/arch/arm/src/stm32/stm32_sdio.c | 108 +++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 47 deletions(-) (limited to 'nuttx/arch/arm/src/stm32/stm32_sdio.c') 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 -- cgit v1.2.3