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.
interface SpiPacket;
interface ArbiterInfo; /* ??? */
}
interface SpiPacket;
interface ArbiterInfo; /* ??? */
}
- uses interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+ uses {
+ interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+ interface GeneralIO as CSn; /* wire only if a SPI slave only */
+ }
}
implementation {
enum {
}
implementation {
enum {
SpiByte = SpiP;
SpiPacket = SpiP;
Configure = SpiP;
SpiByte = SpiP;
SpiPacket = SpiP;
Configure = SpiP;
components Msp430UsciA0C as UsciC;
Resource = UsciC.Resource[CLIENT_ID];
components Msp430UsciA0C as UsciC;
Resource = UsciC.Resource[CLIENT_ID];
interface SpiPacket;
interface ArbiterInfo; /* ??? */
}
interface SpiPacket;
interface ArbiterInfo; /* ??? */
}
- uses interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+ uses {
+ interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+ interface GeneralIO as CSn; /* wire only if a SPI slave only */
+ }
}
implementation {
enum {
}
implementation {
enum {
SpiByte = SpiP;
SpiPacket = SpiP;
Configure = SpiP;
SpiByte = SpiP;
SpiPacket = SpiP;
Configure = SpiP;
components Msp430UsciB0C as UsciC;
Resource = UsciC.Resource[CLIENT_ID];
components Msp430UsciB0C as UsciC;
Resource = UsciC.Resource[CLIENT_ID];
interface SpiPacket;
interface ArbiterInfo; /* ??? */
}
interface SpiPacket;
interface ArbiterInfo; /* ??? */
}
- uses interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+ uses {
+ interface AsyncConfigure<const msp430_usci_spi_t*> as Configure;
+ interface GeneralIO as CSn; /* wire only if a SPI slave only */
+ }
}
implementation {
enum {
}
implementation {
enum {
SpiByte = SpiP;
SpiPacket = SpiP;
Configure = SpiP;
SpiByte = SpiP;
SpiPacket = SpiP;
Configure = SpiP;
components Msp430UsciB1C as UsciC;
Resource = UsciC.Resource[CLIENT_ID];
components Msp430UsciB1C as UsciC;
Resource = UsciC.Resource[CLIENT_ID];
- * 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
*
*
* TODO: Implement error checking via UCxxSTAT
*
uses {
interface HplMsp430UsciReg as Registers;
interface HplMsp430UsciInt as Interrupts;
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 STE;
interface HplMsp430GeneralIO as SIMO;
interface HplMsp430GeneralIO as SOMI;
uint16_t m_len;
uint16_t m_pos;
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;
}
{
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;
}
{
atomic return m_len != 0;
}
- async command uint8_t SpiByte.write(uint8_t byte)
- 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;
- 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;
+ 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();
waitOnTx();
call Registers.setTxbuf(m_txBuf ? m_txBuf[m_pos] : 0);
}
waitOnTx();
call Registers.setTxbuf(m_txBuf ? m_txBuf[m_pos] : 0);
}
- return call Registers.getCtl1(UCSWRST) ? FALSE : TRUE;
+ return call CSn.get() ? FALSE : TRUE;
async event void Interrupts.i2cCal() {}
async event void Interrupts.brk() {}
async event void Interrupts.i2cNak() {}
async event void Interrupts.i2cCal() {}
async event void Interrupts.brk() {}
async event void Interrupts.i2cNak() {}
+
+ default async command bool CSn.get() { return FALSE; }