* - 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"
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();
}
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() {}
}