From: R. Steve McKown Date: Thu, 8 Apr 2010 00:02:56 +0000 (-0600) Subject: Improve interrupt handling for USCI. X-Git-Tag: debian/2.1.0-4-1tmi~1^2~9 X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=commitdiff_plain;h=59a38cc43b09cc83e1a414ec0531588abab72cc9 Improve interrupt handling for USCI. 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. --- diff --git a/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc b/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc index 1ba7ef20..9e69649c 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc @@ -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(); } diff --git a/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc b/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc index 5fa0291c..2b9b1d4f 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc @@ -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(); }