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);
|
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 */
|
/* Re-enable SPI */
|
||||||
|
|
||||||
spi_enable(priv, true);
|
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 */
|
/* 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 */
|
/* Save the mode so that subsequent re-configurations will be faster */
|
||||||
|
|
||||||
priv->mode = mode;
|
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 uint8_t rxdummy[4] __attribute__((aligned(4)));
|
||||||
static const uint16_t txdummy = 0xffff;
|
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",
|
spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n",
|
||||||
txbuffer, rxbuffer, nwords);
|
txbuffer, rxbuffer, nwords);
|
||||||
DEBUGASSERT(priv->spibase != 0);
|
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_dmarxsetup(priv, rxbuffer, (uint16_t *)rxdummy, nbytes);
|
||||||
spi_dmatxsetup(priv, txbuffer, &txdummy, 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 */
|
/* Flush cache to physical memory */
|
||||||
|
|
||||||
if (txbuffer)
|
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);
|
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
|
#ifdef CONFIG_SPI_TRIGGER
|
||||||
/* Is deferred triggering in effect? */
|
/* Is deferred triggering in effect? */
|
||||||
|
|
||||||
if (!priv->defertrig)
|
if (!priv->defertrig)
|
||||||
{
|
{
|
||||||
/* No.. Start the DMAs */
|
/* No.. Start the DMAs then the SPI */
|
||||||
|
|
||||||
spi_dmarxstart(priv);
|
spi_dmarxstart(priv);
|
||||||
spi_dmatxstart(priv);
|
spi_dmatxstart(priv);
|
||||||
|
spi_enable(priv, true);
|
||||||
|
spi_modifyreg(priv, STM32_SPI_CR1_OFFSET, 0, SPI_CR1_CSTART);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1948,20 +1945,32 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
|
|||||||
priv->trigarmed = true;
|
priv->trigarmed = true;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* Start the DMAs */
|
/* Start the DMAs then the SPI */
|
||||||
|
|
||||||
spi_dmarxstart(priv);
|
spi_dmarxstart(priv);
|
||||||
spi_dmatxstart(priv);
|
spi_dmatxstart(priv);
|
||||||
|
spi_enable(priv, true);
|
||||||
|
spi_modifyreg(priv, STM32_SPI_CR1_OFFSET, 0, SPI_CR1_CSTART);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Then wait for each to complete */
|
/* Then wait for each to complete */
|
||||||
|
|
||||||
ret = spi_dmarxwait(priv);
|
spi_dmarxwait(priv);
|
||||||
if (ret >= 0)
|
spi_dmatxwait(priv);
|
||||||
{
|
|
||||||
ret = spi_dmatxwait(priv);
|
/* To close communication it is mandatory to follow these steps in
|
||||||
UNUSED(ret);
|
* 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
|
#ifdef CONFIG_SPI_TRIGGER
|
||||||
priv->trigarmed = false;
|
priv->trigarmed = false;
|
||||||
@ -2012,7 +2021,8 @@ static int spi_trigger(FAR struct spi_dev_s *dev)
|
|||||||
|
|
||||||
spi_dmarxstart(priv);
|
spi_dmarxstart(priv);
|
||||||
spi_dmatxstart(priv);
|
spi_dmatxstart(priv);
|
||||||
|
spi_enable(priv, true);
|
||||||
|
spi_modifyreg(priv, STM32_SPI_CR1_OFFSET, 0, SPI_CR1_CSTART);
|
||||||
return OK;
|
return OK;
|
||||||
#else
|
#else
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user