Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: STM32F7 DMA per SPI #25

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions arch/arm/src/stm32f7/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,72 @@ config STM32F7_SPI_DMA
default n
---help---
Use DMA to improve SPI transfer performance. Cannot be used with STM32F7_SPI_INTERRUPT.

if STM32F7_SPI1

config STM32F7_SPI1_DMA
bool "SPI1 DMA"
default n
depends on STM32F7_SPI_DMA
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add the same chaed Greg did upstream

---help---
Use DMA to improve SPI1 transfer performance.

endif # STM32F7_SPI1

if STM32F7_SPI2

config STM32F7_SPI2_DMA
bool "SPI2 DMA"
default n
depends on STM32F7_SPI_DMA
---help---
Use DMA to improve SPI2 transfer performance.

endif # STM32F7_SPI2

if STM32F7_SPI3

config STM32F7_SPI3_DMA
bool "SPI3 DMA"
default n
depends on STM32F7_SPI_DMA
---help---
Use DMA to improve SPI3 transfer performance.

endif # STM32F7_SPI2

if STM32F7_SPI4

config STM32F7_SPI4_DMA
bool "SPI4 DMA"
default n
depends on STM32F7_SPI_DMA
---help---
Use DMA to improve SPI4 transfer performance.

endif # STM32F7_SPI4

if STM32F7_SPI5

config STM32F7_SPI5_DMA
bool "SPI5 DMA"
default n
depends on STM32F7_SPI_DMA
---help---
Use DMA to improve SPI5 transfer performance.

endif # STM32F7_SPI5

if STM32F7_SPI6

config STM32F7_SPI6_DMA
bool "SPI6 DMA"
default n
depends on STM32F7_SPI_DMA
---help---
Use DMA to improve SPI6 transfer performance.

endif # STM32F7_SPI6

endmenu # "SPI Configuration"

Expand Down
81 changes: 61 additions & 20 deletions arch/arm/src/stm32f7/stm32_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,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
};
#endif
Expand Down Expand Up @@ -307,8 +312,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
};
#endif
Expand Down Expand Up @@ -351,8 +361,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
};
#endif
Expand Down Expand Up @@ -395,8 +410,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
};
#endif
Expand Down Expand Up @@ -439,8 +459,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
};
#endif
Expand All @@ -458,7 +483,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
Expand All @@ -483,8 +508,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
};
#endif
Expand Down Expand Up @@ -1530,10 +1560,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);
}
Expand Down Expand Up @@ -1704,25 +1736,34 @@ 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);

sem_setprotocol(&priv->rxsem, SEM_PRIO_NONE);
sem_setprotocol(&priv->txsem, SEM_PRIO_NONE);
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);

/* 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 */
Expand Down