summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-10-15 22:53:34 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-10-15 22:53:34 +0000
commitef08ec9fb8f731de7469b52a491677a23dd14b31 (patch)
tree85723ca51f63718e2865a8ecf73599649d1a7a5e
parentf5b780c8e6be1e08df0e48d011d8ebe9a82e97e0 (diff)
downloadnuttx-ef08ec9fb8f731de7469b52a491677a23dd14b31.tar.gz
nuttx-ef08ec9fb8f731de7469b52a491677a23dd14b31.tar.bz2
nuttx-ef08ec9fb8f731de7469b52a491677a23dd14b31.zip
Fix nasty race condition
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1050 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/configs/mcu123-lpc214x/src/up_spi.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/nuttx/configs/mcu123-lpc214x/src/up_spi.c b/nuttx/configs/mcu123-lpc214x/src/up_spi.c
index 67323eeb3..60ddf43a0 100644
--- a/nuttx/configs/mcu123-lpc214x/src/up_spi.c
+++ b/nuttx/configs/mcu123-lpc214x/src/up_spi.c
@@ -66,6 +66,7 @@
#include <nuttx/spi.h>
#include <arch/board/board.h>
+#include <nuttx/arch.h>
#include <nuttx/spi.h>
#include "up_internal.h"
@@ -271,6 +272,8 @@ ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen)
{
+ ubyte sr;
+
/* Loop while thre are bytes remaining to be sent */
while (buflen > 0)
@@ -287,18 +290,32 @@ void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buf
}
}
- /* Then read from the RX FIFO while the RX FIFO is not empty or the TX FIFO
- * is not empty. We should get the same number of bytes in response as were
- * sent.
- */
+ /* Then discard all card responses until the TX FIFO is emptied. */
- while ((getreg8(LPC214X_SPI1_SR) & LPC214X_SPI1SR_RNE) ||
- !(getreg8(LPC214X_SPI1_SR) & LPC214X_SPI1SR_TFE))
+ do
{
- /* Read and discard */
+ /* Is there anything in the RX fifo? */
- (void)getreg16(LPC214X_SPI1_DR);
+ sr = getreg8(LPC214X_SPI1_SR);
+ if ((sr & LPC214X_SPI1SR_RNE) != 0)
+ {
+ /* Yes.. Read and discard */
+
+ (void)getreg16(LPC214X_SPI1_DR);
+ }
+
+ /* There is a race condition where TFE may go FALSE just before
+ * RNE goes true. The nasty little delay in the following solves
+ * that (it could probably be tuned to improve performance).
+ */
+
+ else if ((sr & LPC214X_SPI1SR_TFE) == 0)
+ {
+ up_udelay(200);
+ sr = getreg8(LPC214X_SPI1_SR);
+ }
}
+ while ((sr & LPC214X_SPI1SR_RNE) != 0 || (sr & LPC214X_SPI1SR_TFE) == 0);
}
/****************************************************************************