X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fchips%2Fmsp430%2Fusci%2FMsp430SpiP.nc;h=ed8b6743722994273d3d70816f4bad0e8cbf2d07;hb=be862ab07d080085823951d18dcb27a28a310ace;hp=b230f607cab60ca2035626a302686ff5932f2b27;hpb=8b4e47b1164756e843662d4f3063425fddd8c232;p=tinyos-2.x.git diff --git a/tos/chips/msp430/usci/Msp430SpiP.nc b/tos/chips/msp430/usci/Msp430SpiP.nc index b230f607..ed8b6743 100644 --- a/tos/chips/msp430/usci/Msp430SpiP.nc +++ b/tos/chips/msp430/usci/Msp430SpiP.nc @@ -10,7 +10,7 @@ * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * - Neither the name of the Technische Universität Berlin nor the names + * - Neither the name of the Titanium Mirror, Inc. nor the names * of its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -26,9 +26,11 @@ * (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. + * 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 * @@ -36,7 +38,7 @@ * * @author R. Steve McKown */ - + generic module Msp430SpiP(uint16_t blockSize) { provides { interface SpiByte; @@ -46,6 +48,7 @@ generic module Msp430SpiP(uint16_t blockSize) { 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; @@ -69,17 +72,17 @@ implementation { }; uint8_t m_pins; - uint8_t* m_txBuf; - uint8_t* m_rxBuf; - uint16_t m_len; - uint16_t m_pos; + 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 */ + 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 */ + inline bool isBusy() /* TRUE if a SPI transaction is in progress */ { atomic return m_len != 0; } @@ -160,11 +163,10 @@ implementation { task void signalSendDone() { - atomic { - uint16_t len = m_len; - m_len = 0; - signal SpiPacket.sendDone(m_txBuf, m_rxBuf, len, SUCCESS); - } + 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() @@ -205,61 +207,41 @@ implementation { } } - async command uint8_t SpiByte.write(uint8_t byte) + bool waitOnRx() { - if (isBusy()) - return 0; - else { - while (!call Registers.getIfgTx() && !call Registers.getCtl1(UCSWRST)); - call Registers.setTxbuf(byte); - while(!call Registers.getIfgRx() && !call Registers.getCtl1(UCSWRST)); - return call Registers.getRxbuf(); + for (;;) { + if (call Registers.getIfgRx()) + return TRUE; + if (call CSn.get()) /* SPI master has unselected us */ + return FALSE; } } - bool waitOnRx() + bool waitOnTx() { - if (call Registers.getCtl0(UCMST)) { - while (!call Registers.getIfgRx() && !call Registers.getCtl1(UCSWRST)); - return TRUE; - } else { - /* If SPI slave, the host could quit clocking any time, so we need a - * timeout. - */ - unsigned i = 0; - - while (++i) { - if (call Registers.getIfgRx()) - return TRUE; - if (call Registers.getCtl1(UCSWRST)) - return FALSE; - } - return FALSE; + for (;;) { + if (call Registers.getIfgTx()) + return TRUE; + if (call CSn.get()) /* SPI master has unselected us */ + return FALSE; } } - bool waitOnTx() + async command uint8_t SpiByte.write(uint8_t byte) { - if (call Registers.getCtl0(UCMST)) { - while (!call Registers.getIfgTx() && !call Registers.getCtl1(UCSWRST)); - return TRUE; - } else { - /* If SPI slave, the host could quit clocking any time, so we need a - * timeout. - */ - unsigned i = 0; - - while (++i) { - if (call Registers.getIfgTx()) - return TRUE; - if (call Registers.getCtl1(UCSWRST)) - return FALSE; + atomic { + if (isBusy()) + return 0; + else { + waitOnTx(); + call Registers.setTxbuf(byte); + waitOnRx(); + return call Registers.getRxbuf(); } - return FALSE; } } - /* Return FALSE if we are in reset, so callers can clean up as appropriate. */ + /* If we are a slave, return FALSE if the master has unasserted CSn. */ bool sendData() { atomic { @@ -268,6 +250,7 @@ implementation { 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(); @@ -277,7 +260,7 @@ implementation { waitOnTx(); call Registers.setTxbuf(m_txBuf ? m_txBuf[m_pos] : 0); } - return call Registers.getCtl1(UCSWRST) ? FALSE : TRUE; + return call CSn.get() ? FALSE : TRUE; } } @@ -287,19 +270,15 @@ implementation { if (isBusy() || (!txBuf && !rxBuf) || len == 0) return FAIL; else { - atomic { - m_txBuf = txBuf; - m_rxBuf = rxBuf; - m_len = len; - m_pos = 0; - if (sendData()) { - call Registers.setIeRx(); - return SUCCESS; - } else { - m_len = 0; - return FAIL; - } - } + m_txBuf = txBuf; + m_rxBuf = rxBuf; + m_len = len; + m_pos = 0; + if (sendData()) + call Registers.setIeRx(); + else + post signalSendDone(); + return SUCCESS; } } @@ -315,7 +294,7 @@ implementation { return; } call Registers.clrIeRx(); - post signalSendDone(); /* Don't signal from ISR context */ + post signalSendDone(); } default async event void SpiPacket.sendDone(uint8_t*, uint8_t*, uint16_t, @@ -323,7 +302,7 @@ implementation { default async command const msp430_usci_spi_t* Configure.get() { - const static msp430_usci_spi_t def = { + 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 */ @@ -338,5 +317,7 @@ implementation { async event void Interrupts.i2cStop() {} async event void Interrupts.i2cCal() {} async event void Interrupts.brk() {} - async event void Interrupts.i2cNak() {} + async event void Interrupts.i2cNack() {} + + default async command bool CSn.get() { return FALSE; } }