Merged in dagar/nuttx/pr-stm32f7_SPI_DMA_per_bus (pull request #798)

stm32f7 enable separate DMA per SPI configuration

Approved-by: GregoryN <gnutt@nuttx.org>
This commit is contained in:
Daniel Agar 2019-01-02 18:50:40 +00:00 committed by GregoryN
parent a0a537a9f0
commit 3b55f35bb3
2 changed files with 102 additions and 20 deletions

View File

@ -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"

View File

@ -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);