]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Improve interrupt handling for USCI.
authorR. Steve McKown <rsmckown@gmail.com>
Thu, 8 Apr 2010 00:02:56 +0000 (18:02 -0600)
committerR. Steve McKown <rsmckown@gmail.com>
Tue, 13 Apr 2010 20:18:26 +0000 (14:18 -0600)
Because some interrupts share an interrupt vector, we use the relevant interrupt
enable bit to decide if any user is interested in the interrupt.  If not, that
interrupt is skipped so that another interrupt in the if/then/elseif chain can
be taken.  We also defensively try to prevent I2C interrupts from being a
problem if not used, although no I2C code using these interrupts has yet been
written.

tos/chips/msp430/usci/HplMsp430UsciInt0P.nc
tos/chips/msp430/usci/HplMsp430UsciInt1P.nc

index 1ba7ef20668adcf4ec1fd65226b53db1a970fc53..9e69649cd7701f039c4fa3e132a562e394d956bd 100644 (file)
@@ -67,25 +67,38 @@ implementation
    * 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))
+    } else if (READ_FLAG(UCB0STAT, UCNACKIFG)) {
+      CLR_FLAG(UCB0STAT, UCNACKIFG);
+      CLR_FLAG(UC0IFG, UCB0TXIFG); /* Errata USCI25; 'reset' means clear? */
       signal IntB.i2cNak();
-    else if (READ_FLAG(UCB0STAT, UCSTTIFG))
+    } 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 interrupt vector signals transmit events.  USCI_A0 can receive events
@@ -93,11 +106,11 @@ implementation
    * modes.
    */
   TOSH_SIGNAL(USCIAB0TX_VECTOR) {
-    if (READ_FLAG(UC0IFG, UCB0RXIFG))
+    if (READ_FLAG(UC0IFG & UC0IE, UCB0RXIE))
       signal IntB.rx(UCB0RXBUF); /* I2C receive */
-    else if (READ_FLAG(UC0IFG, UCA0TXIFG))
+    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();
   }
 
index 5fa0291ca8255daaa7a2f7fbc11c28afb78b1862..2b9b1d4fa052a57766677ff98330b624e1ecc5ea 100644 (file)
@@ -60,25 +60,38 @@ implementation
    * modes.
    */
   TOSH_SIGNAL(USCIAB1RX_VECTOR) {
-    if (READ_FLAG(UC1IFG, UCA1RXIFG)) {
+    if (READ_FLAG(UC1IFG & UC1IE, UCA1RXIE)) {
       volatile uint8_t c = UCA1RXBUF; /* read to clear UCA1RXIFG */
       if (READ_FLAG(UCA1CTL1, UCBRK)) {
-       UCA1CTL1 &= ~UCBRK;
+       CLR_FLAG(UCA1CTL1, UCBRK);
        if (READ_FLAG(UCA1CTL0, UCMODE_3) == UCMODE_3)
-         UCA1CTL1 &= ~UCDORM;
+         CLR_FLAG(UCA1CTL1, UCDORM);
        signal IntA.brk();
       } else
        signal IntA.rx(c);
-    } else if (READ_FLAG(UC1IFG, UCB1RXIFG))
+    } else if (READ_FLAG(UC1IFG & UC1IE, UCB1RXIE)) {
       signal IntB.rx(UCB1RXBUF); /* read clears UCB1RXIFG */
-    else if (READ_FLAG(UCB1STAT, 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(UCB1STAT, UCALIFG)) {
+      CLR_FLAG(UCB1STAT, UCALIFG);
       signal IntB.i2cCal();
-    else if (READ_FLAG(UCB1STAT, UCNACKIFG))
+    } else if (READ_FLAG(UCB1STAT, UCNACKIFG)) {
+      CLR_FLAG(UCB1STAT, UCNACKIFG);
+      CLR_FLAG(UC1IFG, UCB1TXIFG); /* Errata USCI25; 'reset' means clear? */
       signal IntB.i2cNak();
-    else if (READ_FLAG(UCB1STAT, UCSTTIFG))
+    } else if (READ_FLAG(UCB1STAT, UCSTTIFG)) {
+      CLR_FLAG(UCB1STAT, UCSTTIFG);
       signal IntB.i2cStart();
-    else if (READ_FLAG(UCB1STAT, UCSTPIFG))
+    } else if (READ_FLAG(UCB1STAT, UCSTPIFG)) {
+      CLR_FLAG(UCB1STAT, UCSTPIFG);
       signal IntB.i2cStop();
+    }
   }
   
   /* This interrupt vector signals transmit events.  USCI_A1 can receive events
@@ -86,11 +99,11 @@ implementation
    * modes.
    */
   TOSH_SIGNAL(USCIAB1TX_VECTOR) {
-    if (READ_FLAG(UC1IFG, UCB1RXIFG))
+    if (READ_FLAG(UC1IFG & UC1IE, UCB1RXIE))
       signal IntB.rx(UCB1RXBUF); /* I2C receive */
-    else if (READ_FLAG(UC1IFG, UCA1TXIFG))
+    else if (READ_FLAG(UC1IFG & UC1IE, UCA1TXIFG))
       signal IntA.tx();
-    else if (READ_FLAG(UC1IFG, UCB1TXIFG))
+    else if (READ_FLAG(UC1IFG & UC1IE, UCB1TXIFG))
       signal IntB.tx();
   }