]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
MSP430 USCI peripheral
authorsmckown <smckown@4bc1554a-c7f2-4f65-a403-e0be01f0239c>
Sun, 7 Sep 2008 01:20:29 +0000 (01:20 +0000)
committerR. Steve McKown <rsmckown@gmail.com>
Mon, 9 Jul 2012 16:32:14 +0000 (10:32 -0600)
Supports UART, SPI (slave and master), and I2C modes.

Current I2C limitations and features:

* Master mode only.
* No multi-master bus configurations.
* Will automatically reset a hung bus, if for example the master reset in the
  middle of a transaction and a slave currently is driving SDA low.
* Repeated starts are supported and can be very time efficient.
* An I2C transactions may be processed with multiple I2CPacket.read() or
  I2CPacket.write() commands, as appropriate.  The first must include I2C_START
  and the last must include I2C_STOP.
* Conditions exist during read where the hardware may clock out an extra byte
  from the slave before stop.  This byte is not passed to the user.

23 files changed:
tos/chips/msp430/usci/AsyncConfigure.nc [new file with mode: 0644]
tos/chips/msp430/usci/HplMsp430UsciC.nc [new file with mode: 0644]
tos/chips/msp430/usci/HplMsp430UsciInt.nc [new file with mode: 0644]
tos/chips/msp430/usci/HplMsp430UsciInt0P.nc [new file with mode: 0644]
tos/chips/msp430/usci/HplMsp430UsciInt1P.nc [new file with mode: 0644]
tos/chips/msp430/usci/HplMsp430UsciReg.nc [new file with mode: 0644]
tos/chips/msp430/usci/HplMsp430UsciRegP.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430I2CB0C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430I2CB1C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430I2CP.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430SpiA0C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430SpiB0C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430SpiB1C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430SpiP.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430UartA0C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430UartA1C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430UartP.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430Usci.h [new file with mode: 0644]
tos/chips/msp430/usci/Msp430UsciA0C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430UsciA1C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430UsciB0C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430UsciB1C.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430UsciIntDispatchP.nc [new file with mode: 0644]

