From 5592947363b1fa4dc67880c1d12d83866a49ddb9 Mon Sep 17 00:00:00 2001 From: smckown Date: Fri, 8 May 2009 22:27:14 +0000 Subject: [PATCH] Implement chip select query for SPI peripheral. If the SPI peripheral is in slave mode, a transaction could be halted at any time by the host unasserting (high) the chip select line. This code implements a check on chip select to allow SPI slaves to see the early abort and act accordingly. --- tos/chips/msp430/usci/Msp430SpiA0C.nc | 6 ++- tos/chips/msp430/usci/Msp430SpiB0C.nc | 6 ++- tos/chips/msp430/usci/Msp430SpiB1C.nc | 6 ++- tos/chips/msp430/usci/Msp430SpiP.nc | 75 +++++++++++---------------- 4 files changed, 44 insertions(+), 49 deletions(-) diff --git a/tos/chips/msp430/usci/Msp430SpiA0C.nc b/tos/chips/msp430/usci/Msp430SpiA0C.nc index c428bb8f..9f166521 100644 --- a/tos/chips/msp430/usci/Msp430SpiA0C.nc +++ b/tos/chips/msp430/usci/Msp430SpiA0C.nc @@ -65,7 +65,10 @@ generic configuration Msp430SpiA0C(uint16_t blockSize) { interface SpiPacket; interface ArbiterInfo; /* ??? */ } - uses interface AsyncConfigure as Configure; + uses { + interface AsyncConfigure as Configure; + interface GeneralIO as CSn; /* wire only if a SPI slave only */ + } } implementation { enum { @@ -76,6 +79,7 @@ implementation { SpiByte = SpiP; SpiPacket = SpiP; Configure = SpiP; + CSn = SpiP; components Msp430UsciA0C as UsciC; Resource = UsciC.Resource[CLIENT_ID]; diff --git a/tos/chips/msp430/usci/Msp430SpiB0C.nc b/tos/chips/msp430/usci/Msp430SpiB0C.nc index 6684b79d..dbd00822 100644 --- a/tos/chips/msp430/usci/Msp430SpiB0C.nc +++ b/tos/chips/msp430/usci/Msp430SpiB0C.nc @@ -65,7 +65,10 @@ generic configuration Msp430SpiB0C(uint16_t blockSize) { interface SpiPacket; interface ArbiterInfo; /* ??? */ } - uses interface AsyncConfigure as Configure; + uses { + interface AsyncConfigure as Configure; + interface GeneralIO as CSn; /* wire only if a SPI slave only */ + } } implementation { enum { @@ -76,6 +79,7 @@ implementation { SpiByte = SpiP; SpiPacket = SpiP; Configure = SpiP; + CSn = SpiP; components Msp430UsciB0C as UsciC; Resource = UsciC.Resource[CLIENT_ID]; diff --git a/tos/chips/msp430/usci/Msp430SpiB1C.nc b/tos/chips/msp430/usci/Msp430SpiB1C.nc index 7a5b400b..5fc73fc2 100644 --- a/tos/chips/msp430/usci/Msp430SpiB1C.nc +++ b/tos/chips/msp430/usci/Msp430SpiB1C.nc @@ -65,7 +65,10 @@ generic configuration Msp430SpiB1C(uint16_t blockSize) { interface SpiPacket; interface ArbiterInfo; /* ??? */ } - uses interface AsyncConfigure as Configure; + uses { + interface AsyncConfigure as Configure; + interface GeneralIO as CSn; /* wire only if a SPI slave only */ + } } implementation { enum { @@ -76,6 +79,7 @@ implementation { SpiByte = SpiP; SpiPacket = SpiP; Configure = SpiP; + CSn = SpiP; components Msp430UsciB1C as UsciC; Resource = UsciC.Resource[CLIENT_ID]; diff --git a/tos/chips/msp430/usci/Msp430SpiP.nc b/tos/chips/msp430/usci/Msp430SpiP.nc index b230f607..0aaf9bd3 100644 --- a/tos/chips/msp430/usci/Msp430SpiP.nc +++ b/tos/chips/msp430/usci/Msp430SpiP.nc @@ -28,7 +28,9 @@ */ /** - * 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 * @@ -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; @@ -74,12 +77,12 @@ implementation { uint16_t m_len; 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; } @@ -205,57 +208,35 @@ 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; - } - return FALSE; + if (isBusy()) + return 0; + else { + waitOnTx(); + call Registers.setTxbuf(byte); + waitOnRx(); + return call Registers.getRxbuf(); } } @@ -277,7 +258,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; } } @@ -339,4 +320,6 @@ implementation { async event void Interrupts.i2cCal() {} async event void Interrupts.brk() {} async event void Interrupts.i2cNak() {} + + default async command bool CSn.get() { return FALSE; } } -- 2.39.2