]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/msp430/usci/HplMsp430UsciInt0P.nc
Fix TMI copyright attributions
[tinyos-2.x.git] / tos / chips / msp430 / usci / HplMsp430UsciInt0P.nc
index 65ee5be1494f7c4a4e8269396197e2bd344d8a08..feb75cc14d7f86a9ebe3ba4e17bba51a1723f6da 100644 (file)
@@ -10,7 +10,7 @@
  * - Redistributions in binary form must reproduce the above copyright
  *   notice, this list of conditions and the following disclaimer in the
  *   documentation and/or other materials provided with the distribution.
- * - Neither the name of the Technische Universität Berlin nor the names
+ * - Neither the name of the Titanium Mirror, Inc. nor the names
  *   of its contributors may be used to endorse or promote products derived
  *   from this software without specific prior written permission.
  *
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /**
  * HPL interrupt interface for the USCI0 peripheral.
- * 
+ *
  * @author R. Steve McKown <rsmckown@gmail.com>
  */
+
 #include "Msp430Usci.h"
 #include "msp430hardware.h"
 
@@ -62,40 +62,59 @@ implementation
   MSP430REG_NORACE(UCB0RXBUF);
 #endif
 
-  /* This USCI_Ax and USCI_Bx interrupt vector signals receive events for UART
-   * and SPI modes, and status events for I2C modes.  Only Bx can do I2C.
+  /* This interrupt vector signals receive events.  USCI_A0 can receive events
+   * for UART and SPI modes, while USCI_B0 can receive events for I2C and SPI
+   * modes.
    */
   TOSH_SIGNAL(USCIAB0RX_VECTOR) {
-    if (READ_FLAG(UC0IFG, UCA0RXIFG)) {
+    if (READ_FLAG(UC0IFG & UC0IE, UCA0RXIE)) {
       volatile uint8_t c = UCA0RXBUF; /* read to clear UCA0RXIFG */
       if (READ_FLAG(UCA0CTL1, UCBRK)) {
-       UCA0CTL1 &= ~UCBRK;
+       CLR_FLAG(UCA0CTL1, UCBRK);
        if (READ_FLAG(UCA0CTL0, UCMODE_3) == UCMODE_3)
-         UCA0CTL1 &= ~UCDORM;
+         CLR_FLAG(UCA0CTL1, UCDORM);
        signal IntA.brk();
       } else
        signal IntA.rx(c);
-    } else if (READ_FLAG(UC0IFG, UCB0RXIFG))
+    } else if (READ_FLAG(UC0IFG & UC0IE, UCB0RXIE)) {
       signal IntB.rx(UCB0RXBUF); /* read clears UCB0RXIFG */
-    else if (READ_FLAG(UCB0STAT, UCALIFG))
+
+    /* FIXME: the arbitration of I2C interrupts are not vetted.  If, for example
+     * the UCALIFG bit gets set and neither it nor the corresponding interrupt
+     * enable bit is never unset, then an ISR configured for UCSTTIFG or
+     * UCSTPIFG will never be signalled.
+     */
+
+    } else if (READ_FLAG(UCB0STAT, UCALIFG)) {
+      CLR_FLAG(UCB0STAT, UCALIFG);
       signal IntB.i2cCal();
-    else if (READ_FLAG(UCB0STAT, UCNACKIFG))
-      signal IntB.i2cNak();
-    else if (READ_FLAG(UCB0STAT, UCSTTIFG))
+    } else if (READ_FLAG(UCB0STAT, UCNACKIFG)) {
+      CLR_FLAG(UCB0STAT, UCNACKIFG);
+      CLR_FLAG(UC0IFG, UCB0TXIFG); /* Errata USCI25; 'reset' means clear? */
+      signal IntB.i2cNack();
+    } else if (READ_FLAG(UCB0STAT, UCSTTIFG)) {
+      CLR_FLAG(UCB0STAT, UCSTTIFG);
       signal IntB.i2cStart();
-    else if (READ_FLAG(UCB0STAT, UCSTPIFG))
+    } else if (READ_FLAG(UCB0STAT, UCSTPIFG)) {
+      CLR_FLAG(UCB0STAT, UCSTPIFG);
       signal IntB.i2cStop();
+    }
   }
-  
-  /* This USCI_Ax and USCI_Bx interrupt vector signals transmit events for UART
-   * and SPI modes, and rx/tx events for I2C modes.  Only Bx can do I2C.
+
+  /* This interrupt vector signals transmit events.  USCI_A0 can receive events
+   * for UART and SPI modes, while USCI_B0 can receive events for I2C and SPI
+   * modes.
    */
   TOSH_SIGNAL(USCIAB0TX_VECTOR) {
-    if (READ_FLAG(UC0IFG, UCB0RXIFG))
-      signal IntB.rx(UCB0RXBUF); /* I2C receive */
-    else if (READ_FLAG(UC0IFG, UCA0TXIFG))
+    if (READ_FLAG(UC0IFG & UC0IE, UCB0RXIE)) {
+      /* I2C receive.  Do not read UCB0RXBUF here, as the code receiving
+       * IntB.rx() may first need to set stop and/or start bits.  The receiver
+       * must read UCB0RXBUF.
+       */
+      signal IntB.rx(0);
+    } else if (READ_FLAG(UC0IFG & UC0IE, UCA0TXIFG))
       signal IntA.tx();
-    else if (READ_FLAG(UC0IFG, UCB0TXIFG))
+    else if (READ_FLAG(UC0IFG & UC0IE, UCB0TXIFG))
       signal IntB.tx();
   }
 
@@ -104,15 +123,16 @@ implementation
   default async event void IntA.tx() {}
   /* i2c is not available for A devices, so the below are never signalled */
   default async event void IntA.i2cCal() {}
-  default async event void IntA.i2cNak() {}
+  default async event void IntA.i2cNack() {}
   default async event void IntA.i2cStart() {}
   default async event void IntA.i2cStop() {}
 
+  /* UART is not available for B devices, so IntB.brk() is never sitnalled */
   default async event void IntB.brk() {}
   default async event void IntB.rx(uint8_t byte) {}
   default async event void IntB.tx() {}
   default async event void IntB.i2cCal() {}
-  default async event void IntB.i2cNak() {}
+  default async event void IntB.i2cNack() {}
   default async event void IntB.i2cStart() {}
   default async event void IntB.i2cStop() {}
 }