From 786fd6702d47d1952ff945849dc4affba284d8bc Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 26 Oct 2014 13:13:53 -0600 Subject: EFM32 SPI: Add check to make sure that the SPI RX buffer is empty before starting a transfer --- nuttx/arch/arm/src/efm32/efm32_spi.c | 51 +++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/nuttx/arch/arm/src/efm32/efm32_spi.c b/nuttx/arch/arm/src/efm32/efm32_spi.c index b94530fbc..6b631c904 100644 --- a/nuttx/arch/arm/src/efm32/efm32_spi.c +++ b/nuttx/arch/arm/src/efm32/efm32_spi.c @@ -183,6 +183,9 @@ static uint32_t spi_getreg(const struct efm32_spiconfig_s *config, static void spi_putreg(const struct efm32_spiconfig_s *config, unsigned int regoffset, uint32_t regval); static bool spi_16bitmode(struct efm32_spidev_s *priv); +static void spi_rxflush(const struct efm32_spiconfig_s *config); +static void spi_wait_status(const struct efm32_spiconfig_s *config, + uint32_t mask, uint32_t match); /* DMA support */ @@ -414,6 +417,40 @@ static bool spi_16bitmode(struct efm32_spidev_s *priv) #endif } +/**************************************************************************** + * Name: spi_rxflush + * + * Description: + * Flush any garbage from the RX buffer + * + ****************************************************************************/ + +static void spi_rxflush(const struct efm32_spiconfig_s *config) +{ + /* Loop while data is available */ + + while ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_RXDATAV) != 0) + { + /* Read and discard the data */ + + (void)spi_getreg(config, EFM32_USART_RXDATA_OFFSET); + } +} + +/**************************************************************************** + * Name: spi_wait_status + * + * Description: + * Poll until the SPI status under the mask is equal to the mask value. + * + ****************************************************************************/ + +static void spi_wait_status(const struct efm32_spiconfig_s *config, + uint32_t mask, uint32_t match) +{ + while ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & mask) != match); +} + /**************************************************************************** * Name: spi_dma_timeout * @@ -1191,7 +1228,11 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) /* Wait until there is space in the TX buffer */ - while ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_TXBL) == 0); + spi_wait_status(config, _USART_STATUS_TXBL_MASK, USART_STATUS_TXBL); + + /* Flush any unread data */ + + spi_rxflush(config); /* Write the data */ @@ -1199,7 +1240,7 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) /* Wait for receive data to be available */ - while ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_RXDATAV) == 0); + spi_wait_status(config, _USART_STATUS_RXDATAV_MASK, USART_STATUS_RXDATAV); ret = (uint16_t)spi_getreg(config, EFM32_USART_RXDATA_OFFSET); spivdbg("Sent: %04x Return: %04x \n", wd, ret); @@ -1245,6 +1286,10 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, spivdbg("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords); + /* Flush any unread data */ + + spi_rxflush(config); + /* 8- or 16-bit mode? */ if (spi_16bitmode(priv)) @@ -1316,7 +1361,7 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, /* REVISIT: Could this cause RX data overruns??? */ /* Send data if there is space in the TX buffer. */ - while ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_TXBL) != 0 && + if ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_TXBL) != 0 && unsent > 0) { /* Get the next word to write. Is there a source buffer? */ -- cgit v1.2.3