From 00084d9620ac00140965e647b8c4d75c7d4bbc7d Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 1 Oct 2010 03:28:41 +0000 Subject: Make better use of these deep FIFOs git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2958 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/arch/arm/src/lpc313x/lpc313x_spi.c | 99 +++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 34 deletions(-) (limited to 'nuttx/arch/arm/src/lpc313x') diff --git a/nuttx/arch/arm/src/lpc313x/lpc313x_spi.c b/nuttx/arch/arm/src/lpc313x/lpc313x_spi.c index ed7300a5b..a089c5543 100644 --- a/nuttx/arch/arm/src/lpc313x/lpc313x_spi.c +++ b/nuttx/arch/arm/src/lpc313x/lpc313x_spi.c @@ -72,6 +72,10 @@ # undef CONFIG_DEBUG_SPIREGS #endif +/* FIFOs ****************************************************************************/ + +#define SPI_FIFO_DEPTH 64 /* 64 words deep (8- or 16-bit words) */ + /* Timing ***************************************************************************/ #define SPI_MAX_DIVIDER 65024 /* = 254 * (255 + 1) */ @@ -118,7 +122,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequenc static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setbits(FAR struct spi_dev_s *dev, int nbits); static uint8_t spi_status(FAR struct spi_dev_s *dev, enum spi_dev_e devid); -static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); +static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t word); static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords); #ifndef CONFIG_SPI_EXCHANGE @@ -376,16 +380,13 @@ static inline void spi_select_slave(FAR struct lpc313x_spidev_s *priv, uint8_t s static inline uint16_t spi_readword(FAR struct lpc313x_spidev_s *priv) { - /* Wait until the receive buffer is not empty */ + /* Wait until the RX FIFO is not empty */ - while ((spi_getreg(LPC313X_SPI_STATUS) & SPI_STATUS_RXFIFOEMPTY) != 0) - ; + while ((spi_getreg(LPC313X_SPI_STATUS) & SPI_STATUS_RXFIFOEMPTY) != 0); /* Then return the received word */ - uint32_t val = spi_getreg(LPC313X_SPI_FIFODATA); - - return val; + return (uint16_t)spi_getreg(LPC313X_SPI_FIFODATA); } /************************************************************************************ @@ -405,10 +406,9 @@ static inline uint16_t spi_readword(FAR struct lpc313x_spidev_s *priv) static inline void spi_writeword(FAR struct lpc313x_spidev_s *priv, uint16_t word) { - /* Wait until the transmit buffer is not full */ + /* Wait until the TX FIFO is not full */ - while ((spi_getreg(LPC313X_SPI_STATUS) & SPI_STATUS_TXFIFOFULL) != 0) - ; + while ((spi_getreg(LPC313X_SPI_STATUS) & SPI_STATUS_TXFIFOFULL) != 0); /* Then send the word */ @@ -701,21 +701,21 @@ static uint8_t spi_status(FAR struct spi_dev_s *dev, enum spi_dev_e devid) * Exchange one word on SPI * * Input Parameters: - * dev - Device-specific state data - * wd - The word to send. the size of the data is determined by the - * number of bits selected for the SPI interface. + * dev - Device-specific state data + * word - The word to send. the size of the data is determined by the + * number of bits selected for the SPI interface. * * Returned Value: * response * ************************************************************************************/ -static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) +static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t word) { FAR struct lpc313x_spidev_s *priv = (FAR struct lpc313x_spidev_s *)dev; DEBUGASSERT(priv); - spi_writeword(priv, wd); + spi_writeword(priv, word); return spi_readword(priv); } @@ -743,6 +743,9 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords) { FAR struct lpc313x_spidev_s *priv = (FAR struct lpc313x_spidev_s *)dev; + unsigned int maxtx; + unsigned int ntx; + DEBUGASSERT(priv); /* 8- or 16-bit mode? */ @@ -755,21 +758,35 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, uint16_t *dest = (uint16_t*)rxbuffer; uint16_t word; - while (nwords-- > 0) + while (nwords > 0) { - /* Get the next word to write. Is there a source buffer? */ + /* Fill up the TX FIFO */ - word = src ? *src++ : 0xffff; + maxtx = nwords > SPI_FIFO_DEPTH ? SPI_FIFO_DEPTH : nwords; + for (ntx = 0; ntx < maxtx; ntx++) + { + /* Get the next word to write. Is there a source buffer? */ - /* Exchange one word */ - - word = spi_send(dev, word); + word = src ? *src++ : 0xffff; + + /* Then send the word */ + + spi_writeword(priv, word); + } + nwords -= maxtx; - /* Is there a buffer to receive the return value? */ + /* Then empty the RX FIFO */ - if (dest) + while (ntx-- > 0) { - *dest++ = word; + word = spi_readword(priv); + + /* Is there a buffer to receive the return value? */ + + if (dest) + { + *dest++ = word; + } } } } @@ -781,22 +798,36 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, uint8_t *dest = (uint8_t*)rxbuffer; uint8_t word; - while (nwords-- > 0) + while (nwords > 0) { - /* Get the next word to write. Is there a source buffer? */ + /* Fill up the TX FIFO */ - word = src ? *src++ : 0xff; + maxtx = nwords > SPI_FIFO_DEPTH ? SPI_FIFO_DEPTH : nwords; + for (ntx = 0; ntx < maxtx; ntx++) + { + /* Get the next word to write. Is there a source buffer? */ - /* Exchange one word */ - - word = (uint8_t)spi_send(dev, (uint16_t)word); + word = src ? *src++ : 0xff; + + /* Then send the word */ - /* Is there a buffer to receive the return value? */ + spi_writeword(priv, (uint16_t)word); + } + nwords -= maxtx; + + /* Then empty the RX FIFO */ - if (dest) + while (ntx-- > 0) { - *dest++ = word; - } + word = (uint8_t)spi_readword(priv); + + /* Is there a buffer to receive the return value? */ + + if (dest) + { + *dest++ = word; + } + } } } } -- cgit v1.2.3