}
}
+ task void signalSendDone()
+ {
+ atomic {
+ uint16_t len = m_len;
+ m_len = 0;
+ signal SpiPacket.sendDone(m_txBuf, m_rxBuf, len, SUCCESS);
+ }
+ }
+
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();
}
}
- void sendData()
+ bool waitOnRx()
+ {
+ 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;
+ }
+ }
+
+ bool waitOnTx()
+ {
+ 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;
+ }
+ }
+
+ /* Return FALSE if we are in reset, so callers can clean up as appropriate. */
+ bool sendData()
{
atomic {
uint16_t end = m_pos + (blockSize ? blockSize : BLOCKSIZE_DEFAULT);
end = m_len;
call Registers.setTxbuf(m_txBuf ? m_txBuf[m_pos] : 0);
while (++m_pos < end) {
- while (!call Registers.getIfgRx() && !call Registers.getCtl1(UCSWRST));
+ waitOnRx();
tmp = call Registers.getRxbuf();
if (m_rxBuf)
m_rxBuf[m_pos - 1] = tmp;
- while (!call Registers.getIfgTx() && !call Registers.getCtl1(UCSWRST));
+ waitOnTx();
call Registers.setTxbuf(m_txBuf ? m_txBuf[m_pos] : 0);
}
+ return call Registers.getCtl1(UCSWRST) ? FALSE : TRUE;
}
}
m_rxBuf = rxBuf;
m_len = len;
m_pos = 0;
- call Registers.setIeRx();
- sendData();
- return SUCCESS;
+ if (sendData()) {
+ call Registers.setIeRx();
+ return SUCCESS;
+ } else {
+ m_len = 0;
+ return FAIL;
+ }
}
}
}
async event void Interrupts.tx() {}
- task void signalSendDone()
- {
- atomic {
- uint16_t len = m_len;
- m_len = 0;
- signal SpiPacket.sendDone(m_txBuf, m_rxBuf, len, SUCCESS);
- }
- }
-
async event void Interrupts.rx(uint8_t byte)
{
if (m_rxBuf)
m_rxBuf[m_pos - 1] = byte;
- if (m_pos < m_len)
- sendData();
- else {
- call Registers.clrIeRx();
- post signalSendDone(); /* Don't signal from ISR context */
+ if (m_pos < m_len) {
+ if (sendData())
+ return;
}
+ call Registers.clrIeRx();
+ post signalSendDone(); /* Don't signal from ISR context */
}
default async event void SpiPacket.sendDone(uint8_t*, uint8_t*, uint16_t,