summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-10-26 13:13:53 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-10-26 13:13:53 -0600
commit786fd6702d47d1952ff945849dc4affba284d8bc (patch)
tree17985f19a2357ebf3ac8fcd0d0e4a06b2f355dc4
parent646d46818bcbc370aa94296e7dd6520047f37db4 (diff)
downloadnuttx-786fd6702d47d1952ff945849dc4affba284d8bc.tar.gz
nuttx-786fd6702d47d1952ff945849dc4affba284d8bc.tar.bz2
nuttx-786fd6702d47d1952ff945849dc4affba284d8bc.zip
EFM32 SPI: Add check to make sure that the SPI RX buffer is empty before starting a transfer
-rw-r--r--nuttx/arch/arm/src/efm32/efm32_spi.c51
1 files 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 */
@@ -415,6 +418,40 @@ static bool spi_16bitmode(struct efm32_spidev_s *priv)
}
/****************************************************************************
+ * 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
*
* Description:
@@ -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? */