stm32h7:Fix DMA Overrun error
This commit is contained in:
parent
c191787ba4
commit
fc3ab3e085
@ -1451,16 +1451,6 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
|
||||
|
||||
spi_modifyreg(priv, STM32_SPI_CFG2_OFFSET, clrbits, setbits);
|
||||
|
||||
#ifdef CONFIG_STM32H7_SPI_DMA
|
||||
/* Enabling SPI causes a spurious received character indication
|
||||
* which confuse the DMA controller so we disable DMA during that
|
||||
* enabling; and flush the SPI RX FIFO before re-enabling DMA.
|
||||
*/
|
||||
|
||||
spi_modifyreg(priv, STM32_SPI_CFG1_OFFSET, SPI_CFG1_RXDMAEN |
|
||||
SPI_CFG1_TXDMAEN, 0);
|
||||
#endif
|
||||
|
||||
/* Re-enable SPI */
|
||||
|
||||
spi_enable(priv, true);
|
||||
@ -1469,19 +1459,9 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
|
||||
{
|
||||
/* Flush SPI read FIFO */
|
||||
|
||||
spi_getreg(priv, STM32_SPI_TXDR_OFFSET);
|
||||
spi_getreg(priv, STM32_SPI_RXDR_OFFSET);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STM32H7_SPI_DMA
|
||||
|
||||
/* Re-enable DMA (with SPI disabled) */
|
||||
|
||||
spi_enable(priv, false);
|
||||
spi_modifyreg(priv, STM32_SPI_CFG1_OFFSET, 0, SPI_CFG1_RXDMAEN |
|
||||
SPI_CFG1_TXDMAEN);
|
||||
spi_enable(priv, true);
|
||||
#endif
|
||||
|
||||
/* Save the mode so that subsequent re-configurations will be faster */
|
||||
|
||||
priv->mode = mode;
|
||||
@ -1913,6 +1893,22 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
|
||||
static uint8_t rxdummy[4] __attribute__((aligned(4)));
|
||||
static const uint16_t txdummy = 0xffff;
|
||||
|
||||
/* When starting communication using DMA, to prevent DMA channel
|
||||
* management raising error events, these steps must be followed in
|
||||
* order:
|
||||
* 1. Enable DMA Rx buffer in the RXDMAEN bit in the SPI_CFG1 register,
|
||||
* if DMA Rx is used.
|
||||
* 2. Enable DMA requests for Tx and Rx in DMA registers, if the DMA is
|
||||
* used.
|
||||
* 3. Enable DMA Tx buffer in the TXDMAEN bit in the SPI_CFG1 register,
|
||||
* if DMA Tx is used.
|
||||
* 4. Enable the SPI by setting the SPE bit.
|
||||
*/
|
||||
|
||||
spi_enable(priv, false);
|
||||
spi_modifyreg(priv, STM32_SPI_CFG1_OFFSET, SPI_CFG1_TXDMAEN,
|
||||
SPI_CFG1_RXDMAEN);
|
||||
|
||||
spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n",
|
||||
txbuffer, rxbuffer, nwords);
|
||||
DEBUGASSERT(priv->spibase != 0);
|
||||
@ -1920,6 +1916,9 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
|
||||
spi_dmarxsetup(priv, rxbuffer, (uint16_t *)rxdummy, nbytes);
|
||||
spi_dmatxsetup(priv, txbuffer, &txdummy, nbytes);
|
||||
|
||||
spi_modifyreg(priv, STM32_SPI_CFG1_OFFSET, 0, SPI_CFG1_TXDMAEN |
|
||||
SPI_CFG1_RXDMAEN);
|
||||
|
||||
/* Flush cache to physical memory */
|
||||
|
||||
if (txbuffer)
|
||||
@ -1927,19 +1926,17 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
|
||||
up_flush_dcache((uintptr_t)txbuffer, (uintptr_t)txbuffer + nbytes);
|
||||
}
|
||||
|
||||
/* REVISIT: Master transfer start */
|
||||
|
||||
spi_modifyreg(priv, STM32_SPI_CR1_OFFSET, 0, SPI_CR1_CSTART);
|
||||
|
||||
#ifdef CONFIG_SPI_TRIGGER
|
||||
/* Is deferred triggering in effect? */
|
||||
|
||||
if (!priv->defertrig)
|
||||
{
|
||||
/* No.. Start the DMAs */
|
||||
/* No.. Start the DMAs then the SPI */
|
||||
|
||||
spi_dmarxstart(priv);
|
||||
spi_dmatxstart(priv);
|
||||
spi_enable(priv, true);
|
||||
spi_modifyreg(priv, STM32_SPI_CR1_OFFSET, 0, SPI_CR1_CSTART);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1948,20 +1945,32 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
|
||||
priv->trigarmed = true;
|
||||
}
|
||||
#else
|
||||
/* Start the DMAs */
|
||||
/* Start the DMAs then the SPI */
|
||||
|
||||
spi_dmarxstart(priv);
|
||||
spi_dmatxstart(priv);
|
||||
spi_enable(priv, true);
|
||||
spi_modifyreg(priv, STM32_SPI_CR1_OFFSET, 0, SPI_CR1_CSTART);
|
||||
#endif
|
||||
|
||||
/* Then wait for each to complete */
|
||||
|
||||
ret = spi_dmarxwait(priv);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = spi_dmatxwait(priv);
|
||||
UNUSED(ret);
|
||||
}
|
||||
spi_dmarxwait(priv);
|
||||
spi_dmatxwait(priv);
|
||||
|
||||
/* To close communication it is mandatory to follow these steps in
|
||||
* order:
|
||||
* 1. Disable DMA request for Tx and Rx in the DMA registers, if the
|
||||
* DMA issued.
|
||||
* 2. Disable the SPI by following the SPI disable procedure.
|
||||
* 3. Disable DMA Tx and Rx buffers by clearing the TXDMAEN and RXDMAEN
|
||||
* bits in the SPI_CFG1 register, if DMA Tx and/or DMA Rx are used.
|
||||
*/
|
||||
|
||||
spi_enable(priv, false);
|
||||
spi_modifyreg(priv, STM32_SPI_CFG1_OFFSET, SPI_CFG1_TXDMAEN |
|
||||
SPI_CFG1_RXDMAEN, 0);
|
||||
spi_enable(priv, true);
|
||||
|
||||
#ifdef CONFIG_SPI_TRIGGER
|
||||
priv->trigarmed = false;
|
||||
@ -2012,7 +2021,8 @@ static int spi_trigger(FAR struct spi_dev_s *dev)
|
||||
|
||||
spi_dmarxstart(priv);
|
||||
spi_dmatxstart(priv);
|
||||
|
||||
spi_enable(priv, true);
|
||||
spi_modifyreg(priv, STM32_SPI_CR1_OFFSET, 0, SPI_CR1_CSTART);
|
||||
return OK;
|
||||
#else
|
||||
return -ENOSYS;
|
||||
|
Loading…
Reference in New Issue
Block a user