From 3b55f35bb32852c53a85d60c645da7b324f1508f Mon Sep 17 00:00:00 2001 From: Daniel Agar Date: Wed, 2 Jan 2019 18:50:40 +0000 Subject: [PATCH] Merged in dagar/nuttx/pr-stm32f7_SPI_DMA_per_bus (pull request #798) stm32f7 enable separate DMA per SPI configuration Approved-by: GregoryN --- arch/arm/src/stm32f7/Kconfig | 42 +++++++++++++++++ arch/arm/src/stm32f7/stm32_spi.c | 80 ++++++++++++++++++++++++-------- 2 files changed, 102 insertions(+), 20 deletions(-) diff --git a/arch/arm/src/stm32f7/Kconfig b/arch/arm/src/stm32f7/Kconfig index 5611efec40..4b72417698 100644 --- a/arch/arm/src/stm32f7/Kconfig +++ b/arch/arm/src/stm32f7/Kconfig @@ -1969,6 +1969,48 @@ config STM32F7_SPI_DMA default n ---help--- Use DMA to improve SPI transfer performance. Cannot be used with STM32F7_SPI_INTERRUPT. + +config STM32F7_SPI1_DMA + bool "SPI1 DMA" + default n + depends on STM32F7_SPI1 && STM32F7_SPI_DMA + ---help--- + Use DMA to improve SPI1 transfer performance. + +config STM32F7_SPI2_DMA + bool "SPI2 DMA" + default n + depends on STM32F7_SPI2 && STM32F7_SPI_DMA + ---help--- + Use DMA to improve SPI2 transfer performance. + +config STM32F7_SPI3_DMA + bool "SPI3 DMA" + default n + depends on STM32F7_SPI3 && STM32F7_SPI_DMA + ---help--- + Use DMA to improve SPI3 transfer performance. + +config STM32F7_SPI4_DMA + bool "SPI4 DMA" + default n + depends on STM32F7_SPI4 && STM32F7_SPI_DMA + ---help--- + Use DMA to improve SPI4 transfer performance. + +config STM32F7_SPI5_DMA + bool "SPI5 DMA" + default n + depends on STM32F7_SPI5 && STM32F7_SPI_DMA + ---help--- + Use DMA to improve SPI5 transfer performance. + +config STM32F7_SPI6_DMA + bool "SPI6 DMA" + default n + depends on STM32F7_SPI6 && STM32F7_SPI_DMA + ---help--- + Use DMA to improve SPI6 transfer performance. endmenu # "SPI Configuration" diff --git a/arch/arm/src/stm32f7/stm32_spi.c b/arch/arm/src/stm32f7/stm32_spi.c index e776309c57..ee0e5e4672 100644 --- a/arch/arm/src/stm32f7/stm32_spi.c +++ b/arch/arm/src/stm32f7/stm32_spi.c @@ -286,8 +286,13 @@ static struct stm32_spidev_s g_spi1dev = .spiirq = STM32_IRQ_SPI1, #endif #ifdef CONFIG_STM32F7_SPI_DMA +# ifdef CONFIG_STM32F7_SPI1_DMA .rxch = DMAMAP_SPI1_RX, .txch = DMAMAP_SPI1_TX, +# else + .rxch = 0, + .txch = 0, +# endif #endif #ifdef CONFIG_PM .pm_cb.prepare = spi_pm_prepare, @@ -336,8 +341,13 @@ static struct stm32_spidev_s g_spi2dev = .spiirq = STM32_IRQ_SPI2, #endif #ifdef CONFIG_STM32F7_SPI_DMA +# ifdef CONFIG_STM32F7_SPI2_DMA .rxch = DMAMAP_SPI2_RX, .txch = DMAMAP_SPI2_TX, +# else + .rxch = 0, + .txch = 0, +# endif #endif #ifdef CONFIG_PM .pm_cb.prepare = spi_pm_prepare, @@ -386,8 +396,13 @@ static struct stm32_spidev_s g_spi3dev = .spiirq = STM32_IRQ_SPI3, #endif #ifdef CONFIG_STM32F7_SPI_DMA +# ifdef CONFIG_STM32F7_SPI3_DMA .rxch = DMAMAP_SPI3_RX, .txch = DMAMAP_SPI3_TX, +# else + .rxch = 0, + .txch = 0, +# endif #endif #ifdef CONFIG_PM .pm_cb.prepare = spi_pm_prepare, @@ -436,8 +451,13 @@ static struct stm32_spidev_s g_spi4dev = .spiirq = STM32_IRQ_SPI4, #endif #ifdef CONFIG_STM32F7_SPI_DMA +# ifdef CONFIG_STM32F7_SPI4_DMA .rxch = DMAMAP_SPI4_RX, .txch = DMAMAP_SPI4_TX, +# else + .rxch = 0, + .txch = 0, +# endif #endif #ifdef CONFIG_PM .pm_cb.prepare = spi_pm_prepare, @@ -486,8 +506,13 @@ static struct stm32_spidev_s g_spi5dev = .spiirq = STM32_IRQ_SPI5, #endif #ifdef CONFIG_STM32F7_SPI_DMA +# ifdef CONFIG_STM32F7_SPI5_DMA .rxch = DMAMAP_SPI5_RX, .txch = DMAMAP_SPI5_TX, +# else + .rxch = 0, + .txch = 0, +# endif #endif #ifdef CONFIG_PM .pm_cb.prepare = spi_pm_prepare, @@ -508,7 +533,7 @@ static const struct spi_ops_s g_sp6iops = #endif .status = stm32_spi6status, #ifdef CONFIG_SPI_CMDDATA - .cmddata = stm32_spi3cmddata, + .cmddata = stm32_spi6cmddata, #endif .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE @@ -536,8 +561,13 @@ static struct stm32_spidev_s g_spi6dev = .spiirq = STM32_IRQ_SPI6, #endif #ifdef CONFIG_STM32F7_SPI_DMA +# ifdef CONFIG_STM32F7_SPI6_DMA .rxch = DMAMAP_SPI6_RX, .txch = DMAMAP_SPI6_TX, +# else + .rxch = 0, + .txch = 0, +# endif #endif #ifdef CONFIG_PM .pm_cb.prepare = spi_pm_prepare, @@ -1648,10 +1678,12 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, DEBUGASSERT(priv != NULL); #ifdef CONFIG_STM32F7_DMACAPABLE - if ((txbuffer && !stm32_dmacapable((uint32_t)txbuffer, nwords, priv->txccr)) || - (rxbuffer && !stm32_dmacapable((uint32_t)rxbuffer, nwords, priv->rxccr))) + if ((priv->rxdma == NULL) || (priv->txdma == NULL) || + (txbuffer && !stm32_dmacapable((uint32_t)txbuffer, nwords, priv->txccr)) || + (rxbuffer && !stm32_dmacapable((uint32_t)rxbuffer, nwords, priv->rxccr)) || + up_interrupt_context()) { - /* Unsupported memory region, fall back to non-DMA method. */ + /* Invalid DMA channels, unsupported memory region, or interrupt context, fall back to non-DMA method. */ spi_exchange_nodma(dev, txbuffer, rxbuffer, nwords); } @@ -1959,28 +1991,36 @@ static void spi_bus_initialize(struct stm32_spidev_s *priv) * priority inheritance enabled. */ - nxsem_init(&priv->rxsem, 0, 0); - nxsem_init(&priv->txsem, 0, 0); + if (priv->rxch && priv->txch) + { + nxsem_init(&priv->rxsem, 0, 0); + nxsem_init(&priv->txsem, 0, 0); - nxsem_setprotocol(&priv->rxsem, SEM_PRIO_NONE); - nxsem_setprotocol(&priv->txsem, SEM_PRIO_NONE); + nxsem_setprotocol(&priv->rxsem, SEM_PRIO_NONE); + nxsem_setprotocol(&priv->txsem, SEM_PRIO_NONE); - /* Get DMA channels. NOTE: stm32_dmachannel() will always assign the DMA channel. - * if the channel is not available, then stm32_dmachannel() will block and wait - * until the channel becomes available. WARNING: If you have another device sharing - * a DMA channel with SPI and the code never releases that channel, then the call - * to stm32_dmachannel() will hang forever in this function! Don't let your - * design do that! - */ + /* Get DMA channels. NOTE: stm32_dmachannel() will always assign the DMA + * channel. If the channel is not available, then stm32_dmachannel() will + * block and wait until the channel becomes available. WARNING: If you have + * another device sharing a DMA channel with SPI and the code never releases + * that channel, then the call to stm32_dmachannel() will hang forever in + * this function! Don't let your design do that! + */ - priv->rxdma = stm32_dmachannel(priv->rxch); - priv->txdma = stm32_dmachannel(priv->txch); - DEBUGASSERT(priv->rxdma && priv->txdma); + priv->rxdma = stm32_dmachannel(priv->rxch); + priv->txdma = stm32_dmachannel(priv->txch); + DEBUGASSERT(priv->rxdma && priv->txdma); - spi_modifycr2(priv, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN, 0); + spi_modifycr2(priv, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN, 0); + } + else + { + priv->rxdma = NULL; + priv->txdma = NULL; + } #endif - /* Enable spi */ + /* Enable SPI */ spi_modifycr1(priv, SPI_CR1_SPE, 0);