This is an automated email from the ASF dual-hosted git repository. gustavonihei pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit f702c89c3393bd7f19f51234121c944706102135 Author: raiden00pl <raide...@railab.me> AuthorDate: Thu Jul 14 16:10:30 2022 +0200 stm32f0l0g0/SPI: configure DMA support individually for each SPI --- arch/arm/src/stm32f0l0g0/Kconfig | 14 ++++++++ arch/arm/src/stm32f0l0g0/stm32_spi.c | 66 ++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/arch/arm/src/stm32f0l0g0/Kconfig b/arch/arm/src/stm32f0l0g0/Kconfig index 7be4333525..de4c965fb4 100644 --- a/arch/arm/src/stm32f0l0g0/Kconfig +++ b/arch/arm/src/stm32f0l0g0/Kconfig @@ -1272,6 +1272,20 @@ config STM32F0L0G0_SPI2 select SPI select STM32F0L0G0_SPI +config STM32F0L0G0_SPI1_DMA + bool "SPI1 DMA" + default n + depends on STM32F0L0G0_SPI1 && STM32F0L0G0_SPI_DMA + ---help--- + Use DMA to improve SPI1 transfer performance. + +config STM32F0L0G0_SPI2_DMA + bool "SPI2 DMA" + default n + depends on STM32F0L0G0_SPI2 && STM32F0L0G0_SPI_DMA + ---help--- + Use DMA to improve SPI2 transfer performance. + config STM32F0L0G0_SYSCFG bool "SYSCFG" default y diff --git a/arch/arm/src/stm32f0l0g0/stm32_spi.c b/arch/arm/src/stm32f0l0g0/stm32_spi.c index fad7343fa8..a8a7542e37 100644 --- a/arch/arm/src/stm32f0l0g0/stm32_spi.c +++ b/arch/arm/src/stm32f0l0g0/stm32_spi.c @@ -285,7 +285,7 @@ static struct stm32_spidev_s g_spi1dev = #ifdef CONFIG_STM32F0L0G0_SPI_INTERRUPTS .spiirq = STM32_IRQ_SPI1, #endif -#ifdef CONFIG_STM32F0L0G0_SPI_DMA +#ifdef CONFIG_STM32F0L0G0_SPI1_DMA /* lines must be configured in board.h */ .rxch = DMACHAN_SPI1_RX, @@ -340,7 +340,7 @@ static struct stm32_spidev_s g_spi2dev = #ifdef CONFIG_STM32F0L0G0_SPI_INTERRUPTS .spiirq = STM32_IRQ_SPI2, #endif -#ifdef CONFIG_STM32F0L0G0_SPI_DMA +#ifdef CONFIG_STM32F0L0G0_SPI2_DMA .rxch = DMACHAN_SPI2_RX, .txch = DMACHAN_SPI2_TX, #endif @@ -1407,6 +1407,17 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, { struct stm32_spidev_s *priv = (struct stm32_spidev_s *)dev; + if ((priv->rxdma == NULL) || (priv->txdma == NULL) || + up_interrupt_context()) + { + /* Invalid DMA channels, or interrupt context, fall + * back to non-DMA method. + */ + + spi_exchange_nodma(dev, txbuffer, rxbuffer, nwords); + return; + } + #ifdef CONFIG_STM32F0L0G0_DMACAPABLE if ((txbuffer && !stm32_dmacapable((uintptr_t)txbuffer, nwords, priv->txccr)) || @@ -1724,32 +1735,43 @@ static void spi_bus_initialize(struct stm32_spidev_s *priv) nxsem_init(&priv->exclsem, 0, 1); #ifdef CONFIG_STM32F0L0G0_SPI_DMA - /* Initialize the SPI semaphores that is used to wait for DMA completion */ + if (priv->rxch && priv->txch) + { + /* Initialize the SPI semaphores that is used to wait for DMA + * completion + */ - nxsem_init(&priv->rxsem, 0, 0); - nxsem_init(&priv->txsem, 0, 0); + nxsem_init(&priv->rxsem, 0, 0); + nxsem_init(&priv->txsem, 0, 0); - /* These semaphores are used for signaling and, hence, should not have - * priority inheritance enabled. - */ + /* These semaphores are used for signaling and, hence, should not have + * priority inheritance enabled. + */ - nxsem_set_protocol(&priv->rxsem, SEM_PRIO_NONE); - nxsem_set_protocol(&priv->txsem, SEM_PRIO_NONE); + nxsem_set_protocol(&priv->rxsem, SEM_PRIO_NONE); + nxsem_set_protocol(&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_modifycr(STM32_SPI_CR2_OFFSET, priv, - SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN, 0); + spi_modifycr(STM32_SPI_CR2_OFFSET, priv, + SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN, 0); + } + else + { + priv->rxdma = NULL; + priv->txdma = NULL; + } #endif /* Enable spi */