From bca890df5f0780d243edc8535f3cdd53edd5ae1e Mon Sep 17 00:00:00 2001 From: Daniel Agar Date: Mon, 9 Jul 2018 17:59:35 -0400 Subject: [PATCH] WIP: STM32 DMA per SPI --- arch/arm/src/stm32/Kconfig | 42 +++++++++++++++++++++++ arch/arm/src/stm32/stm32_spi.c | 63 ++++++++++++++++++++++++++++------ 2 files changed, 94 insertions(+), 11 deletions(-) diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index 942bf92260f..427bc96ead0 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -6381,6 +6381,48 @@ config STM32_SPI_DMA ---help--- Use DMA to improve SPI transfer performance. Cannot be used with STM32_SPI_INTERRUPT. +config STM32_SPI1_DMA + bool "SPI1 DMA" + default n + depends on STM32_SPI_DMA && STM32_HAVE_SPI1 + ---help--- + Use DMA to improve SPI1 transfer performance. + +config STM32_SPI2_DMA + bool "SPI2 DMA" + default n + depends on STM32_SPI_DMA && STM32_HAVE_SPI2 + ---help--- + Use DMA to improve SPI2 transfer performance. + +config STM32_SPI3_DMA + bool "SPI3 DMA" + default n + depends on STM32_SPI_DMA && STM32_HAVE_SPI3 + ---help--- + Use DMA to improve SPI3 transfer performance. + +config STM32_SPI4_DMA + bool "SPI4 DMA" + default n + depends on STM32_SPI_DMA && STM32_HAVE_SPI4 + ---help--- + Use DMA to improve SPI4 transfer performance. + +config STM32_SPI5_DMA + bool "SPI5 DMA" + default n + depends on STM32_SPI_DMA && STM32_HAVE_SPI5 + ---help--- + Use DMA to improve SPI5 transfer performance. + +config STM32_SPI6_DMA + bool "SPI6 DMA" + default n + depends on STM32_SPI_DMA && STM32_HAVE_SPI6 + ---help--- + Use DMA to improve SPI6 transfer performance. + endmenu menu "I2S Configuration" diff --git a/arch/arm/src/stm32/stm32_spi.c b/arch/arm/src/stm32/stm32_spi.c index 89859f67635..a17e87b30a7 100644 --- a/arch/arm/src/stm32/stm32_spi.c +++ b/arch/arm/src/stm32/stm32_spi.c @@ -290,8 +290,13 @@ static struct stm32_spidev_s g_spi1dev = .spiirq = STM32_IRQ_SPI1, #endif #ifdef CONFIG_STM32_SPI_DMA +#ifdef CONFIG_STM32_SPI1_DMA .rxch = DMACHAN_SPI1_RX, .txch = DMACHAN_SPI1_TX, +#else + .rxch = 0, + .txch = 0, +#endif #endif }; #endif @@ -334,8 +339,13 @@ static struct stm32_spidev_s g_spi2dev = .spiirq = STM32_IRQ_SPI2, #endif #ifdef CONFIG_STM32_SPI_DMA +#ifdef CONFIG_STM32_SPI2_DMA .rxch = DMACHAN_SPI2_RX, .txch = DMACHAN_SPI2_TX, +#else + .rxch = 0, + .txch = 0, +#endif #endif }; #endif @@ -378,8 +388,13 @@ static struct stm32_spidev_s g_spi3dev = .spiirq = STM32_IRQ_SPI3, #endif #ifdef CONFIG_STM32_SPI_DMA +#ifdef CONFIG_STM32_SPI3_DMA .rxch = DMACHAN_SPI3_RX, .txch = DMACHAN_SPI3_TX, +#else + .rxch = 0, + .txch = 0, +#endif #endif }; #endif @@ -422,8 +437,13 @@ static struct stm32_spidev_s g_spi4dev = .spiirq = STM32_IRQ_SPI4, #endif #ifdef CONFIG_STM32_SPI_DMA +#ifdef CONFIG_STM32_SPI4_DMA .rxch = DMACHAN_SPI4_RX, .txch = DMACHAN_SPI4_TX, +#else + .rxch = 0, + .txch = 0, +#endif #endif }; #endif @@ -466,8 +486,13 @@ static struct stm32_spidev_s g_spi5dev = .spiirq = STM32_IRQ_SPI5, #endif #ifdef CONFIG_STM32_SPI_DMA +#ifdef CONFIG_STM32_SPI5_DMA .rxch = DMACHAN_SPI5_RX, .txch = DMACHAN_SPI5_TX, +#else + .rxch = 0, + .txch = 0, +#endif #endif }; #endif @@ -510,8 +535,13 @@ static struct stm32_spidev_s g_spi6dev = .spiirq = STM32_IRQ_SPI6, #endif #ifdef CONFIG_STM32_SPI_DMA +#ifdef CONFIG_STM32_SPI6_DMA .rxch = DMACHAN_SPI6_RX, .txch = DMACHAN_SPI6_TX, +#else + .rxch = 0, + .txch = 0, +#endif #endif }; #endif @@ -1567,10 +1597,12 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; #ifdef CONFIG_STM32_DMACAPABLE - if ((txbuffer && !stm32_dmacapable((uint32_t)txbuffer, nwords, priv->txccr)) || - (rxbuffer && !stm32_dmacapable((uint32_t)rxbuffer, nwords, priv->rxccr))) + if (!(priv->rxch && priv->txch) || + (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); } @@ -1730,11 +1762,12 @@ static void spi_bus_initialize(FAR struct stm32_spidev_s *priv) * priority inheritance enabled. */ - sem_init(&priv->rxsem, 0, 0); - sem_init(&priv->txsem, 0, 0); + if (priv->rxch && priv->txch) { + sem_init(&priv->rxsem, 0, 0); + sem_init(&priv->txsem, 0, 0); - sem_setprotocol(&priv->rxsem, SEM_PRIO_NONE); - sem_setprotocol(&priv->txsem, SEM_PRIO_NONE); + sem_setprotocol(&priv->rxsem, SEM_PRIO_NONE); + sem_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 @@ -1744,11 +1777,19 @@ static void spi_bus_initialize(FAR struct stm32_spidev_s *priv) * 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); + + } else { + priv->rxsem = NULL; + priv->txsem = NULL; - spi_modifycr2(priv, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN, 0); + priv->rxdma = NULL; + priv->txdma = NULL; + } #endif /* Enable spi */