]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Implement chip select query for SPI peripheral.
authorsmckown <smckown@4bc1554a-c7f2-4f65-a403-e0be01f0239c>
Fri, 8 May 2009 22:27:14 +0000 (22:27 +0000)
committerR. Steve McKown <rsmckown@gmail.com>
Tue, 1 Dec 2009 03:01:32 +0000 (20:01 -0700)
If the SPI peripheral is in slave mode, a transaction could be halted at any
time by the host unasserting (high) the chip select line.  This code implements
a check on chip select to allow SPI slaves to see the early abort and act
accordingly.

tos/chips/msp430/usci/Msp430SpiA0C.nc
tos/chips/msp430/usci/Msp430SpiB0C.nc
tos/chips/msp430/usci/Msp430SpiB1C.nc
tos/chips/msp430/usci/Msp430SpiP.nc

index c428bb8f0056a6aa26e16334c2a6c6f5de54745d..9f166521bf76c4d2531982212ee9981476368cf3 100644 (file)
@@ -65,7 +65,10 @@ generic configuration Msp430SpiA0C(uint16_t blockSize) {
     interface SpiPacket;
     interface ArbiterInfo; /* ??? */
   }
-  uses interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+  uses {
+    interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+    interface GeneralIO as CSn;        /* wire only if a SPI slave only */
+  }
 }
 implementation {
   enum {
@@ -76,6 +79,7 @@ implementation {
   SpiByte = SpiP;
   SpiPacket = SpiP;
   Configure = SpiP;
+  CSn = SpiP;
 
   components Msp430UsciA0C as UsciC;
   Resource = UsciC.Resource[CLIENT_ID];
index 6684b79d574d88b568d1e3aa8c9ba7e5c8b2a07d..dbd008220be9ca39ef13aa7019eed1492c86d81e 100644 (file)
@@ -65,7 +65,10 @@ generic configuration Msp430SpiB0C(uint16_t blockSize) {
     interface SpiPacket;
     interface ArbiterInfo; /* ??? */
   }
-  uses interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+  uses {
+    interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+    interface GeneralIO as CSn;        /* wire only if a SPI slave only */
+  }
 }
 implementation {
   enum {
@@ -76,6 +79,7 @@ implementation {
   SpiByte = SpiP;
   SpiPacket = SpiP;
   Configure = SpiP;
+  CSn = SpiP;
 
   components Msp430UsciB0C as UsciC;
   Resource = UsciC.Resource[CLIENT_ID];
index 7a5b400b13e1acc7e1143fc999dd6b292402da4a..5fc73fc23356aaf98e7a07844636a5efc83f9589 100644 (file)
@@ -65,7 +65,10 @@ generic configuration Msp430SpiB1C(uint16_t blockSize) {
     interface SpiPacket;
     interface ArbiterInfo; /* ??? */
   }
-  uses interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+  uses {
+    interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+    interface GeneralIO as CSn;        /* wire only if a SPI slave only */
+  }
 }
 implementation {
   enum {
@@ -76,6 +79,7 @@ implementation {
   SpiByte = SpiP;
   SpiPacket = SpiP;
   Configure = SpiP;
+  CSn = SpiP;
 
   components Msp430UsciB1C as UsciC;
   Resource = UsciC.Resource[CLIENT_ID];
index b230f607cab60ca2035626a302686ff5932f2b27..0aaf9bd34c06c17784a526fa9c4d1aa7675d8537 100644 (file)
@@ -28,7 +28,9 @@
  */
  
 /**
- * Spi implementation using a USCI device.
+ * Spi implementation using a USCI device.  When being used as a SPI slave, the
+ * CSn interface should be wired to the chip select driven by the SPI master so
+ * the module can know when a communications session is terminated unexpectedly.
  *
  * TODO: Implement error checking via UCxxSTAT
  *
@@ -46,6 +48,7 @@ generic module Msp430SpiP(uint16_t blockSize) {
   uses {
     interface HplMsp430UsciReg as Registers;
     interface HplMsp430UsciInt as Interrupts;
+    interface GeneralIO as CSn;
     interface HplMsp430GeneralIO as STE;
     interface HplMsp430GeneralIO as SIMO;
     interface HplMsp430GeneralIO as SOMI;
@@ -74,12 +77,12 @@ implementation {
   uint16_t m_len;
   uint16_t m_pos;
 
-  inline bool is4pin() /* true if the SPI bus is in 4-pin mode */
+  inline bool is4pin() /* TRUE if the SPI bus is in 4-pin mode */
   {
     return (call Registers.getCtl0(UCMODE_3)) != UCMODE_0;
   }
 
-  inline bool isBusy() /* true if a SPI transaction is in progress */
+  inline bool isBusy() /* TRUE if a SPI transaction is in progress */
   {
     atomic return m_len != 0;
   }
@@ -205,57 +208,35 @@ implementation {
     }
   }
 
-  async command uint8_t SpiByte.write(uint8_t byte)
+  bool waitOnRx()
   {
-    if (isBusy())
-      return 0;
-    else {
-      while (!call Registers.getIfgTx() && !call Registers.getCtl1(UCSWRST));
-      call Registers.setTxbuf(byte);
-      while(!call Registers.getIfgRx() && !call Registers.getCtl1(UCSWRST));
-      return call Registers.getRxbuf();
+    for (;;) {
+      if (call Registers.getIfgRx())
+       return TRUE;
+      if (call CSn.get())              /* SPI master has unselected us */
+       return FALSE;
     }
   }
 
-  bool waitOnRx()
+  bool waitOnTx()
   {
-    if (call Registers.getCtl0(UCMST)) {
-      while (!call Registers.getIfgRx() && !call Registers.getCtl1(UCSWRST));
-      return TRUE;
-    } else {
-      /* If SPI slave, the host could quit clocking any time, so we need a
-       * timeout.
-       */
-      unsigned i = 0;
-
-      while (++i) {
-       if (call Registers.getIfgRx())
-         return TRUE;
-       if (call Registers.getCtl1(UCSWRST))
-         return FALSE;
-      }
-      return FALSE;
+    for (;;) {
+      if (call Registers.getIfgTx())
+       return TRUE;
+      if (call CSn.get())              /* SPI master has unselected us */
+       return FALSE;
     }
   }
 
-  bool waitOnTx()
+  async command uint8_t SpiByte.write(uint8_t byte)
   {
-    if (call Registers.getCtl0(UCMST)) {
-      while (!call Registers.getIfgTx() && !call Registers.getCtl1(UCSWRST));
-      return TRUE;
-    } else {
-      /* If SPI slave, the host could quit clocking any time, so we need a
-       * timeout.
-       */
-      unsigned i = 0;
-
-      while (++i) {
-       if (call Registers.getIfgTx())
-         return TRUE;
-       if (call Registers.getCtl1(UCSWRST))
-         return FALSE;
-      }
-      return FALSE;
+    if (isBusy())
+      return 0;
+    else {
+      waitOnTx();
+      call Registers.setTxbuf(byte);
+      waitOnRx();
+      return call Registers.getRxbuf();
     }
   }
 
@@ -277,7 +258,7 @@ implementation {
        waitOnTx();
        call Registers.setTxbuf(m_txBuf ? m_txBuf[m_pos] : 0);
       }
-      return call Registers.getCtl1(UCSWRST) ? FALSE : TRUE;
+      return call CSn.get() ? FALSE : TRUE;
     }
   }
 
@@ -339,4 +320,6 @@ implementation {
   async event void Interrupts.i2cCal() {}
   async event void Interrupts.brk() {}
   async event void Interrupts.i2cNak() {}
+
+  default async command bool CSn.get() { return FALSE; }
 }