Skip to content

Commit

Permalink
WIP: STM32 DMA per SPI
Browse files Browse the repository at this point in the history
  • Loading branch information
dagar committed Jul 9, 2018
1 parent d5c12b2 commit bca890d
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 11 deletions.
42 changes: 42 additions & 0 deletions arch/arm/src/stm32/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
63 changes: 52 additions & 11 deletions arch/arm/src/stm32/stm32_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand All @@ -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 */
Expand Down

0 comments on commit bca890d

Please sign in to comment.