diff --git a/tos/chips/msp430/usci/AsyncConfigure.nc b/tos/chips/msp430/usci/AsyncConfigure.nc
new file mode 100644 (file)
index 0000000..f1e343d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Generic async configuration interface.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+interface AsyncConfigure<val_t> {
+  async command val_t get();
+}
diff --git a/tos/chips/msp430/usci/HplMsp430UsciC.nc b/tos/chips/msp430/usci/HplMsp430UsciC.nc
new file mode 100644 (file)
index 0000000..05917df
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Provides HPL access to both registers and interrupts of all USCI devices on
+ * a supported msp430 processor.  The interfaces available are created
+ * depending upon the type of msp430 for which the code is being compiled.
+ * Currently most parts with one or two USCI peripherals supported by mspgcc
+ * (msp430-gcc) should be supported.  The most common will probably be the
+ * parts offering two USCI peripherals, which use names like these to describe
+ * their provided serial devices:
+ *
+ *    USCI_A0 and USCI_B0, from the first USCI peripheral; and
+ *    USCI_A1 and USCI_B1, from the second USCI peripheral.
+ *
+ * 'A' devices offer UART, LIN, IrDA and SPI modes of operation.  'B' devices
+ * are limited to SPI and I2C modes.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+configuration HplMsp430UsciC {
+  provides {
+#if defined(__MSP430_HAS_USCI_AB0__) || defined(__MSP430_HAS_USCI__)
+    interface HplMsp430UsciReg as RegA0;
+    interface HplMsp430UsciInt as IntA0;
+    interface HplMsp430UsciReg as RegB0;
+    interface HplMsp430UsciInt as IntB0;
+#endif
+#if defined(__MSP430_HAS_USCI_AB1__)
+    interface HplMsp430UsciReg as RegA1;
+    interface HplMsp430UsciInt as IntA1;
+    interface HplMsp430UsciReg as RegB1;
+    interface HplMsp430UsciInt as IntB1;
+#endif
+  }
+}
+implementation {
+#if defined(__MSP430_HAS_USCI_AB0__) || defined(__MSP430_HAS_USCI__)
+  components new HplMsp430UsciRegP(UCA0CTL0_, UCA0CTL1_, UCA0BR0_, UCA0BR1_,
+    UCA0MCTL_, 0/*UCA0I2CIE_*/, UCA0STAT_, UCA0RXBUF_, UCA0TXBUF_, UCA0ABCTL_,
+    UCA0IRTCTL_, UCA0IRRCTL_, 0/*UCA0I2COA_*/, 0/*UCA0I2CSA_*/, IE2_, IFG2_,
+    UCA0RXIFG, UCA0TXIFG) as RegA0P;
+  RegA0 = RegA0P.Registers;
+
+  components new HplMsp430UsciRegP(UCB0CTL0_, UCB0CTL1_, UCB0BR0_, UCB0BR1_,
+    0/*UCB0MCTL_*/, UCB0I2CIE_, UCB0STAT_, UCB0RXBUF_, UCB0TXBUF_,
+    0/*UCB0ABCTL_*/, 0/*UCB0IRTCTL_*/, 0/*UCB0IRRCTL_*/, UCB0I2COA_,
+    UCB0I2CSA_, IE2_, IFG2_, UCB0RXIFG, UCB0TXIFG) as RegB0P;
+  RegB0 = RegB0P.Registers;
+
+  components HplMsp430UsciInt0P as Int0P;
+  IntA0 = Int0P.IntA;
+  IntB0 = Int0P.IntB;
+#endif
+
+#if defined(__MSP430_HAS_USCI_AB1__)
+  components new HplMsp430UsciRegP(UCA1CTL0_, UCA1CTL1_, UCA1BR0_, UCA1BR1_,
+    UCA1MCTL_, 0/*UCA1I2CIE_*/, UCA1STAT_, UCA1RXBUF_, UCA1TXBUF_, UCA1ABCTL_,
+    UCA1IRTCTL_, UCA1IRRCTL_, 0/*UCA1I2COA_*/, 0/*UCA1I2CSA_*/, UC1IE_,
+    UC1IFG_, UCA1RXIFG, UCA1TXIFG) as RegA1P;
+  RegA1 = RegA1P.Registers;
+
+  components new HplMsp430UsciRegP(UCB1CTL0_, UCB1CTL1_, UCB1BR0_, UCB1BR1_,
+    0/*UCB1MCTL_*/, UCB1I2CIE_, UCB1STAT_, UCB1RXBUF_, UCB1TXBUF_,
+    0/*UCB1ABCTL_*/, 0/*UCB1IRTCTL_*/, 0/*UCB1IRRCTL_*/, UCB1I2COA_,
+    UCB1I2CSA_, UC1IE_, UC1IFG_, UCB1RXIFG, UCB1TXIFG) as RegB1P;
+  RegB1 = RegB1P.Registers;
+
+  components HplMsp430UsciInt1P as Int1P;
+  IntA1 = Int1P.IntA;
+  IntB1 = Int1P.IntB;
+#endif
+}
diff --git a/tos/chips/msp430/usci/HplMsp430UsciInt.nc b/tos/chips/msp430/usci/HplMsp430UsciInt.nc
new file mode 100644 (file)
index 0000000..d0021cd
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Interrupt interface for USCI peripherals.  Although A and B devices have
+ * different interrupt sets since B only support I2C, we use a single set for
+ * both so that upper layers need not deal with the different sets.  This is
+ * critical in the case of SPI communications, which is supported by both A
+ * and B devices.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#include "Msp430Usci.h"
+
+interface HplMsp430UsciInt {
+  /**
+   * Signals a break received in UART modes if UCBRKIE is enabled.  The
+   * provider must reset the UCxIFG.UCxxRXIFG and UCxSTAT.UCBRK bits prior to
+   * signalling the event to the user.
+   */
+  async event void brk();
+
+  /**
+   * Signals a character received for any USCI mode.  The provider must reset
+   * UCxIFG.UCxxRXIFG before signalling the event to the user.
+   *
+   * @params byte The character received.
+   */
+  async event void rx(uint8_t byte);
+
+  /**
+   * Signals that the device's transmit buffer is empty and can accept
+   * another character.  Note that the USCI device may still be in the
+   * process of transmitting the last character when this event is signalled.
+   * The UCxxTXIFG bit will automatically reset when the interface user writes
+   * a value to the related UCxxTXBUF register after receipt of this event.
+   */
+  async event void tx();
+
+  /**
+   * I2C mode only.  Indicates the device has lost arbitration.  Valid only in
+   * multi-master contexts.
+   */
+  async event void i2cCal();
+
+  /**
+   * I2C mode only.  Indicates the device was expecting an ACK and it was not
+   * received.
+   */
+  async event void i2cNack();
+
+  /**
+   * I2C mode only.  Indicates the device has detected a start condition
+   * together with its own address while in slave mode.
+   */
+  async event void i2cStart();
+
+  /**
+   * I2C mode only.  Indicates the device has detected a stop condition while
+   * in slave mode.
+   */
+  async event void i2cStop();
+}
diff --git a/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc b/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc
new file mode 100644 (file)
index 0000000..d802a0b
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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"
+
+#if defined(USCIRX_VECTOR) /* odd def for MSP430G461 */
+#define USCIAB0RX_VECTOR USCIRX_VECTOR
+#endif
+#if defined(USCITX_VECTOR) /* odd def for MSP430G461 */
+#define USCIAB0TX_VECTOR USCITX_VECTOR
+#endif
+
+module HplMsp430UsciInt0P @safe() {
+  provides {
+    interface HplMsp430UsciInt as IntA;
+    interface HplMsp430UsciInt as IntB;
+  }
+}
+
+implementation
+{
+#if 0
+  MSP430REG_NORACE(UC0IFG);
+  MSP430REG_NORACE(UCA0CTL0);
+  MSP430REG_NORACE(UCA0CTL1);
+  MSP430REG_NORACE(UCA0RXBUF);
+  MSP430REG_NORACE(UCB0CTL0);
+  MSP430REG_NORACE(UCB0CTL1);
+  MSP430REG_NORACE(UCB0RXBUF);
+#endif
+
+  /* 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 & UC0IE, UCA0RXIE)) {
+      volatile uint8_t c = UCA0RXBUF; /* read to clear UCA0RXIFG */
+      if (READ_FLAG(UCA0CTL1, UCBRK)) {
+       CLR_FLAG(UCA0CTL1, UCBRK);
+       if (READ_FLAG(UCA0CTL0, UCMODE_3) == UCMODE_3)
+         CLR_FLAG(UCA0CTL1, UCDORM);
+       signal IntA.brk();
+      } else
+       signal IntA.rx(c);
+    } else if (READ_FLAG(UC0IFG & UC0IE, UCB0RXIE)) {
+      signal IntB.rx(UCB0RXBUF); /* read clears UCB0RXIFG */
+
+    /* 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)) {
+      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)) {
+      CLR_FLAG(UCB0STAT, UCSTPIFG);
+      signal IntB.i2cStop();
+    }
+  }
+
+  /* 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 & 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 & UC0IE, UCB0TXIFG))
+      signal IntB.tx();
+  }
+
+  default async event void IntA.brk() {}
+  default async event void IntA.rx(uint8_t byte) {}
+  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.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.i2cNack() {}
+  default async event void IntB.i2cStart() {}
+  default async event void IntB.i2cStop() {}
+}
diff --git a/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc b/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc
new file mode 100644 (file)
index 0000000..1e18eb7
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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 USCI1 peripheral.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#include "Msp430Usci.h"
+#include "msp430hardware.h"
+
+module HplMsp430UsciInt1P @safe() {
+  provides {
+    interface HplMsp430UsciInt as IntA;
+    interface HplMsp430UsciInt as IntB;
+  }
+}
+
+implementation
+{
+#if 0
+  MSP430REG_NORACE(UC1IFG);
+  MSP430REG_NORACE(UCA1CTL0);
+  MSP430REG_NORACE(UCA1CTL1);
+  MSP430REG_NORACE(UCA1RXBUF);
+  MSP430REG_NORACE(UCB1CTL0);
+  MSP430REG_NORACE(UCB1CTL1);
+  MSP430REG_NORACE(UCB1RXBUF);
+#endif
+
+  /* This interrupt vector signals receive events.  USCI_A1 can receive events
+   * for UART and SPI modes, while USCI_B1 can receive events for I2C and SPI
+   * modes.
+   */
+  TOSH_SIGNAL(USCIAB1RX_VECTOR) {
+    if (READ_FLAG(UC1IFG & UC1IE, UCA1RXIE)) {
+      volatile uint8_t c = UCA1RXBUF; /* read to clear UCA1RXIFG */
+      if (READ_FLAG(UCA1CTL1, UCBRK)) {
+       CLR_FLAG(UCA1CTL1, UCBRK);
+       if (READ_FLAG(UCA1CTL0, UCMODE_3) == UCMODE_3)
+         CLR_FLAG(UCA1CTL1, UCDORM);
+       signal IntA.brk();
+      } else
+       signal IntA.rx(c);
+    } else if (READ_FLAG(UC1IFG & UC1IE, UCB1RXIE)) {
+      signal IntB.rx(UCB1RXBUF); /* read clears UCB1RXIFG */
+
+    /* 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)) {
+      CLR_FLAG(UCB1STAT, UCNACKIFG);
+      CLR_FLAG(UC1IFG, UCB1TXIFG); /* Errata USCI25; 'reset' means clear? */
+      signal IntB.i2cNack();
+    } else if (READ_FLAG(UCB1STAT, UCSTTIFG)) {
+      CLR_FLAG(UCB1STAT, UCSTTIFG);
+      signal IntB.i2cStart();
+    } else if (READ_FLAG(UCB1STAT, UCSTPIFG)) {
+      CLR_FLAG(UCB1STAT, UCSTPIFG);
+      signal IntB.i2cStop();
+    }
+  }
+
+  /* This interrupt vector signals transmit events.  USCI_A1 can receive events
+   * for UART and SPI modes, while USCI_B1 can receive events for I2C and SPI
+   * modes.
+   */
+  TOSH_SIGNAL(USCIAB1TX_VECTOR) {
+    if (READ_FLAG(UC1IFG & UC1IE, UCB1RXIE))
+      /* I2C receive.  Do not read UCB1RXBUF here, as the code receiving
+       * IntB.rx() may first need to set stop and/or start bits.  The receiver
+       * must read UCB1RXBUF.
+       */
+      signal IntB.rx(0);
+    else if (READ_FLAG(UC1IFG & UC1IE, UCA1TXIFG))
+      signal IntA.tx();
+    else if (READ_FLAG(UC1IFG & UC1IE, UCB1TXIFG))
+      signal IntB.tx();
+  }
+
+  default async event void IntA.brk() {}
+  default async event void IntA.rx(uint8_t byte) {}
+  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.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.i2cNack() {}
+  default async event void IntB.i2cStart() {}
+  default async event void IntB.i2cStop() {}
+}
diff --git a/tos/chips/msp430/usci/HplMsp430UsciReg.nc b/tos/chips/msp430/usci/HplMsp430UsciReg.nc
new file mode 100644 (file)
index 0000000..b3a876f
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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 interface to a USCI peripheral device in UART mode.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#include "Msp430Usci.h"
+
+interface HplMsp430UsciReg {
+  /**
+   * Return the current mode.
+   */
+  async command msp430_usci_mode_t getMode();
+
+  /**
+   * Prepare to set the mode.  If the device supports the requested mode, its
+   * UCxxCTL1.UCSWRST bit is set and TRUE is returned.  If the device does not
+   * support the requested mode, no operations are performed and FALSE is
+   * returned.
+   *
+   * @param msp430usci_mode_t The desired USCI mode.
+   * @return bool TRUE if the device supports the requested mode, else FALSE.
+   */
+  async command bool setMode(msp430_usci_mode_t mode);
+
+  /**
+   * Get pointer to the UCxxCTL0 register associated with the USCI device.
+   *
+   * @return The pointer to the device's UCxxCTL0 register.
+   */
+  async command volatile uint8_t* ptrCtl0();
+
+  /**
+   * Get bits from the UCxxCTL0 register associated with the USCI device.
+   *
+   * @parm mask The bits upon which the operation is to be performed must be
+   * set in <t>mask</t>.
+   * @return The value of the device's UCxxCTL0 register ANDed with
+   * <t>mask</t>.
+   */
+  async command uint8_t getCtl0(uint8_t mask);
+
+  /**
+   * Set bits in the UCxxCTL0 register associated with the USCI device.
+   * The operation is equivalent to: <t>UCxxCTL0 |= mask</t>.
+   *
+   * @parm mask The bits in set in <t>mask</t> to set in UCxxCTL0.
+   */
+  async command void setCtl0(uint8_t mask);
+
+  /**
+   * Clear bits in the UCxxCTL0 register associated with the USCI device.
+   * The operation is equivalent to: <t>UCxxCTL0 &= ~mask</t>.
+   *
+   * @parm mask The bits in set in <t>mask</t> to clear in UCxxCTL0.
+   */
+  async command void clrCtl0(uint8_t mask);
+
+  /**
+   * Assign the values of the bits in <t>value</t>, whose corresponding bits in
+   * <t>mask</t> are set, in the UCxxCTL0 register.  The operation is
+   * equivalent to: <t>UCxxCTL0 = (UCxxCTL0 & ~mask) | (value & mask)</t>.
+   */
+  //async command void assignCtl0(uint8_t mask, uint8_t value);
+  async command void assignCtl0(uint8_t value);
+
+  /**
+   * Manipulate bits in the UCxxCTL1 register.  See the methods that manipulate
+   * UCxxCTL0 for more information.
+   */
+  async command volatile uint8_t* ptrCtl1();
+  async command uint8_t getCtl1(uint8_t mask);
+  async command void setCtl1(uint8_t mask);
+  async command void clrCtl1(uint8_t mask);
+  //async command void assignCtl1(uint8_t mask, uint8_t value);
+  async command void assignCtl1(uint8_t value);
+
+  /**
+   * Manipulate bits in the UCxxBR0 register.  See the methods that manipulate
+   * UCxxCTL0 for more information.
+   */
+  async command volatile uint8_t* ptrBr0();
+  async command uint8_t getBr0(uint8_t mask);
+  async command void setBr0(uint8_t mask);
+  async command void clrBr0(uint8_t mask);
+  //async command void assignBr0(uint8_t mask, uint8_t value);
+  async command void assignBr0(uint8_t value);
+
+  /**
+   * Manipulate bits in the UCxxBR1 register.  See the methods that manipulate
+   * UCxxCTL0 for more information.
+   */
+  async command volatile uint8_t* ptrBr1();
+  async command uint8_t getBr1(uint8_t mask);
+  async command void setBr1(uint8_t mask);
+  async command void clrBr1(uint8_t mask);
+  //async command void assignBr1(uint8_t mask, uint8_t value);
+  async command void assignBr1(uint8_t value);
+
+  /**
+   * Manipulate bits in the UCxxMCTL register.  See the methods that manipulate
+   * UCxxCTL0 for more information.  These methods perform no operation on
+   * providers implementing a USCI_Bx device.
+   */
+  async command volatile uint8_t* ptrMctl();
+  async command uint8_t getMctl(uint8_t mask);
+  async command void setMctl(uint8_t mask);
+  async command void clrMctl(uint8_t mask);
+  //async command void assignMctl(uint8_t mask, uint8_t value);
+  async command void assignMctl(uint8_t value);
+
+  /**
+   * Manipulate bits in the UCxxI2CIE register.  See the methods that
+   * manipulate UCxxCTL0 for more information.  These methods perform no
+   * operation on providers implementing a USCI_Ax device.
+   */
+  async command volatile uint8_t* ptrI2Cie();
+  async command uint8_t getI2Cie(uint8_t mask);
+  async command void setI2Cie(uint8_t mask);
+  async command void clrI2Cie(uint8_t mask);
+  //async command void assignI2Cie(uint8_t mask, uint8_t value);
+  async command void assignI2Cie(uint8_t value);
+
+  /**
+   * Manipulate bits in the UCxxSTAT register.  See the methods that manipulate
+   * UCxxCTL0 for more information.
+   */
+  async command volatile uint8_t* ptrStat();
+  async command uint8_t getStat(uint8_t mask);
+  async command void setStat(uint8_t mask);
+  async command void clrStat(uint8_t mask);
+  //async command void assignStat(uint8_t mask, uint8_t value);
+  async command void assignStat(uint8_t value);
+
+  /**
+   * Return pointer to the UCAxxRXBUF register used by the USCI device.
+   */
+  async command volatile uint8_t* ptrRxbuf();
+
+  /**
+   * Read the contents of the UCAxxRXBUF register.  This register cannot be
+   * written.
+   */
+  async command uint8_t getRxbuf();
+
+  /**
+   * Return pointer to the UCAxxTXBUF register used by the USCI device.
+   */
+  async command volatile uint8_t* ptrTxbuf();
+
+  /**
+   * Read the contents of the UCAxxTXBUF register.
+   */
+  async command uint8_t getTxbuf();
+
+  /**
+   * Write a byte to the UCAxxTXBUF register.
+   */
+  async command void setTxbuf(uint8_t byte);
+
+  /**
+   * Manipulate bits in the UCxxABCTL register.  See the methods that
+   * manipulate UCxxCTL0 for more information.  These methods perform no
+   * operation on providers implementing a USCI_Bx device.
+   */
+  async command volatile uint8_t* ptrAbctl();
+  async command uint8_t getAbctl(uint8_t mask);
+  async command void setAbctl(uint8_t mask);
+  async command void clrAbctl(uint8_t mask);
+  //async command void assignAbctl(uint8_t mask, uint8_t value);
+  async command void assignAbctl(uint8_t value);
+
+  /**
+   * Manipulate bits in the UCxxIRTCTL register.  See the methods that
+   * manipulate UCxxCTL0 for more information.  These methods perform no
+   * operation on providers implementing a USCI_Bx device.
+   */
+  async command volatile uint8_t* ptrIrtctl();
+  async command uint8_t getIrtctl(uint8_t mask);
+  async command void setIrtctl(uint8_t mask);
+  async command void clrIrtctl(uint8_t mask);
+  //async command void assignIrtctl(uint8_t mask, uint8_t value);
+  async command void assignIrtctl(uint8_t value);
+
+  /**
+   * Manipulate bits in the UCxxIRRCTL register.  See the methods that
+   * manipulate UCxxCTL0 for more information.  These methods perform no
+   * operation on providers implementing a USCI_Bx device.
+   */
+  async command volatile uint8_t* ptrIrrctl();
+  async command uint8_t getIrrctl(uint8_t mask);
+  async command void setIrrctl(uint8_t mask);
+  async command void clrIrrctl(uint8_t mask);
+  //async command void assignIrrctl(uint8_t mask, uint8_t value);
+  async command void assignIrrctl(uint8_t value);
+
+  /**
+   * Access to the UCBxI2COA register.
+   */
+  async command volatile uint8_t* ptrI2Coa();
+  async command uint16_t readI2Coa();
+  async command void assignI2Coa(uint16_t addr);
+
+  /**
+   * Access to the UCBxI2SA register.
+   */
+  async command volatile uint8_t* ptrI2Csa();
+  async command uint16_t readI2Csa();
+  async command void assignI2Csa(uint16_t addr);
+
+  /**
+   * Manipulate bits in the UCxxIE register.  See the methods that manipulate
+   * UCxxCTL0 for more information.
+   */
+  async command bool getIeRx();
+  async command void setIeRx();
+  async command void clrIeRx();
+  async command bool getIeTx();
+  async command void setIeTx();
+  async command void clrIeTx();
+
+  /**
+   * Manipulate bits in the UCxxIFG register.  See the methods that manipulate
+   * UCxxCTL0 for more information.
+   */
+  async command bool getIfgRx();
+  async command void clrIfgRx();
+  async command bool getIfgTx();
+  async command void clrIfgTx();
+}
diff --git a/tos/chips/msp430/usci/HplMsp430UsciRegP.nc b/tos/chips/msp430/usci/HplMsp430UsciRegP.nc
new file mode 100644 (file)
index 0000000..32f3de1
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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 register interface to USCI peripherals.  The interface abstracts the
+ * differences between pysical devices (aka addresses) such that a user of
+ * the interface can equally use any USCI device, providing the device
+ * provides the necessary capabilities.  For example, I2C is only available
+ * on USCI_Bx ports.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#include "Msp430Usci.h"
+#include "msp430hardware.h"
+
+generic module HplMsp430UsciRegP(
+    uint16_t Ctl0_addr,
+    uint16_t Ctl1_addr,
+    uint16_t Br0_addr,
+    uint16_t Br1_addr,
+    uint16_t Mctl_addr,                /* A devices only */
+    uint16_t I2Cie_addr,       /* B devices only */
+    uint16_t Stat_addr,
+    uint16_t Rxbuf_addr,
+    uint16_t Txbuf_addr,
+    uint16_t Abctl_addr,       /* A devices only */
+    uint16_t Irtctl_addr,      /* A devices only */
+    uint16_t Irrctl_addr,      /* A devices only */
+    uint16_t I2Coa_addr,       /* B devices only */
+    uint16_t I2Csa_addr,       /* B devices only */
+    uint16_t Ie_addr,
+    uint16_t Ifg_addr,
+    uint16_t UCxxRXIFG,        /* We rely on xIE and xIFG at same bit positions */
+    uint16_t UCxxTXIFG
+    ) @safe() {
+  provides interface HplMsp430UsciReg as Registers;
+}
+
+implementation
+{
+  #define IS_USCI_Ax (Mctl_addr != 0)
+  #define IS_USCI_Bx (I2Cie_addr != 0)
+
+  #define UCxxCtl0 (*TCAST(volatile uint8_t* ONE, Ctl0_addr))
+  #define UCxxCtl1 (*TCAST(volatile uint8_t* ONE, Ctl1_addr))
+  #define UCxxBr0 (*TCAST(volatile uint8_t* ONE, Br0_addr))
+  #define UCxxBr1 (*TCAST(volatile uint8_t* ONE, Br1_addr))
+  #define UCAxMctl (*TCAST(volatile uint8_t* ONE, Mctl_addr))
+  #define UCBxI2Cie (*TCAST(volatile uint8_t* ONE, I2Cie_addr))
+  #define UCxxStat (*TCAST(volatile uint8_t* ONE, Stat_addr))
+  #define UCxxRxbuf (*TCAST(volatile uint8_t* ONE, Rxbuf_addr))
+  #define UCxxTxbuf (*TCAST(volatile uint8_t* ONE, Txbuf_addr))
+  #define UCAxAbctl (*TCAST(volatile uint8_t* ONE, Abctl_addr))
+  #define UCAxIrtctl (*TCAST(volatile uint8_t* ONE, Irtctl_addr))
+  #define UCAxIrrctl (*TCAST(volatile uint8_t* ONE, Irrctl_addr))
+  #define UCBxI2Coa (*TCAST(volatile uint8_t* ONE, I2Coa_addr))
+  #define UCBxI2Csa (*TCAST(volatile uint8_t* ONE, I2Csa_addr))
+  #define UCxxIe (*TCAST(volatile uint8_t* ONE, Ie_addr))
+  #define UCxxIfg (*TCAST(volatile uint8_t* ONE, Ifg_addr))
+
+#if 0
+  #define ASSIGNBITS(reg, mask, value) \
+               (reg = ((reg) & ~(mask)) | ((value) & (mask)))
+#endif
+
+  #define RENDER(name) \
+       async command volatile uint8_t* Registers.ptr##name() { \
+               return &UCxx##name; \
+       } \
+       async command uint8_t Registers.get##name(uint8_t mask) { \
+               return READ_FLAG(UCxx##name, mask); \
+       } \
+       async command void Registers.set##name(uint8_t mask) { \
+               SET_FLAG(UCxx##name, mask); \
+       } \
+       async command void Registers.clr##name(uint8_t mask) { \
+               CLR_FLAG(UCxx##name, mask); \
+       } \
+       async command void Registers.assign##name(uint8_t value) { \
+               UCxx##name = value; \
+       }
+
+  #define RENDER_A(name) \
+       async command volatile uint8_t* Registers.ptr##name() { \
+               return &UCAx##name; \
+       } \
+       async command uint8_t Registers.get##name(uint8_t mask) { \
+               if (IS_USCI_Ax) \
+                       return READ_FLAG(UCAx##name, mask); \
+               else \
+                       return 0; \
+       } \
+       async command void Registers.set##name(uint8_t mask) { \
+               if (IS_USCI_Ax) \
+                       SET_FLAG(UCAx##name, mask); \
+       } \
+       async command void Registers.clr##name(uint8_t mask) { \
+               if (IS_USCI_Ax) \
+                       CLR_FLAG(UCAx##name, mask); \
+       } \
+       async command void Registers.assign##name(uint8_t value) { \
+               if (IS_USCI_Ax) \
+                       UCAx##name = value; \
+       }
+
+  #define RENDER_B(name) \
+       async command volatile uint8_t* Registers.ptr##name() { \
+               return &UCBx##name; \
+       } \
+       async command uint8_t Registers.get##name(uint8_t mask) { \
+               if (IS_USCI_Bx) \
+                       return READ_FLAG(UCBx##name, mask); \
+               else \
+                       return 0; \
+       } \
+       async command void Registers.set##name(uint8_t mask) { \
+               if (IS_USCI_Bx) \
+                       SET_FLAG(UCBx##name, mask); \
+       } \
+       async command void Registers.clr##name(uint8_t mask) { \
+               if (IS_USCI_Bx) \
+                       CLR_FLAG(UCBx##name, mask); \
+       } \
+       async command void Registers.assign##name(uint8_t value) { \
+               if (IS_USCI_Bx) \
+                       UCBx##name = value; \
+       }
+
+#if 0
+  MSP430REG_NORACE(UCxxCtl0);
+  MSP430REG_NORACE(UCxxCtl0);
+  MSP430REG_NORACE(UCxxCtl1);
+  MSP430REG_NORACE(UCxxBr0);
+  MSP430REG_NORACE(UCxxBr1);
+  MSP430REG_NORACE(UCAxMctl);
+  MSP430REG_NORACE(UCBxI2Cie);
+  MSP430REG_NORACE(UCxxStat);
+  MSP430REG_NORACE(UCxxRxbuf);
+  MSP430REG_NORACE(UCxxTxbuf);
+  MSP430REG_NORACE(UCAxAbctl);
+  MSP430REG_NORACE(UCAxIrtctl);
+  MSP430REG_NORACE(UCAxIrrctl);
+  MSP430REG_NORACE(UCBxI2Coa);
+  MSP430REG_NORACE(UCBxI2Csa);
+  MSP430REG_NORACE(UCxIe);
+  MSP430REG_NORACE(UCxIfg);
+#endif
+
+  async command msp430_usci_mode_t Registers.getMode()
+  {
+    if (READ_FLAG(UCxxCtl0, UCSYNC)) {
+      if (READ_FLAG(UCxxCtl0, UCMODE_3) == UCMODE_3)
+       return USCI_I2C;
+      else
+       return USCI_SPI;
+    } else {
+      return USCI_UART;
+    }
+  }
+
+  /* Doesn't really set the mode, but checks the mode for the device and inits
+   * the device.
+   */
+  async command bool Registers.setMode(msp430_usci_mode_t mode)
+  {
+    if (mode == USCI_UART && IS_USCI_Bx)
+      return FALSE;
+    if (mode == USCI_I2C && IS_USCI_Ax)
+      return FALSE;
+    SET_FLAG(UCxxCtl1, UCSWRST);
+    return TRUE;
+  }
+
+  RENDER(Ctl0);
+  RENDER(Ctl1);
+  RENDER(Br0);
+  RENDER(Br1);
+  RENDER_A(Mctl);
+  RENDER_B(I2Cie);
+  RENDER(Stat);
+
+  /* RENDER(Rxbuf); */
+  async command volatile uint8_t* Registers.ptrRxbuf()
+  {
+    return &UCxxRxbuf;
+  }
+
+  async command uint8_t Registers.getRxbuf()
+  {
+    return UCxxRxbuf;
+  }
+
+  /* RENDER(Txbuf); */
+  async command volatile uint8_t* Registers.ptrTxbuf()
+  {
+    return &UCxxTxbuf;
+  }
+
+  async command uint8_t Registers.getTxbuf()
+  {
+    return UCxxTxbuf;
+  }
+
+  async command void Registers.setTxbuf(uint8_t byte)
+  {
+    UCxxTxbuf = byte;
+  }
+
+  RENDER_A(Abctl);
+  RENDER_A(Irtctl);
+  RENDER_A(Irrctl);
+
+  /* RENDER_B(I2Coa); */
+  async command volatile uint8_t* Registers.ptrI2Coa()
+  {
+    return &UCBxI2Coa;
+  }
+
+  async command uint16_t Registers.readI2Coa()
+  {
+    return UCBxI2Coa;
+  }
+
+  async command void Registers.assignI2Coa(uint16_t addr)
+  {
+    UCBxI2Coa = addr;
+  }
+
+  /* RENDER_B(I2Csa); */
+  async command volatile uint8_t* Registers.ptrI2Csa()
+  {
+    return &UCBxI2Csa;
+  }
+
+  async command uint16_t Registers.readI2Csa()
+  {
+    return UCBxI2Csa;
+  }
+
+  async command void Registers.assignI2Csa(uint16_t addr)
+  {
+    UCBxI2Csa = addr;
+  }
+
+  /* RENDER(Ie); */
+  async command bool Registers.getIeRx()
+  {
+    return READ_FLAG(UCxxIe, UCxxRXIFG);
+  }
+
+  async command void Registers.setIeRx()
+  {
+    SET_FLAG(UCxxIe, UCxxRXIFG);
+  }
+
+  async command void Registers.clrIeRx()
+  {
+    CLR_FLAG(UCxxIe, UCxxRXIFG);
+  }
+
+  async command bool Registers.getIeTx()
+  {
+    return READ_FLAG(UCxxIe, UCxxTXIFG);
+  }
+
+  async command void Registers.setIeTx()
+  {
+    SET_FLAG(UCxxIe, UCxxTXIFG);
+  }
+
+  async command void Registers.clrIeTx()
+  {
+    CLR_FLAG(UCxxIe, UCxxTXIFG);
+  }
+
+  /* RENDER(Ifg); */
+  async command bool Registers.getIfgRx()
+  {
+    return READ_FLAG(UCxxIfg, UCxxRXIFG);
+  }
+
+  async command void Registers.clrIfgRx()
+  {
+    CLR_FLAG(UCxxIfg, UCxxRXIFG);
+  }
+
+  async command bool Registers.getIfgTx()
+  {
+    return READ_FLAG(UCxxIfg, UCxxTXIFG);
+  }
+
+  async command void Registers.clrIfgTx()
+  {
+    CLR_FLAG(UCxxIfg, UCxxTXIFG);
+  }
+}
diff --git a/tos/chips/msp430/usci/Msp430I2CB0C.nc b/tos/chips/msp430/usci/Msp430I2CB0C.nc
new file mode 100644 (file)
index 0000000..9b76c0f
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This configuration provides the interface for using USCI_B0 in its I2C
+ * mode.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#if !defined(__MSP430_HAS_USCI_AB0__)
+#error "Target does not have a USCI_B0 peripheral (I2C)"
+#endif
+
+#include "I2C.h"
+#include "Msp430Usci.h"
+
+generic configuration Msp430I2CB0C() {
+  provides {
+    interface Resource;
+    interface ResourceRequested;
+    /* interface SomethingToSetOwnAddress */
+    /* interface SomethingToDenoteMode */
+    interface I2CPacket<TI2CBasicAddr> as I2CBasicPacket;
+    interface I2CPacket<TI2CExtdAddr> as I2CExtdPacket;
+    interface ArbiterInfo; /* ??? */
+  }
+  uses interface AsyncConfigure<const msp430_usci_i2c_t*> as Configure;
+}
+implementation {
+  enum {
+    CLIENT_ID = unique(MSP430_USCIB0_RESOURCE)
+  };
+
+  components new Msp430I2CP() as I2CP;
+  I2CBasicPacket = I2CP;
+  I2CExtdPacket = I2CP;
+  Configure = I2CP;
+
+  components Msp430UsciB0C as UsciC;
+  Resource = UsciC.Resource[CLIENT_ID];
+  ResourceRequested = UsciC.ResourceRequested[CLIENT_ID];
+  ArbiterInfo = UsciC.ArbiterInfo;
+  I2CP -> UsciC.Registers;
+  I2CP -> UsciC.Interrupts[CLIENT_ID];
+  I2CP -> UsciC.ArbiterInfo;
+  UsciC.ResourceConfigure[CLIENT_ID] -> I2CP;
+
+  components HplMsp430GeneralIOC as IOC;
+  I2CP.SCL -> IOC.UCB0SCL;
+  I2CP.SDA -> IOC.UCB0SDA;
+
+#if 0 /* FIXME: no virtualized alarm for msp430 */
+  comonents new SomeVirtualizedAlarmClientC() as AlarmC;
+  I2CP.Alarm -> AlarmC;
+#endif
+
+  components BusyWaitMicroC;
+  I2CP.BusyWait -> BusyWaitMicroC;
+
+  components Msp430CounterMicroC;
+  I2CP.Counter -> Msp430CounterMicroC;
+}
diff --git a/tos/chips/msp430/usci/Msp430I2CB1C.nc b/tos/chips/msp430/usci/Msp430I2CB1C.nc
new file mode 100644 (file)
index 0000000..47cab8d
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This configuration provides the interface for using USCI_B1 in its I2C
+ * mode.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#if !defined(__MSP430_HAS_USCI_AB1__)
+#error "Target does not have a USCI_B1 peripheral (I2C)"
+#endif
+
+#include "I2C.h"
+#include "Msp430Usci.h"
+
+generic configuration Msp430I2CB1C() {
+  provides {
+    interface Resource;
+    interface ResourceRequested;
+    /* interface SomethingToSetOwnAddress */
+    /* interface SomethingToDenoteMode */
+    interface I2CPacket<TI2CBasicAddr> as I2CBasicPacket;
+    interface I2CPacket<TI2CExtdAddr> as I2CExtdPacket;
+    interface ArbiterInfo; /* ??? */
+  }
+  uses interface AsyncConfigure<const msp430_usci_i2c_t*> as Configure;
+}
+implementation {
+  enum {
+    CLIENT_ID = unique(MSP430_USCIB1_RESOURCE)
+  };
+
+  components new Msp430I2CP() as I2CP;
+  I2CBasicPacket = I2CP;
+  I2CExtdPacket = I2CP;
+  Configure = I2CP;
+
+  components Msp430UsciB1C as UsciC;
+  Resource = UsciC.Resource[CLIENT_ID];
+  ResourceRequested = UsciC.ResourceRequested[CLIENT_ID];
+  ArbiterInfo = UsciC.ArbiterInfo;
+  I2CP -> UsciC.Registers;
+  I2CP -> UsciC.Interrupts[CLIENT_ID];
+  I2CP -> UsciC.ArbiterInfo;
+  UsciC.ResourceConfigure[CLIENT_ID] -> I2CP;
+
+  components HplMsp430GeneralIOC as IOC;
+  I2CP.SCL -> IOC.UCB1SCL;
+  I2CP.SDA -> IOC.UCB1SDA;
+
+#if 0 /* FIXME: no virtualized alarm for msp430 */
+  comonents new SomeVirtualizedAlarmClientC() as AlarmC;
+  I2CP.Alarm -> AlarmC;
+#endif
+
+  components BusyWaitMicroC;
+  I2CP.BusyWait -> BusyWaitMicroC;
+
+  components Msp430CounterMicroC;
+  I2CP.Counter -> Msp430CounterMicroC;
+}
diff --git a/tos/chips/msp430/usci/Msp430I2CP.nc b/tos/chips/msp430/usci/Msp430I2CP.nc
new file mode 100644 (file)
index 0000000..8ce827d
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * USCI I2C implementation.  Currently supports only single master operation.
+ * Repeated start operations are supported, as are using multiple I2CPacket
+ * read or write commands to satisfy a single I2C read or write transaction.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic module Msp430I2CP() {
+  provides {
+    interface I2CPacket<TI2CBasicAddr> as I2CBasicPacket;
+    interface I2CPacket<TI2CExtdAddr> as I2CExtdPacket;
+    interface ResourceConfigure;
+  }
+  uses {
+    interface HplMsp430UsciReg as Registers;
+    interface HplMsp430UsciInt as Interrupts;
+    interface HplMsp430GeneralIO as SDA;
+    interface HplMsp430GeneralIO as SCL;
+    interface AsyncConfigure<const msp430_usci_i2c_t*> as Configure;
+    interface ArbiterInfo;
+    interface BusyWait<TMicro, uint16_t>;
+    interface Counter<TMicro, uint16_t>;
+  }
+}
+implementation {
+  enum {
+    /* Activity timing */
+    SCL_WAIT_TIME = 1024,      /* micros */
+    BUSY_CHECK_TIME = 1024,    /* micros */
+    START_CHECK_TIME = 102,    /* micros */
+    STOP_CHECK_TIME = 102,     /* micros */
+
+    /* Setting new I2C flags is dangerous; manually ensure the bit definitions
+     * below do not overlap with those defined in tos/types/I2C.h.
+     */
+    I2C_EXTENDED = 0x10,
+  };
+
+  i2c_flags_t m_flags;
+  uint8_t* m_buf;
+  uint16_t m_len;
+  uint16_t m_pos;
+
+  inline void setSDA()
+  {
+    call SDA.makeInput();
+  }
+
+  inline void clrSDA()
+  {
+    call SDA.makeOutput();
+  }
+
+  inline void setSCL()
+  {
+    call SCL.makeInput();
+  }
+
+  inline void clrSCL()
+  {
+    call SCL.makeOutput();
+  }
+
+  bool idleBus()
+  {
+    /* Look for bus idle when the I2C pins are in IO mode. */
+    return (call SDA.get() && call SCL.get());
+  }
+
+  bool resetBus()
+  {
+    /* When the I2C pins are in IO mode, verify the I2C bus is idle or attempt
+     * to get the bus into an idle state.  This code is only valid if we are
+     * the only master on the I2C bus and is not suitable for multi-master
+     * setups.
+     *
+     * Return TRUE if the bus was idle or was successfully brought to idle.
+     * Return FALSE if the bus could not be made idle in a reasonable time.
+     */
+    if (idleBus())
+      return TRUE;
+    else {
+      uint16_t i;
+
+      /* Wait a bit if SCL is low.  A save might be clock stretching. */
+      i = call Counter.get();
+      while (call Counter.get() - i <= SCL_WAIT_TIME) {
+       if (!(call SCL.get()))
+         return FALSE;
+      }
+
+      /* If SDA is low, clock SCL in an attempt to release it. */
+      for (i = 0; i < 10 && !call SDA.get(); i++) {
+       clrSCL();
+       call BusyWait.wait(10);
+       setSCL();
+       call BusyWait.wait(10);
+      }
+      if (!idleBus())
+       return FALSE;
+
+      /* Drive a stop condition on the bus to stop any active slaves. */
+      clrSCL();
+      clrSDA();
+      call BusyWait.wait(10);
+      setSCL();
+      call BusyWait.wait(10);
+      setSDA();
+      call BusyWait.wait(10);
+      return idleBus();
+    }
+  }
+
+  bool isConfigured()
+  {
+    return !(call Registers.getCtl1(UCSWRST));
+  }
+
+  /* TRUE if a transaction (we initiated, single master) is in progress. */
+  bool isBusy()
+  {
+    return m_len;
+  }
+
+  /* Wait for an I2C start, if in progress, to complete.  Return FALSE if a
+   * start is pending and did not finish within the allotted time.  Return TRUE
+   * if no start was pending, or it finished within the allotted time.
+   */
+  bool waitStart()
+  {
+    uint16_t t0 = call Counter.get();
+
+    do {
+      if (!(call Registers.getCtl1(UCTXSTT)))
+       return TRUE;
+    } while (call Counter.get() - t0 <= START_CHECK_TIME);
+    return FALSE;
+  }
+
+  /* Wait for an I2C stop, if in progress, to complete.  Return FALSE if a
+   * stop is pending and did not finish within the allotted time.  Return TRUE
+   * if no stop was pending, or it finished within the allotted time.
+   */
+  bool waitStop()
+  {
+    uint16_t t0 = call Counter.get();
+
+    do {
+      if (!(call Registers.getCtl1(UCTXSTP)))
+       return TRUE;
+    } while (call Counter.get() - t0 <= STOP_CHECK_TIME);
+    return FALSE;
+  }
+
+  async command void ResourceConfigure.configure()
+  {
+    atomic {
+      const msp430_usci_i2c_t* config = call Configure.get();
+
+      call Registers.setCtl1(UCSWRST);
+
+      /* Several conditions might find a slave driving the bus at this point.
+       * One such condition is a badly timed PUC of this slave.  Use resetBus()
+       * to attempt rectification of such conditions.
+       */
+      if (!resetBus())
+       return;
+
+      /* Configure USCI registers.  I2C requires UCMODE_3 and UCSYNC */
+      call Registers.assignCtl0(config->ctl0 | UCMODE_3 | UCSYNC);
+      call Registers.assignCtl1(config->ctl1 | UCSWRST);
+      call Registers.assignBr0(config->brx & 0xff);
+      call Registers.assignBr1(config->brx >> 8);
+      call Registers.assignMctl(0);
+      call Registers.assignI2Coa(config->i2coa);
+      call Registers.assignI2Csa(0);
+
+      /* Configure pins for I2C */
+      call SDA.selectModuleFunc();
+      call SCL.selectModuleFunc();
+
+      /* Clear interrupts; we'll add them as needed */
+      call Registers.assignI2Cie(0);
+      call Registers.clrIeRx();
+      call Registers.clrIeTx();
+
+      /* Enable the device */
+      call Registers.clrCtl1(UCSWRST);
+    }
+  }
+
+  void signalDone()
+  {
+    error_t error = (m_pos == m_len) ? SUCCESS : FAIL;
+    uint16_t len = m_len;
+    uint16_t addr;
+
+    /* No more I2C interrupts until the next I2C request arrives */
+    call Registers.assignI2Cie(0);
+    call Registers.clrIeTx();
+    call Registers.clrIeRx();
+
+    /* Wait for stop to finish, if it is in progress. */
+    if (!waitStop())
+      error = FAIL;
+
+    m_len = 0;
+    addr = call Registers.readI2Csa();
+    switch ((call Registers.getCtl0(UCSLA10) ? 2 : 0) +        /* extended addr */
+           (call Registers.getCtl1(UCTR) ? 1 : 0)) {   /* write */
+      case 0:
+       atomic signal I2CBasicPacket.readDone(error, addr, len, m_buf);
+       break;
+      case 1:
+       atomic signal I2CBasicPacket.writeDone(error, addr, len, m_buf);
+       break;
+      case 2:
+       atomic signal I2CExtdPacket.readDone(error, addr, len, m_buf);
+       break;
+      case 3:
+       atomic signal I2CExtdPacket.writeDone(error, addr, len, m_buf);
+       break;
+    }
+  }
+
+  async command void ResourceConfigure.unconfigure()
+  {
+    atomic {
+      /* Signal done if a pending operation */
+      if (isBusy())
+       signalDone();
+
+      /* Disable the device */
+      call Registers.setCtl1(UCSWRST);
+
+      /* Clear interrupts and interrupt flags. */
+      call Registers.assignI2Cie(0);
+      call Registers.clrIeRx();
+      call Registers.clrIfgRx();
+
+      /* Restore I2C pins to IO function */
+      call SDA.selectIOFunc();
+      call SCL.selectIOFunc();
+    }
+  }
+
+  error_t read(i2c_flags_t flags, uint16_t addr, uint8_t len, uint8_t* rxBuf)
+  {
+    /* From the TI family guide SDAU144D, page 17-17:
+     * "Data is received from the slave as long as UCTXSTP or UCTXSTT is not
+     * set.  If UCBxRXBUF is not read the master holds the bus during reception
+     * of the last data bit and until the UCBxRXBUF is read."
+     *
+     * Since the I2C bus can only be suspended during read by *not* reading a
+     * byte out of RXBUF, the only reasonable command after a read() that
+     * did not include I2C_STOP is a read that does not include I2C_START.  A
+     * read that includes I2C_START, or a write (which by definition must
+     * include I2C_START) will effectively create the situation where the
+     * prior read caused the slave to send one more byte than was delivered via
+     * readDone() to the user code.  In many cases, this won't be a problem, as
+     * triggering the slave to read an extra byte will do no harm.  But this
+     * may not always be the case, if for example the slave maintains state
+     * that is changed upon the read of that final byte the user code never
+     * sees.
+     */
+    if (!isConfigured() || isBusy() || len == 0 || !rxBuf)
+      return FAIL;
+
+    m_flags = flags;
+    m_len = len;
+    m_buf = rxBuf;
+    m_pos = 0;
+
+#if 0 /* FIXME: No virtualized alarm for msp430 */
+    /* We require an alarm because we aren't looking at UCALIFG, arbitration
+     * lost.  If this were to happen, the state machine hangs.
+     */
+    call Alarm.start(I2C_TIMEOUT);
+#endif
+    if (m_flags & I2C_EXTENDED)
+      call Registers.setCtl0(UCSLA10);
+    else
+      call Registers.clrCtl0(UCSLA10);
+    call Registers.assignI2Csa(addr);
+    call Registers.clrCtl1(UCTR);
+    if (m_flags & I2C_START) {
+      call Registers.clrIfgRx(); /* see above re: suspending reads */
+      call Registers.setCtl1(UCTXSTT);
+    }
+    if (m_len == 1 && (m_flags & I2C_STOP)) {
+      /* UCTXSTP must assert before hw finishes clocking in the last byte.
+       * FIXME: in reading a single I2C trx using multiple I2C...read() calls,
+       * too much time spent by the user processing the readDone() can cause
+       * the I2C hardware to clock an extra byte's worth of clocks, thereby
+       * issuing 1 byte more of read with the slave, before the stop event.
+       */
+      waitStart();
+      call Registers.setCtl1(UCTXSTP);
+    }
+    call Registers.setI2Cie(UCNACKIE);
+    call Registers.setIeRx();
+    return SUCCESS;
+  }
+
+  async command error_t I2CBasicPacket.read(i2c_flags_t flags, uint16_t addr,
+      uint8_t length, uint8_t* data)
+  {
+    atomic return read(flags & ~I2C_EXTENDED, addr, length, data);
+  }
+
+  async command error_t I2CExtdPacket.read(i2c_flags_t flags, uint16_t addr,
+      uint8_t length, uint8_t* data)
+  {
+    atomic return read(flags | I2C_EXTENDED, addr, length, data);
+  }
+
+  error_t write(i2c_flags_t flags, uint16_t addr, uint8_t len, uint8_t* txBuf)
+  {
+    if (!isConfigured() || isBusy() || len == 0 || !txBuf)
+      return FAIL;
+
+    m_flags = flags;
+    m_len = len;
+    m_buf = txBuf;
+    m_pos = 0;
+
+#if 0 /* FIXME: No virtualized alarm for msp430 */
+    /* We require an alarm because we aren't looking at UCALIFG, arbitration
+     * lost.  If this were to happen, the state machine hangs.
+     */
+    call Alarm.start(I2C_TIMEOUT);
+#endif
+    if (m_flags & I2C_EXTENDED)
+      call Registers.setCtl0(UCSLA10);
+    else
+      call Registers.clrCtl0(UCSLA10);
+    call Registers.assignI2Csa(addr);
+    call Registers.setCtl1((m_flags & I2C_START) ? UCTR + UCTXSTT : UCTR);
+    call Registers.setI2Cie(UCNACKIE);
+    call Registers.setIeTx();
+    return SUCCESS;
+  }
+
+  async command error_t I2CBasicPacket.write(i2c_flags_t flags, uint16_t addr,
+      uint8_t length, uint8_t* data)
+  {
+    atomic return write(flags & ~I2C_EXTENDED, addr, length, data);
+  }
+
+  async command error_t I2CExtdPacket.write(i2c_flags_t flags, uint16_t addr,
+      uint8_t length, uint8_t* data)
+  {
+    atomic return write(flags | I2C_EXTENDED, addr, length, data);
+  }
+
+#if 0 /* FIXME: need a virtualized alarm for msp430 */
+  event void Alarm.fired()
+  {
+    if (m_flags & I2C_STOP) {
+      call Registers.setCtl1(UCTXSTP);
+      call Registers.clrIfgTx();
+    }
+    signalDone();
+  }
+#endif
+
+  async event void Interrupts.tx()
+  {
+    if (m_pos == m_len) {
+      if (m_flags & I2C_STOP) {
+       call Registers.setCtl1(UCTXSTP);
+       call Registers.clrIfgTx();
+      }
+      signalDone();
+    } else
+      call Registers.setTxbuf(m_buf[m_pos++]);
+  }
+
+  async event void Interrupts.rx(uint8_t nobyte)
+  {
+    if (m_len - m_pos == 2 && (m_flags & I2C_STOP)) {
+      /* As soon as we read RXBUF, the hw will begin clocking in the next byte.
+       * To guarantee that a slow uC can still set UCTXSTP before the last
+       * byte is fully clocked, we set it before the second to last byte is
+       * read from RXBUF, when the hw has I2C communications suspended.
+       */
+      call Registers.setCtl1(UCTXSTP);
+    }
+    m_buf[m_pos++] = call Registers.getRxbuf();
+    if (m_pos == m_len)
+      signalDone();
+  }
+
+  async event void Interrupts.i2cNack()
+  {
+    call Registers.setCtl1(UCTXSTP);
+    call Registers.clrStat(UCNACKIFG);
+    signalDone();
+  }
+
+  default async event void I2CBasicPacket.readDone(error_t error, uint16_t addr,
+      uint8_t length, uint8_t* data) {}
+  default async event void I2CBasicPacket.writeDone(error_t error,
+      uint16_t addr, uint8_t length, uint8_t* data) {}
+  default async event void I2CExtdPacket.readDone(error_t error, uint16_t addr,
+      uint8_t length, uint8_t* data) {}
+  default async event void I2CExtdPacket.writeDone(error_t error, uint16_t addr,
+      uint8_t length, uint8_t* data) {}
+
+  default async command const msp430_usci_i2c_t* Configure.get()
+  {
+    const static msp430_usci_i2c_t def = {
+      ctl0: UCSYNC | UCMODE_3 | UCMST, /* I2C master */
+      ctl1: UCSWRST | UCSSEL_3,                /* I2C clock source is SMCLK */
+      brx: 10,                 /* I2C clock=SMCLK/10; ~95KHz if SMCLK=2^20Hz */
+      ren: USCI_REN_NONE
+    };
+
+    return &def;
+  }
+
+  async event void Interrupts.i2cStart() {}
+  async event void Interrupts.i2cStop() {}
+  async event void Interrupts.i2cCal() {}
+  async event void Interrupts.brk() {}
+  async event void Counter.overflow() {}
+}
diff --git a/tos/chips/msp430/usci/Msp430SpiA0C.nc b/tos/chips/msp430/usci/Msp430SpiA0C.nc
new file mode 100644 (file)
index 0000000..b3c284f
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This configuration provides the interface for using USCI_A0 in its SPI
+ * mode.
+ *
+ * The instantiator should set the blockSize, which represents the maximum
+ * number of bytes the underlying SPI stack will transmit or receive in a
+ * single interrupt service.  Increasing the block size decreases SPI
+ * communications time at the expense of reducing system responsiveness to
+ * other events.
+ *
+ * The blockSize is best set by considering the maximum time the SPI stack
+ * should be able to delay other events.  A rule of thumb formula would be:
+ *
+ * block_time = block_size / (spi_bitclock/8)
+ *
+ * For example, using a 500KHZ SPI bitclock, a block size of 64 bytes
+ * equates to a block time of 1 ms.  Note that this calculation is rough
+ * because it does not take into account ISR overhead and other factors.
+ *
+ * The implementation will use a default blockSize if set to 0 here.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#if !defined(__MSP430_HAS_USCI_AB0__)
+#error "Target does not have a USCI_A0 peripheral (SPI)"
+#endif
+
+#include "Msp430Usci.h"
+
+generic configuration Msp430SpiA0C(uint16_t blockSize) {
+  provides {
+    interface Resource;
+    interface ResourceRequested;
+    interface SpiByte;
+    interface SpiPacket;
+    interface ArbiterInfo; /* ??? */
+  }
+  uses {
+    interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+    interface GeneralIO as CSn;        /* wire only if a SPI slave only */
+  }
+}
+implementation {
+  enum {
+    CLIENT_ID = unique(MSP430_USCIA0_RESOURCE)
+  };
+
+  components new Msp430SpiP(blockSize) as SpiP;
+  SpiByte = SpiP;
+  SpiPacket = SpiP;
+  Configure = SpiP;
+  CSn = SpiP;
+
+  components Msp430UsciA0C as UsciC;
+  Resource = UsciC.Resource[CLIENT_ID];
+  ResourceRequested = UsciC.ResourceRequested[CLIENT_ID];
+  ArbiterInfo = UsciC.ArbiterInfo;
+  SpiP -> UsciC.Registers;
+  SpiP -> UsciC.Interrupts[CLIENT_ID];
+  SpiP -> UsciC.ArbiterInfo;
+  UsciC.ResourceConfigure[CLIENT_ID] -> SpiP;
+
+  components HplMsp430GeneralIOC as IOC;
+  SpiP.STE -> IOC.UCA0STE;
+  SpiP.SIMO -> IOC.UCA0SIMO;
+  SpiP.SOMI -> IOC.UCA0SOMI;
+  SpiP.CLK -> IOC.UCA0CLK;
+}
diff --git a/tos/chips/msp430/usci/Msp430SpiB0C.nc b/tos/chips/msp430/usci/Msp430SpiB0C.nc
new file mode 100644 (file)
index 0000000..8da9619
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This configuration provides the interface for using USCI_B0 in its SPI
+ * mode.
+ *
+ * The instantiator should set the blockSize, which represents the maximum
+ * number of bytes the underlying SPI stack will transmit or receive in a
+ * single interrupt service.  Increasing the block size decreases SPI
+ * communications time at the expense of reducing system responsiveness to
+ * other events.
+ *
+ * The blockSize is best set by considering the maximum time the SPI stack
+ * should be able to delay other events.  A rule of thumb formula would be:
+ *
+ * block_time = block_size / (spi_bitclock/8)
+ *
+ * For example, using a 500KHZ SPI bitclock, a block size of 64 bytes
+ * equates to a block time of 1 ms.  Note that this calculation is rough
+ * because it does not take into account ISR overhead and other factors.
+ *
+ * The implementation will use a default blockSize if set to 0 here.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#if !defined(__MSP430_HAS_USCI_AB0__)
+#error "Target does not have a USCI_B0 peripheral (SPI)"
+#endif
+
+#include "Msp430Usci.h"
+
+generic configuration Msp430SpiB0C(uint16_t blockSize) {
+  provides {
+    interface Resource;
+    interface ResourceRequested;
+    interface SpiByte;
+    interface SpiPacket;
+    interface ArbiterInfo; /* ??? */
+  }
+  uses {
+    interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+    interface GeneralIO as CSn;        /* wire only if a SPI slave only */
+  }
+}
+implementation {
+  enum {
+    CLIENT_ID = unique(MSP430_USCIB0_RESOURCE)
+  };
+
+  components new Msp430SpiP(blockSize) as SpiP;
+  SpiByte = SpiP;
+  SpiPacket = SpiP;
+  Configure = SpiP;
+  CSn = SpiP;
+
+  components Msp430UsciB0C as UsciC;
+  Resource = UsciC.Resource[CLIENT_ID];
+  ResourceRequested = UsciC.ResourceRequested[CLIENT_ID];
+  ArbiterInfo = UsciC.ArbiterInfo;
+  SpiP -> UsciC.Registers;
+  SpiP -> UsciC.Interrupts[CLIENT_ID];
+  SpiP -> UsciC.ArbiterInfo;
+  UsciC.ResourceConfigure[CLIENT_ID] -> SpiP;
+
+  components HplMsp430GeneralIOC as IOC;
+  SpiP.STE -> IOC.UCB0STE;
+  SpiP.SIMO -> IOC.UCB0SIMO;
+  SpiP.SOMI -> IOC.UCB0SOMI;
+  SpiP.CLK -> IOC.UCB0CLK;
+}
diff --git a/tos/chips/msp430/usci/Msp430SpiB1C.nc b/tos/chips/msp430/usci/Msp430SpiB1C.nc
new file mode 100644 (file)
index 0000000..f06cc41
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This configuration provides the interface for using USCI_B1 in its SPI
+ * mode.
+ *
+ * The instantiator should set the blockSize, which represents the maximum
+ * number of bytes the underlying SPI stack will transmit or receive in a
+ * single interrupt service.  Increasing the block size decreases SPI
+ * communications time at the expense of reducing system responsiveness to
+ * other events.
+ *
+ * The blockSize is best set by considering the maximum time the SPI stack
+ * should be able to delay other events.  A rule of thumb formula would be:
+ *
+ * block_time = block_size / (spi_bitclock/8)
+ *
+ * For example, using a 500KHZ SPI bitclock, a block size of 64 bytes
+ * equates to a block time of 1 ms.  Note that this calculation is rough
+ * because it does not take into account ISR overhead and other factors.
+ *
+ * The implementation will use a default blockSize if set to 0 here.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#if !defined(__MSP430_HAS_USCI_AB1__)
+#error "Target does not have a USCI_B1 peripheral (SPI)"
+#endif
+
+#include "Msp430Usci.h"
+
+generic configuration Msp430SpiB1C(uint16_t blockSize) {
+  provides {
+    interface Resource;
+    interface ResourceRequested;
+    interface SpiByte;
+    interface SpiPacket;
+    interface ArbiterInfo; /* ??? */
+  }
+  uses {
+    interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+    interface GeneralIO as CSn;        /* wire only if a SPI slave only */
+  }
+}
+implementation {
+  enum {
+    CLIENT_ID = unique(MSP430_USCIB1_RESOURCE)
+  };
+
+  components new Msp430SpiP(blockSize) as SpiP;
+  SpiByte = SpiP;
+  SpiPacket = SpiP;
+  Configure = SpiP;
+  CSn = SpiP;
+
+  components Msp430UsciB1C as UsciC;
+  Resource = UsciC.Resource[CLIENT_ID];
+  ResourceRequested = UsciC.ResourceRequested[CLIENT_ID];
+  ArbiterInfo = UsciC.ArbiterInfo;
+  SpiP -> UsciC.Registers;
+  SpiP -> UsciC.Interrupts[CLIENT_ID];
+  SpiP -> UsciC.ArbiterInfo;
+  UsciC.ResourceConfigure[CLIENT_ID] -> SpiP;
+
+  components HplMsp430GeneralIOC as IOC;
+  SpiP.STE -> IOC.UCB1STE;
+  SpiP.SIMO -> IOC.UCB1SIMO;
+  SpiP.SOMI -> IOC.UCB1SOMI;
+  SpiP.CLK -> IOC.UCB1CLK;
+}
diff --git a/tos/chips/msp430/usci/Msp430SpiP.nc b/tos/chips/msp430/usci/Msp430SpiP.nc
new file mode 100644 (file)
index 0000000..93b9422
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * 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
+ *
+ * NOTE: Define NO_REN_ON_SPI to disable PxREN bits when SPI is acquired.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic module Msp430SpiP(uint16_t blockSize) {
+  provides {
+    interface SpiByte;
+    interface SpiPacket;
+    interface ResourceConfigure;
+  }
+  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;
+    interface HplMsp430GeneralIO as CLK;
+    interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+    interface ArbiterInfo;
+  }
+}
+implementation {
+  enum {
+    BLOCKSIZE_DEFAULT = 64,
+
+    /* Bit positions in m_pins */
+    PINS_STE = 0,
+    PINS_SOMI,
+    PINS_SIMO,
+    PINS_CLK,
+#ifdef NO_REN_ON_SPI
+    PINS_RENADDR,      /* This gets added to store the PxREN bit */
+#endif
+  };
+
+  uint8_t m_pins;
+  norace uint8_t* m_txBuf;
+  norace uint8_t* m_rxBuf;
+  norace uint16_t m_len;
+  norace uint16_t m_pos;
+
+  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 */
+  {
+    atomic return m_len != 0;
+  }
+
+  async command void ResourceConfigure.configure()
+  {
+    atomic {
+      const msp430_usci_spi_t* config = call Configure.get();
+      uint8_t ctl0;
+
+      call Registers.setCtl1(UCSWRST);
+
+      /* UCMODE_3 is invalid for SPI.  Presume the configuration data
+       * are wrong and force 3-pin SPI as a minimially safe alternative.
+       */
+      ctl0 = config->ctl0 | UCSYNC;
+      if ((ctl0 & UCMODE_3) == UCMODE_3)
+       ctl0 &= ~(UCMODE_3);
+
+      /* Configure USCI registers */
+      call Registers.assignCtl0(ctl0);
+      call Registers.assignCtl1(config->ctl1 | UCSWRST);
+      call Registers.assignBr0(config->brx & 0xff);
+      call Registers.assignBr1(config->brx >> 8);
+      call Registers.assignMctl(0);
+      if (config->uclisten)
+       call Registers.setStat(UCLISTEN);
+      else
+       call Registers.clrStat(UCLISTEN);
+
+      /* Configure pins for SPI, saving prior pin states */
+      m_pins = 0;
+#ifdef NO_REN_ON_SPI
+      /* - First save off and disable PxREN bits */
+      if (is4pin() && call STE.isRen()) {
+       m_pins |= (1 << (PINS_STE + PINS_RENADDR));
+       call STE.disableRen();
+      }
+      if (call SOMI.isRen()) {
+       m_pins |= (1 << (PINS_SOMI + PINS_RENADDR));
+       call SOMI.disableRen();
+      }
+      if (call SIMO.isRen()) {
+       m_pins |= (1 << (PINS_SIMO + PINS_RENADDR));
+       call SIMO.disableRen();
+      }
+      if (call CLK.isRen()) {
+       m_pins |= (1 << (PINS_CLK + PINS_RENADDR));
+       call CLK.disableRen();
+      }
+#endif
+      /* - Then save off IOFunc state and enable ModuleFunc */
+      if (is4pin() && call STE.isIOFunc()) {
+       m_pins |= (1 << PINS_STE);
+       call STE.selectModuleFunc();
+      }
+      if (call SOMI.isIOFunc()) {
+       m_pins |= (1 << PINS_SOMI);
+       call SOMI.selectModuleFunc();
+      }
+      if (call SIMO.isIOFunc()) {
+       m_pins |= (1 << PINS_SIMO);
+       call SIMO.selectModuleFunc();
+      }
+      if (call CLK.isIOFunc()) {
+       m_pins |= (1 << PINS_CLK);
+       call CLK.selectModuleFunc();
+      }
+
+      /* Clear interrupts; we'll add them as needed */
+      call Registers.clrIeRx();
+      call Registers.clrIeTx();
+
+      /* Enable the device */
+      call Registers.clrCtl1(UCSWRST);
+    }
+  }
+
+  task void signalSendDone()
+  {
+    error_t error = (m_pos == m_len) ? SUCCESS : FAIL;
+
+    m_len = 0;
+    atomic signal SpiPacket.sendDone(m_txBuf, m_rxBuf, m_pos, error);
+  }
+
+  async command void ResourceConfigure.unconfigure()
+  {
+    atomic {
+      /* Disable the device */
+      call Registers.setCtl1(UCSWRST);
+
+      /* Ensure SpiPacket.sendDone is posted if a trx was in progress */
+      if (m_len)
+       post signalSendDone();
+
+      /* Clear interrupts and interrupt flags.  We only used Rx */
+      call Registers.clrIeRx();
+      call Registers.clrIfgRx();
+
+      /* Restore pins to their pre-configure state */
+      /* - First restore IOFunc states */
+      if (is4pin() && (m_pins & (1 << PINS_STE)))
+       call STE.selectIOFunc();
+      if (m_pins & (1 << PINS_SIMO))
+       call SIMO.selectIOFunc();
+      if (m_pins & (1 << PINS_SOMI))
+       call SOMI.selectIOFunc();
+      if (m_pins & (1 << PINS_CLK))
+       call CLK.selectIOFunc();
+      /* - Then restore PxREN bits */
+#ifdef NO_REN_ON_SPI
+      if (is4pin() && (m_pins & (1 << (PINS_STE + PINS_RENADDR))))
+       call STE.enableRen();
+      if (m_pins & (1 << (PINS_SIMO + PINS_RENADDR)))
+       call SIMO.enableRen();
+      if (m_pins & (1 << (PINS_SOMI + PINS_RENADDR)))
+       call SOMI.enableRen();
+      if (m_pins & (1 << (PINS_CLK + PINS_RENADDR)))
+       call CLK.enableRen();
+#endif
+    }
+  }
+
+  bool waitOnRx()
+  {
+    for (;;) {
+      if (call Registers.getIfgRx())
+       return TRUE;
+      if (call CSn.get())              /* SPI master has unselected us */
+       return FALSE;
+    }
+  }
+
+  bool waitOnTx()
+  {
+    for (;;) {
+      if (call Registers.getIfgTx())
+       return TRUE;
+      if (call CSn.get())              /* SPI master has unselected us */
+       return FALSE;
+    }
+  }
+
+  async command uint8_t SpiByte.write(uint8_t byte)
+  {
+    atomic {
+      if (isBusy())
+       return 0;
+      else {
+       waitOnTx();
+       call Registers.setTxbuf(byte);
+       waitOnRx();
+       return call Registers.getRxbuf();
+      }
+    }
+  }
+
+  /* If we are a slave, return FALSE if the master has unasserted CSn. */
+  bool sendData()
+  {
+    atomic {
+      uint16_t end = m_pos + (blockSize ? blockSize : BLOCKSIZE_DEFAULT);
+      uint8_t tmp;
+
+      if (end > m_len)
+       end = m_len;
+      waitOnTx(); /* Don't assume that the last tx is done already */
+      call Registers.setTxbuf(m_txBuf ? m_txBuf[m_pos] : 0);
+      while (++m_pos < end) {
+       waitOnRx();
+       tmp = call Registers.getRxbuf();
+       if (m_rxBuf)
+         m_rxBuf[m_pos - 1] = tmp;
+       waitOnTx();
+       call Registers.setTxbuf(m_txBuf ? m_txBuf[m_pos] : 0);
+      }
+      return call CSn.get() ? FALSE : TRUE;
+    }
+  }
+
+  async command error_t SpiPacket.send(uint8_t* txBuf, uint8_t* rxBuf,
+      uint16_t len)
+  {
+    if (isBusy() || (!txBuf && !rxBuf) || len == 0)
+      return FAIL;
+    else {
+      m_txBuf = txBuf;
+      m_rxBuf = rxBuf;
+      m_len = len;
+      m_pos = 0;
+      if (sendData())
+       call Registers.setIeRx();
+      else
+       post signalSendDone();
+      return SUCCESS;
+    }
+  }
+
+  async event void Interrupts.tx() {}
+
+  async event void Interrupts.rx(uint8_t byte)
+  {
+    if (m_rxBuf)
+      m_rxBuf[m_pos - 1] = byte;
+
+    if (m_pos < m_len) {
+      if (sendData())
+       return;
+    }
+    call Registers.clrIeRx();
+    post signalSendDone();
+  }
+
+  default async event void SpiPacket.sendDone(uint8_t*, uint8_t*, uint16_t,
+      error_t) {}
+
+  default async command const msp430_usci_spi_t* Configure.get()
+  {
+    const static msp430_usci_spi_t def = {
+      ctl0: UCSYNC | UCMODE_0 | UCMST, /* 3-pin SPI mode 0, LSB first */
+      ctl1: UCSWRST | UCSSEL_3,                /* SPI clock source is SMCLK */
+      brx: 10,                 /* SPI clock=SMCLK/10; ~105KHz if SMCLK=1MHz */
+      uclisten: FALSE,
+      ren: USCI_REN_NONE
+    };
+
+    return &def;
+  }
+
+  async event void Interrupts.i2cStart() {}
+  async event void Interrupts.i2cStop() {}
+  async event void Interrupts.i2cCal() {}
+  async event void Interrupts.brk() {}
+  async event void Interrupts.i2cNack() {}
+
+  default async command bool CSn.get() { return FALSE; }
+}
diff --git a/tos/chips/msp430/usci/Msp430UartA0C.nc b/tos/chips/msp430/usci/Msp430UartA0C.nc
new file mode 100644 (file)
index 0000000..bbdf8a4
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This configuration provides the interface for using USCI_A0 in its UART
+ * mode.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#if !defined(__MSP430_HAS_USCI_AB0__)
+#error "Target does not have a USCI_A0 peripheral (UART)"
+#endif
+
+#include "Msp430Usci.h"
+
+generic configuration Msp430UartA0C() {
+  provides {
+    interface Resource;
+    interface ResourceRequested;
+    interface UartStream;
+    interface UartByte;
+    interface ArbiterInfo; /* ??? */
+  }
+  uses interface AsyncConfigure<const msp430_usci_uart_t*> as Configure;
+}
+implementation {
+  enum {
+    CLIENT_ID = unique(MSP430_USCIA0_RESOURCE)
+  };
+
+  components new Msp430UartP() as UartP;
+  UartStream = UartP;
+  UartByte = UartP;
+  Configure = UartP;
+
+  components Msp430UsciA0C as UsciC;
+  Resource = UsciC.Resource[CLIENT_ID];
+  ResourceRequested = UsciC.ResourceRequested[CLIENT_ID];
+  ArbiterInfo = UsciC.ArbiterInfo;
+  UartP -> UsciC.Registers;
+  UartP -> UsciC.Interrupts[CLIENT_ID];
+  UartP -> UsciC.ArbiterInfo;
+  UsciC.ResourceConfigure[CLIENT_ID] -> UartP;
+
+  components HplMsp430GeneralIOC as IOC;
+  UartP.RXD -> IOC.UCA0RXD;
+  UartP.TXD -> IOC.UCA0TXD;
+}
diff --git a/tos/chips/msp430/usci/Msp430UartA1C.nc b/tos/chips/msp430/usci/Msp430UartA1C.nc
new file mode 100644 (file)
index 0000000..67a917c
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This configuration provides the interface for using USCI_A1 in its UART
+ * mode.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#if !defined(__MSP430_HAS_USCI_AB0__)
+#error "Target does not have a USCI_A1 peripheral (UART)"
+#endif
+
+#include "Msp430Usci.h"
+
+generic configuration Msp430UartA1C() {
+  provides {
+    interface Resource;
+    interface ResourceRequested;
+    interface UartStream;
+    interface UartByte;
+    interface ArbiterInfo; /* ??? */
+  }
+  uses interface AsyncConfigure<const msp430_usci_uart_t*> as Configure;
+}
+implementation {
+  enum {
+    CLIENT_ID = unique(MSP430_USCIA1_RESOURCE)
+  };
+
+  components new Msp430UartP() as UartP;
+  UartStream = UartP;
+  UartByte = UartP;
+  Configure = UartP;
+
+  components Msp430UsciA1C as UsciC;
+  Resource = UsciC.Resource[CLIENT_ID];
+  ResourceRequested = UsciC.ResourceRequested[CLIENT_ID];
+  ArbiterInfo = UsciC.ArbiterInfo;
+  UartP -> UsciC.Registers;
+  UartP -> UsciC.Interrupts[CLIENT_ID];
+  UartP -> UsciC.ArbiterInfo;
+  UsciC.ResourceConfigure[CLIENT_ID] -> UartP;
+
+  components HplMsp430GeneralIOC as IOC;
+  UartP.RXD -> IOC.UCA1RXD;
+  UartP.TXD -> IOC.UCA1TXD;
+}
diff --git a/tos/chips/msp430/usci/Msp430UartP.nc b/tos/chips/msp430/usci/Msp430UartP.nc
new file mode 100644 (file)
index 0000000..4821f7b
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Uart implementation using a USCI device.
+ *
+ * TODO: Implement blocking like in Msp430UartSpiP.nc.
+ *       Implement error checking via UCAxSTAT.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic module Msp430UartP() {
+  provides {
+    interface UartStream;
+    interface UartByte;
+    interface ResourceConfigure;
+  }
+  uses {
+    interface HplMsp430UsciReg as Registers;
+    interface HplMsp430UsciInt as Interrupts;
+    interface HplMsp430GeneralIO as RXD;
+    interface HplMsp430GeneralIO as TXD;
+    interface AsyncConfigure<const msp430_usci_uart_t*> as Configure;
+    interface Counter<T32khz,uint16_t>;
+    interface ArbiterInfo;
+  }
+}
+implementation {
+  enum {
+    /* Bit positions in m_pins */
+    PINS_RXD = 0,
+    PINS_TXD
+  };
+
+  uint8_t m_pins;
+  uint8_t* m_sobuf;    /* Original buffer ptr from UartStream.send() */
+  uint16_t m_solen;    /* Original buffer len from UartStream.send() */
+  uint8_t* m_sbuf;     /* Position of next char to send */
+  uint16_t m_slen;     /* Len of chars in m_sbuf to send */
+  bool m_rxie;         /* Set if rxie has been enabled to UartStream.receive() */
+  uint8_t* m_robuf;    /* Original receive buffer */
+  uint16_t m_rolen;    /* Original (maximum) receive len */
+  uint8_t* m_rbuf;     /* Position of next byte in which to receive a char */
+  uint16_t m_rlen;     /* Remaining length in receive buffer */
+
+  sfrb(MYBRX, 219U);
+
+  async command void ResourceConfigure.configure()
+  {
+    atomic {
+      const msp430_usci_uart_t* config = call Configure.get();
+
+      call Registers.setCtl1(UCSWRST);
+
+      /* Configure USCI registers */
+      call Registers.assignCtl0(config->ctl0 & ~UCSYNC);
+      call Registers.assignCtl1(config->ctl1 | UCSWRST);
+      call Registers.assignBr0(config->brx & 0xff);
+      call Registers.assignBr1(config->brx >> 8);
+      call Registers.assignMctl(config->mctl);
+      call Registers.assignIrtctl(config->irtctl);
+      call Registers.assignIrrctl(config->irrctl);
+      call Registers.assignAbctl(config->abctl);
+      if (config->uclisten)
+       call Registers.setStat(UCLISTEN);
+      else
+       call Registers.clrStat(UCLISTEN);
+
+      /* Configure pins for UART, saving prior pin states */
+      m_pins = 0;
+      if (call RXD.isIOFunc()) {
+       m_pins |= (1 << PINS_RXD);
+       call RXD.selectModuleFunc();
+      }
+      if (call TXD.isIOFunc()) {
+       m_pins |= (1 << PINS_TXD);
+       call TXD.selectModuleFunc();
+      }
+
+      /* Reset important state variables */
+      m_robuf = 0;
+      m_sobuf = 0;
+
+      /* Clear interrupts; we'll add them as needed */
+      call Registers.clrIeRx();
+      call Registers.clrIeTx();
+
+      /* Enable the device */
+      call Registers.clrCtl1(UCSWRST);
+
+      /* TOS convention is for receive interrupts on by default. */
+      call Registers.clrIfgRx();
+      call Registers.setIeRx();
+    }
+  }
+
+  async command void ResourceConfigure.unconfigure()
+  {
+    atomic {
+      /* Disable the device */
+      call Registers.setCtl1(UCSWRST);
+
+      /* Clear interrupts and interrupt flags */
+      call Registers.clrIeRx();
+      call Registers.clrIeTx();
+      call Registers.clrIfgRx();
+
+      /* Reset important state variables */
+      m_robuf = 0;
+      m_sobuf = 0;
+
+      /* Restore pins to their pre-configure state */
+      if (m_pins & (1 << PINS_RXD))
+       call RXD.selectIOFunc();
+      if (m_pins & (1 << PINS_TXD))
+       call TXD.selectIOFunc();
+    }
+  }
+
+  async command error_t UartByte.send(uint8_t byte)
+  {
+    atomic {
+      while (!call Registers.getIfgTx());
+      call Registers.setTxbuf(byte);
+      return SUCCESS;
+    }
+  }
+
+  async command error_t UartStream.send(uint8_t* buf, uint16_t len)
+  {
+    atomic {
+      if (m_sobuf || !buf || !len)
+       return FAIL;
+      m_sbuf = m_sobuf = buf;
+      m_slen = m_solen = len;
+      call Registers.setIeTx();
+      return SUCCESS;
+    }
+  }
+
+  async event void Interrupts.tx()
+  {
+    /* FIXME: this can cause an arbitrarily long ISR, if m_slen is large.
+     * But depending on timing, we may always only write 1 byte.
+     */
+    if (m_sobuf) {
+      while (!call Registers.getIfgTx()); /* in case interleaved UB.send */
+      while (m_slen && call Registers.getIfgTx()) {
+       call Registers.setTxbuf(*m_sbuf);
+       if (--m_slen)
+         m_sbuf++;
+      }
+      if (m_slen == 0) {
+       call Registers.clrIeTx();
+       m_sobuf = 0;
+       signal UartStream.sendDone(m_sobuf, m_solen, SUCCESS);
+      }
+    }
+  }
+
+  async command error_t UartStream.enableReceiveInterrupt()
+  {
+    atomic {
+      if (!m_robuf)
+       call Registers.clrIfgRx();
+      call Registers.setIeRx();
+      m_rxie = FALSE;
+      return SUCCESS;
+    }
+  }
+
+  async command error_t UartStream.disableReceiveInterrupt()
+  {
+    atomic {
+      if (!m_robuf) {
+       call Registers.clrIeRx();
+       call Registers.clrIfgRx();
+      } else
+       m_rxie = TRUE;
+      return SUCCESS;
+    }
+  }
+
+  async command error_t UartByte.receive(uint8_t* byte, uint8_t timeout)
+  {
+    atomic {
+      uint16_t t;
+
+      /* FIXME: race with UartStream.receive() */
+      if (m_robuf || !byte)
+       return FAIL;
+      /* TODO: implement timeout, byte-time units.  For now, 1-2 sec */
+      t = TBR;
+      while (t < TBR) {
+       if (call Registers.getIfgRx()) {
+         *byte = call Registers.getRxbuf();
+         return SUCCESS;
+       }
+      }
+      return FAIL;
+    }
+  }
+
+  async command error_t UartStream.receive(uint8_t* buf, uint16_t len)
+  {
+    atomic {
+      if (m_robuf || !buf || !len)
+       return FAIL;
+      m_robuf = m_rbuf = buf;
+      m_rolen = m_rlen = len;
+      if (!call Registers.getIeRx()) {
+       call Registers.clrIfgRx();
+       call Registers.setIeRx();
+       m_rxie = TRUE;
+      } else
+       m_rxie = FALSE;
+    }
+  }
+
+  async event void Interrupts.rx(uint8_t byte)
+  {
+    if (m_robuf) {
+      /* receive() takes precedence if active */
+      /* FIXME: an arbitrarily long ISR may occur if m_rlen is large.
+       * But depending on timing, we may always only read 1 byte.
+       */
+      while (m_rlen && call Registers.getIfgRx()) {
+       *m_rbuf = byte;
+       if (--m_rlen)
+         m_rbuf++;
+      }
+      if (m_rlen == 0 && m_robuf) {
+       if (m_rxie) {
+         call Registers.clrIeRx();
+         call Registers.clrIfgRx();
+       }
+       m_robuf = 0;
+       signal UartStream.receiveDone(m_robuf, m_rolen, SUCCESS);
+      }
+    } else
+      signal UartStream.receivedByte(byte);
+  }
+
+  default async command const msp430_usci_uart_t* Configure.get()
+  {
+    const static msp430_usci_uart_t def = {
+      ctl0: UCMODE_0,          /* async, lsb first, 8N1 */
+      ctl1: UCSWRST | UCSSEL_3,        /* clock uart from SMCLK */
+      brx: UBRX_1MHZ_115200,
+      mctl: UMCTL_1MHZ_115200,
+      irtctl: 0,
+      irrctl: 0,
+      abctl: 0,
+      uclisten: FALSE,
+      ren: USCI_REN_NONE
+    };
+
+    return &def;
+  }
+
+  async event void Interrupts.i2cStart() {}
+  async event void Interrupts.i2cStop() {}
+  async event void Interrupts.i2cCal() {}
+  async event void Interrupts.brk() {}
+  async event void Interrupts.i2cNack() {}
+  async event void Counter.overflow() {}
+
+  default async event void UartStream.sendDone( uint8_t* buf, uint16_t len,
+      error_t error ) {}
+  default async event void UartStream.receivedByte( uint8_t byte ) {}
+  default async event void UartStream.receiveDone( uint8_t* buf, uint16_t len,
+      error_t error ) {}
+}
diff --git a/tos/chips/msp430/usci/Msp430Usci.h b/tos/chips/msp430/usci/Msp430Usci.h
new file mode 100644 (file)
index 0000000..575889d
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Header definitions for the USCI peripheral in newer msp430 processors.
+ * A USCI peripheral provides two communications devices, denoted A and B.
+ * Many parts have 2 USCI peripherals, denoted by 0 and 1.  Therefore, a
+ * part with 2 USCI peripherals has 4 communications devices:
+ *
+ *    USCI_A0 and USCI_B0, from the first USCI peripheral; and
+ *    USCI_A1 and USCI_B1, from the second USCI peripheral.
+ *
+ * A devices offer UART, LIN, IrDA and SPI modes of operation.  B parts are
+ * limited to SPI and I2C modes.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+#ifndef MSP430_USCI_h
+#define MSP430_USCI_h
+
+#define MSP430_USCIA0_RESOURCE "Msp430UsciA0.Resource"
+#define MSP430_USCIB0_RESOURCE "Msp430UsciB0.Resource"
+#define MSP430_USCIA1_RESOURCE "Msp430UsciA1.Resource"
+#define MSP430_USCIB1_RESOURCE "Msp430UsciB1.Resource"
+
+typedef enum
+{
+  USCI_UART = 0,
+  USCI_SPI,
+  USCI_I2C
+} msp430_usci_mode_t;
+
+typedef enum {
+  USCI_REN_NONE = 0,
+
+  /* For use in UART mode */
+  USCI_REN_TX = 0x03,
+  USCI_REN_TX_PULLUP = 0x01,
+  USCI_REN_TX_PULLDOWN = 0x02,
+  USCI_REN_RX = 0x0c,
+  USCI_REN_RX_PULLUP = 0x04,
+  USCI_REN_RX_PULLDOWN = 0x08,
+
+  /* For use in SPI mode */
+  USCI_REN_STE = 0x30,
+  USCI_REN_STE_PULLUP = 0x10,
+  USCI_REN_STE_PULLDOWN = 0x20,
+  USCI_REN_SIMO = USCI_REN_TX,
+  USCI_REN_SIMO_PULLUP = USCI_REN_TX_PULLUP,
+  USCI_REN_SIMO_PULLDOWN = USCI_REN_TX_PULLDOWN,
+  USCI_REN_SOMI = USCI_REN_RX,
+  USCI_REN_SOMI_PULLUP = USCI_REN_RX_PULLUP,
+  USCI_REN_SOMI_PULLDOWN = USCI_REN_RX_PULLDOWN,
+  USCI_REN_CLK = 0xc0,
+  USCI_REN_CLK_PULLUP = 0x40,
+  USCI_REN_CLK_PULLDOWN = 0x80,
+
+  /* For use in I2C mode */
+  USCI_REN_SDA = USCI_REN_TX,
+  USCI_REN_SDA_PULLUP = USCI_REN_TX_PULLUP,
+  USCI_REN_SDA_PULLDOWN = USCI_REN_TX_PULLDOWN,
+  USCI_REN_SCL = USCI_REN_RX,
+  USCI_REN_SCL_PULLUP = USCI_REN_RX_PULLUP,
+  USCI_REN_SCL_PULLDOWN = USCI_REN_RX_PULLDOWN
+} msp430_ren_t;
+
+/* Baud rates for UART mode.  Only 32KHz modes work right now. */
+typedef enum {
+  /* UCOS16=0.  UMCTL = UCBRFx << 4 + UCBRSx << 1 + UCOS16.
+   * 1MHZ = 1,048576HZ, 1E6MHZ = 1,000,000HZ.
+   */
+  UBRX_32768HZ_9600=3, UMCTL_32768HZ_9600=(0 << 4) + (3 << 1) + 0,
+  UBRX_1MHZ_9600=109, UMCTL_1MHZ_9600=(0 << 4) + (2 << 1) + 0,
+  UBRX_1MHZ_19200=54, UMCTL_1MHZ_19200=(0 << 4) + (5 << 1) + 0,
+  UBRX_1MHZ_38400=27, UMCTL_1MHZ_38400=(0 << 4) + (2 << 1) + 0,
+  UBRX_1MHZ_115200=9, UMCTL_1MHZ_115200=(0 << 4) + (1 << 1) + 0,
+  UBRX_1E6HZ_9600=104, UMCTL_1E6HZ_9600=(0 << 4) + (1 << 1) + 0,
+  UBRX_1E6HZ_19200=52, UMCTL_1E6HZ_19200=(0 << 4) + (0 << 1) + 0,
+  UBRX_1E6HZ_115200=8, UMCTL_1E6HZ_115200=(0 << 4) + (6 << 1) + 0,
+} msp430_usci_uart_rate_t;
+
+typedef struct {
+  uint8_t ctl0;
+  uint8_t ctl1;
+  uint16_t brx;
+  uint8_t mctl;
+  uint8_t irtctl;
+  uint8_t irrctl;
+  uint8_t abctl;
+  bool uclisten;
+  msp430_ren_t ren;
+} msp430_usci_uart_t;
+
+typedef struct {
+  uint8_t ctl0;
+  uint8_t ctl1;
+  uint16_t brx;
+  bool uclisten;
+  msp430_ren_t ren;
+} msp430_usci_spi_t;
+
+typedef struct {
+  uint8_t ctl0;
+  uint8_t ctl1;
+  uint16_t brx;
+  uint8_t i2coa;
+  msp430_ren_t ren;
+} msp430_usci_i2c_t;
+
+#endif
diff --git a/tos/chips/msp430/usci/Msp430UsciA0C.nc b/tos/chips/msp430/usci/Msp430UsciA0C.nc
new file mode 100644 (file)
index 0000000..cf4ee6e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Defines the USCI_A0 peripheral.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+configuration Msp430UsciA0C {
+  provides {
+    interface HplMsp430UsciReg as Registers;
+    interface HplMsp430UsciInt as Interrupts[uint8_t];
+    interface Resource as Resource[uint8_t];
+    interface ResourceRequested as ResourceRequested[uint8_t];
+    interface ArbiterInfo;
+  }
+  uses interface ResourceConfigure as ResourceConfigure[uint8_t];
+}
+implementation {
+  components new FcfsArbiterC(MSP430_USCIA0_RESOURCE) as ArbiterC;
+  Resource = ArbiterC;
+  ResourceRequested = ArbiterC;
+  ResourceConfigure = ArbiterC;
+  ArbiterInfo = ArbiterC;
+
+  components new Msp430UsciIntDispatchP() as IntDispatchA0P;
+  Interrupts = IntDispatchA0P;
+  IntDispatchA0P.ArbiterInfo -> ArbiterC;
+
+  components HplMsp430UsciC as UsciC;
+  Registers = UsciC.RegA0;
+  IntDispatchA0P.RawInt -> UsciC.IntA0;
+}
diff --git a/tos/chips/msp430/usci/Msp430UsciA1C.nc b/tos/chips/msp430/usci/Msp430UsciA1C.nc
new file mode 100644 (file)
index 0000000..800300d
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Defines the USCI_A1 peripheral.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+configuration Msp430UsciA1C {
+  provides {
+    interface HplMsp430UsciReg as Registers;
+    interface HplMsp430UsciInt as Interrupts[uint8_t];
+    interface Resource as Resource[uint8_t];
+    interface ResourceRequested as ResourceRequested[uint8_t];
+    interface ArbiterInfo;
+  }
+  uses interface ResourceConfigure as ResourceConfigure[uint8_t];
+}
+implementation {
+  components new FcfsArbiterC(MSP430_USCIA1_RESOURCE) as ArbiterC;
+  Resource = ArbiterC;
+  ResourceRequested = ArbiterC;
+  ResourceConfigure = ArbiterC;
+  ArbiterInfo = ArbiterC;
+
+  components new Msp430UsciIntDispatchP() as IntDispatchA1P;
+  Interrupts = IntDispatchA1P;
+  IntDispatchA1P.ArbiterInfo -> ArbiterC;
+
+  components HplMsp430UsciC as UsciC;
+  Registers = UsciC.RegA1;
+  IntDispatchA1P.RawInt -> UsciC.IntA1;
+}
diff --git a/tos/chips/msp430/usci/Msp430UsciB0C.nc b/tos/chips/msp430/usci/Msp430UsciB0C.nc
new file mode 100644 (file)
index 0000000..12f821e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Defines the USCI_B0 peripheral.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+configuration Msp430UsciB0C {
+  provides {
+    interface HplMsp430UsciReg as Registers;
+    interface HplMsp430UsciInt as Interrupts[uint8_t];
+    interface Resource as Resource[uint8_t];
+    interface ResourceRequested as ResourceRequested[uint8_t];
+    interface ArbiterInfo;
+  }
+  uses interface ResourceConfigure as ResourceConfigure[uint8_t];
+}
+implementation {
+  components new FcfsArbiterC(MSP430_USCIB0_RESOURCE) as ArbiterC;
+  Resource = ArbiterC;
+  ResourceRequested = ArbiterC;
+  ResourceConfigure = ArbiterC;
+  ArbiterInfo = ArbiterC;
+
+  components new Msp430UsciIntDispatchP() as IntDispatchB0P;
+  Interrupts = IntDispatchB0P;
+  IntDispatchB0P.ArbiterInfo -> ArbiterC;
+
+  components HplMsp430UsciC as UsciC;
+  Registers = UsciC.RegB0;
+  IntDispatchB0P.RawInt -> UsciC.IntB0;
+}
diff --git a/tos/chips/msp430/usci/Msp430UsciB1C.nc b/tos/chips/msp430/usci/Msp430UsciB1C.nc
new file mode 100644 (file)
index 0000000..81b5e60
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Defines the USCI_B1 peripheral.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+configuration Msp430UsciB1C {
+  provides {
+    interface HplMsp430UsciReg as Registers;
+    interface HplMsp430UsciInt as Interrupts[uint8_t];
+    interface Resource as Resource[uint8_t];
+    interface ResourceRequested as ResourceRequested[uint8_t];
+    interface ArbiterInfo;
+  }
+  uses interface ResourceConfigure as ResourceConfigure[uint8_t];
+}
+implementation {
+  components new FcfsArbiterC(MSP430_USCIB1_RESOURCE) as ArbiterC;
+  Resource = ArbiterC;
+  ResourceRequested = ArbiterC;
+  ResourceConfigure = ArbiterC;
+  ArbiterInfo = ArbiterC;
+
+  components new Msp430UsciIntDispatchP() as IntDispatchB1P;
+  Interrupts = IntDispatchB1P;
+  IntDispatchB1P.ArbiterInfo -> ArbiterC;
+
+  components HplMsp430UsciC as UsciC;
+  Registers = UsciC.RegB1;
+  IntDispatchB1P.RawInt -> UsciC.IntB1;
+}
diff --git a/tos/chips/msp430/usci/Msp430UsciIntDispatchP.nc b/tos/chips/msp430/usci/Msp430UsciIntDispatchP.nc
new file mode 100644 (file)
index 0000000..2312f6c
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Interrupt dispatch for USCI_Ax and USCI_Bx devices.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic module Msp430UsciIntDispatchP() @safe() {
+  provides interface HplMsp430UsciInt as Interrupts[uint8_t id];
+  uses {
+    interface HplMsp430UsciInt as RawInt;
+    interface ArbiterInfo;
+  }
+}
+
+implementation {
+  async event void RawInt.brk()
+  {
+    if (call ArbiterInfo.inUse())
+      signal Interrupts.brk[call ArbiterInfo.userId()]();
+  }
+
+  async event void RawInt.rx(uint8_t byte)
+  {
+    if (call ArbiterInfo.inUse())
+      signal Interrupts.rx[call ArbiterInfo.userId()](byte);
+  }
+
+  async event void RawInt.tx()
+  {
+    if (call ArbiterInfo.inUse())
+      signal Interrupts.tx[call ArbiterInfo.userId()]();
+  }
+
+  async event void RawInt.i2cCal()
+  {
+    if (call ArbiterInfo.inUse())
+      signal Interrupts.i2cCal[call ArbiterInfo.userId()]();
+  }
+
+  async event void RawInt.i2cNack()
+  {
+    if (call ArbiterInfo.inUse())
+      signal Interrupts.i2cNack[call ArbiterInfo.userId()]();
+  }
+
+  async event void RawInt.i2cStart()
+  {
+    if (call ArbiterInfo.inUse())
+      signal Interrupts.i2cStart[call ArbiterInfo.userId()]();
+  }
+
+  async event void RawInt.i2cStop()
+  {
+    if (call ArbiterInfo.inUse())
+      signal Interrupts.i2cStop[call ArbiterInfo.userId()]();
+  }
+
+  default async event void Interrupts.brk[uint8_t id]() {}
+  default async event void Interrupts.rx[uint8_t id](uint8_t byte) {}
+  default async event void Interrupts.tx[uint8_t id]() {}
+  default async event void Interrupts.i2cCal[uint8_t id]() {}
+  default async event void Interrupts.i2cNack[uint8_t id]() {}
+  default async event void Interrupts.i2cStart[uint8_t id]() {}
+  default async event void Interrupts.i2cStop[uint8_t id]() {}
+}