This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 4b3116df4c3a30db30cc7fefecf9a3342a8dca0e Author: Liam Howatt <[email protected]> AuthorDate: Wed Aug 19 16:29:44 2026 -0400 arch/arm/stm32h5: Support non-DMA and DMA SPI instances together. The stm32h5 SPI driver had some issues when both non-DMA and DMA instances were present at the same time. Modify the driver to allow them to correctly coexist. Signed-off-by: Liam Howatt <[email protected]> --- arch/arm/src/stm32h5/stm32_spi.c | 136 ++++++++++++++++++++++++++++----------- 1 file changed, 99 insertions(+), 37 deletions(-) diff --git a/arch/arm/src/stm32h5/stm32_spi.c b/arch/arm/src/stm32h5/stm32_spi.c index 6e2f0cadcaa..312a4484043 100644 --- a/arch/arm/src/stm32h5/stm32_spi.c +++ b/arch/arm/src/stm32h5/stm32_spi.c @@ -284,6 +284,7 @@ struct stm32_spidev_s uint32_t spiclock; /* Clocking for the SPI module */ uint8_t spiirq; /* SPI IRQ number */ #ifdef CONFIG_STM32_SPI_DMA + bool usedma; /* Whether DMA shall be used for this SPI instance */ volatile uint8_t rxresult; /* Result of the RX DMA */ volatile uint8_t txresult; /* Result of the RX DMA */ #ifdef CONFIG_SPI_TRIGGER @@ -372,9 +373,14 @@ static int spi_hwfeatures(struct spi_dev_s *dev, spi_hwfeatures_t features); #endif static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd); -static void spi_exchange(struct spi_dev_s *dev, - const void *txbuffer, void *rxbuffer, - size_t nwords); +static void spi_exchange_nodma(struct spi_dev_s *dev, + const void *txbuffer, void *rxbuffer, + size_t nwords); +#ifdef CONFIG_STM32_SPI_DMA +static void spi_exchange_dma(struct spi_dev_s *dev, + const void *txbuffer, void *rxbuffer, + size_t nwords); +#endif #ifdef CONFIG_SPI_TRIGGER static int spi_trigger(struct spi_dev_s *dev); #endif @@ -420,7 +426,11 @@ static const struct spi_ops_s g_sp1iops = #endif .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE - .exchange = spi_exchange, +# ifdef CONFIG_STM32_SPI1_DMA + .exchange = spi_exchange_dma, +# else + .exchange = spi_exchange_nodma, +# endif #else .sndblock = spi_sndblock, .recvblock = spi_recvblock, @@ -450,6 +460,7 @@ static struct stm32_spidev_s g_spi1dev = .spiclock = STM32_SPI1_FREQUENCY, .spiirq = STM32_IRQ_SPI1, #ifdef CONFIG_STM32_SPI1_DMA + .usedma = true, .rxreq = GPDMA_REQ_SPI1_RX, .txreq = GPDMA_REQ_SPI1_TX, # if defined(SPI1_DMABUFSIZE_ADJUSTED) @@ -493,7 +504,11 @@ static const struct spi_ops_s g_sp2iops = #endif .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE - .exchange = spi_exchange, +# ifdef CONFIG_STM32_SPI2_DMA + .exchange = spi_exchange_dma, +# else + .exchange = spi_exchange_nodma, +# endif #else .sndblock = spi_sndblock, .recvblock = spi_recvblock, @@ -523,6 +538,7 @@ static struct stm32_spidev_s g_spi2dev = .spiclock = STM32_SPI2_FREQUENCY, .spiirq = STM32_IRQ_SPI2, #ifdef CONFIG_STM32_SPI2_DMA + .usedma = true, .rxreq = GPDMA_REQ_SPI2_RX, .txreq = GPDMA_REQ_SPI2_TX, # if defined(SPI2_DMABUFSIZE_ADJUSTED) @@ -566,7 +582,11 @@ static const struct spi_ops_s g_sp3iops = #endif .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE - .exchange = spi_exchange, +# ifdef CONFIG_STM32_SPI3_DMA + .exchange = spi_exchange_dma, +# else + .exchange = spi_exchange_nodma, +# endif #else .sndblock = spi_sndblock, .recvblock = spi_recvblock, @@ -596,6 +616,7 @@ static struct stm32_spidev_s g_spi3dev = .spiclock = STM32_SPI3_FREQUENCY, .spiirq = STM32_IRQ_SPI3, #ifdef CONFIG_STM32_SPI3_DMA + .usedma = true, .rxreq = GPDMA_REQ_SPI3_RX, .txreq = GPDMA_REQ_SPI3_TX, # if defined(SPI3_DMABUFSIZE_ADJUSTED) @@ -639,7 +660,11 @@ static const struct spi_ops_s g_sp4iops = #endif .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE - .exchange = spi_exchange, +# ifdef CONFIG_STM32_SPI4_DMA + .exchange = spi_exchange_dma, +# else + .exchange = spi_exchange_nodma, +# endif #else .sndblock = spi_sndblock, .recvblock = spi_recvblock, @@ -669,6 +694,7 @@ static struct stm32_spidev_s g_spi4dev = .spiclock = STM32_SPI4_FREQUENCY, .spiirq = STM32_IRQ_SPI4, #ifdef CONFIG_STM32_SPI4_DMA + .usedma = true, .rxreq = GPDMA_REQ_SPI4_RX, .txreq = GPDMA_REQ_SPI4_TX, # if defined(SPI4_DMABUFSIZE_ADJUSTED) @@ -712,7 +738,11 @@ static const struct spi_ops_s g_sp5iops = #endif .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE - .exchange = spi_exchange, +# ifdef CONFIG_STM32_SPI5_DMA + .exchange = spi_exchange_dma, +# else + .exchange = spi_exchange_nodma, +# endif #else .sndblock = spi_sndblock, .recvblock = spi_recvblock, @@ -742,6 +772,7 @@ static struct stm32_spidev_s g_spi5dev = .spiclock = STM32_SPI5_FREQUENCY, .spiirq = STM32_IRQ_SPI5, #ifdef CONFIG_STM32_SPI5_DMA + .usedma = true, .rxreq = GPDMA_REQ_SPI5_RX, .txreq = GPDMA_REQ_SPI5_TX, # if defined(SPI5_DMABUFSIZE_ADJUSTED) @@ -785,7 +816,11 @@ static const struct spi_ops_s g_sp6iops = #endif .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE - .exchange = spi_exchange, +# ifdef CONFIG_STM32_SPI6_DMA + .exchange = spi_exchange_dma, +# else + .exchange = spi_exchange_nodma, +# endif #else .sndblock = spi_sndblock, .recvblock = spi_recvblock, @@ -816,6 +851,7 @@ static struct stm32_spidev_s g_spi6dev = .spiclock = STM32_SPI6_FREQUENCY, .spiirq = STM32_IRQ_SPI6, #ifdef CONFIG_STM32_SPI6_DMA + .usedma = true, .rxreq = GPDMA_REQ_SPI6_RX, .txreq = GPDMA_REQ_SPI6_TX, # if defined(SPI6_DMABUFSIZE_ADJUSTED) @@ -1160,8 +1196,11 @@ static int spi_interrupt(int irq, void *context, void *arg) /* Set result and release wait semaphore */ #ifdef CONFIG_STM32_SPI_DMA - priv->txresult = 0x80; - nxsem_post(&priv->txsem); + if (priv->usedma) + { + priv->txresult = 0x80; + nxsem_post(&priv->txsem); + } #endif } @@ -1891,6 +1930,7 @@ static int spi_hwfeatures(struct spi_dev_s *dev, #endif #ifdef CONFIG_SPI_TRIGGER +# ifdef CONFIG_STM32_SPI_DMA /* Turn deferred trigger mode on or off. Only applicable for DMA mode. If a * transfer is deferred then the DMA will not actually be triggered until a * subsequent call to SPI_TRIGGER to set it off. The thread will be waiting @@ -1898,6 +1938,8 @@ static int spi_hwfeatures(struct spi_dev_s *dev, */ priv->defertrig = ((features & HWFEAT_TRIGGER) != 0); +# endif + features &= ~HWFEAT_TRIGGER; #endif @@ -1987,7 +2029,7 @@ static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd) } /**************************************************************************** - * Name: spi_exchange (no DMA). aka spi_exchange_nodma + * Name: spi_exchange_nodma * * Description: * Exchange a block of data on SPI without using DMA @@ -2007,16 +2049,9 @@ static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd) * ****************************************************************************/ -#if !defined(CONFIG_STM32_SPI_DMA) || defined(CONFIG_STM32_DMACAPABLE) || \ - defined(CONFIG_STM32_SPI_DMATHRESHOLD) -#if !defined(CONFIG_STM32_SPI_DMA) -static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, - void *rxbuffer, size_t nwords) -#else static void spi_exchange_nodma(struct spi_dev_s *dev, const void *txbuffer, void *rxbuffer, size_t nwords) -#endif { struct stm32_spidev_s *priv = (struct stm32_spidev_s *)dev; DEBUGASSERT(priv && priv->spibase); @@ -2167,10 +2202,6 @@ static void spi_exchange_nodma(struct spi_dev_s *dev, while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_SUSP) == 0); } -#endif /* !CONFIG_STM32_SPI_DMA || CONFIG_STM32_DMACAPABLE || - * CONFIG_STM32_SPI_DMATHRESHOLD - */ - /**************************************************************************** * Name: spi_exchange (with DMA capability) * @@ -2193,8 +2224,8 @@ static void spi_exchange_nodma(struct spi_dev_s *dev, ****************************************************************************/ #ifdef CONFIG_STM32_SPI_DMA -static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, - void *rxbuffer, size_t nwords) +static void spi_exchange_dma(struct spi_dev_s *dev, const void *txbuffer, + void *rxbuffer, size_t nwords) { struct stm32_spidev_s *priv = (struct stm32_spidev_s *)dev; struct stm32_gpdma_cfg_s rxdmacfg; @@ -2356,6 +2387,7 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, spi_dmarxstart(priv); spi_dmatxstart(priv); spi_enable(priv, true); + spi_modifyreg(priv, STM32_SPI_IFCR_OFFSET, 0, SPI_IFCR_SUSPC); spi_modifyreg(priv, STM32_SPI_CR1_OFFSET, 0, SPI_CR1_CSTART); } else @@ -2370,6 +2402,7 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, spi_dmarxstart(priv); spi_dmatxstart(priv); spi_enable(priv, true); + spi_modifyreg(priv, STM32_SPI_IFCR_OFFSET, 0, SPI_IFCR_SUSPC); spi_modifyreg(priv, STM32_SPI_CR1_OFFSET, 0, SPI_CR1_CSTART); #endif @@ -2474,8 +2507,21 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *txbuffer, size_t nwords) { +#ifdef CONFIG_STM32_SPI_DMA + struct stm32_spidev_s *priv = (struct stm32_spidev_s *)dev; +#endif + spiinfo("txbuffer=%p nwords=%d\n", txbuffer, nwords); - return spi_exchange(dev, txbuffer, NULL, nwords); +#ifdef CONFIG_STM32_SPI_DMA + if (priv->usedma) + { + return spi_exchange_dma(dev, txbuffer, NULL, nwords); + } + else +#endif + { + return spi_exchange_nodma(dev, txbuffer, NULL, nwords); + } } #endif @@ -2504,8 +2550,21 @@ static void spi_recvblock(struct spi_dev_s *dev, void *rxbuffer, size_t nwords) { +#ifdef CONFIG_STM32_SPI_DMA + struct stm32_spidev_s *priv = (struct stm32_spidev_s *)dev; +#endif + spiinfo("rxbuffer=%p nwords=%d\n", rxbuffer, nwords); - return spi_exchange(dev, NULL, rxbuffer, nwords); +#ifdef CONFIG_STM32_SPI_DMA + if (priv->usedma) + { + return spi_exchange_dma(dev, NULL, rxbuffer, nwords); + } + else +#endif + { + return spi_exchange_nodma(dev, NULL, rxbuffer, nwords); + } } #endif @@ -2675,18 +2734,21 @@ static void spi_bus_initialize(struct stm32_spidev_s *priv) priv->rxdma = NULL; priv->txdma = NULL; - if (priv->config != SIMPLEX_TX) + if (priv->usedma) { - priv->rxdma = stm32_dmachannel(GPDMA_TTYPE_P2M); - DEBUGASSERT(priv->rxdma); - spi_modifyreg(priv, STM32_SPI_CFG1_OFFSET, 0, SPI_CFG1_RXDMAEN); - } + if (priv->config != SIMPLEX_TX) + { + priv->rxdma = stm32_dmachannel(GPDMA_TTYPE_P2M); + DEBUGASSERT(priv->rxdma); + spi_modifyreg(priv, STM32_SPI_CFG1_OFFSET, 0, SPI_CFG1_RXDMAEN); + } - if (priv->config != SIMPLEX_RX) - { - priv->txdma = stm32_dmachannel(GPDMA_TTYPE_M2P); - DEBUGASSERT(priv->txdma); - spi_modifyreg(priv, STM32_SPI_CFG1_OFFSET, 0, SPI_CFG1_TXDMAEN); + if (priv->config != SIMPLEX_RX) + { + priv->txdma = stm32_dmachannel(GPDMA_TTYPE_M2P); + DEBUGASSERT(priv->txdma); + spi_modifyreg(priv, STM32_SPI_CFG1_OFFSET, 0, SPI_CFG1_TXDMAEN); + } } #endif
