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.
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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() {}
+}
--- /dev/null
+/*
+ * 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() {}
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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() {}
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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; }
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 ) {}
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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]() {}
+}