From: smckown Date: Wed, 10 Sep 2008 22:15:35 +0000 (+0000) Subject: Added SPI support. Now working using the loopback feature (UCLISTEN bit). X-Git-Tag: release/2.1.0-1~55 X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=commitdiff_plain;h=97db9cf16631f784eea3fc7a3ec925f09bc65c08 Added SPI support. Now working using the loopback feature (UCLISTEN bit). Also fixed a relocation error problem due to packed structures and placement of instantiations in text page via "const static ...". No change to text or data page sizes at compilation. Since msp430_usci_xxx_t will never be on the stack, removal of the packed attribute was the way to work around what appears to be a compiler problem. --- diff --git a/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc b/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc index 8c3a3451..65ee5be1 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciInt0P.nc @@ -75,16 +75,9 @@ implementation signal IntA.brk(); } else signal IntA.rx(c); - } else if (READ_FLAG(UC0IFG, UCB0RXIFG)) { - volatile uint8_t c = UCB0RXBUF; /* read to clear UCB0RXIFG */ - if (READ_FLAG(UCB0CTL1, UCBRK)) { - CLR_FLAG(UCB0CTL1, UCBRK); - if (READ_FLAG(UCB0CTL0, UCMODE_3) == UCMODE_3) - CLR_FLAG(UCB0CTL1, UCDORM); - signal IntB.brk(); - } else - signal IntB.rx(c); - } else if (READ_FLAG(UCB0STAT, UCALIFG)) + } else if (READ_FLAG(UC0IFG, UCB0RXIFG)) + signal IntB.rx(UCB0RXBUF); /* read clears UCB0RXIFG */ + else if (READ_FLAG(UCB0STAT, UCALIFG)) signal IntB.i2cCal(); else if (READ_FLAG(UCB0STAT, UCNACKIFG)) signal IntB.i2cNak(); diff --git a/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc b/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc index e6a79a14..c083cdb9 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciInt1P.nc @@ -68,16 +68,9 @@ implementation signal IntA.brk(); } else signal IntA.rx(c); - } else if (READ_FLAG(UC1IFG, UCB1RXIFG)) { - volatile uint8_t c = UCB1RXBUF; /* read to clear UCB1RXIFG */ - if (READ_FLAG(UCB1CTL1, UCBRK)) { - CLR_FLAG(UCB1CTL1, UCBRK); - if (READ_FLAG(UCB1CTL0, UCMODE_3) == UCMODE_3) - CLR_FLAG(UCB1CTL1, UCDORM); - signal IntB.brk(); - } else - signal IntB.rx(c); - } else if (READ_FLAG(UCB1STAT, UCALIFG)) + } else if (READ_FLAG(UC1IFG, UCB1RXIFG)) + signal IntB.rx(UCB1RXBUF); /* read clears UCB1RXIFG */ + else if (READ_FLAG(UCB1STAT, UCALIFG)) signal IntB.i2cCal(); else if (READ_FLAG(UCB1STAT, UCNACKIFG)) signal IntB.i2cNak(); diff --git a/tos/chips/msp430/usci/HplMsp430UsciRegP.nc b/tos/chips/msp430/usci/HplMsp430UsciRegP.nc index 67f650a7..a9994ade 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciRegP.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciRegP.nc @@ -57,8 +57,8 @@ generic module HplMsp430UsciRegP( uint16_t I2Csa_addr, /* B devices only */ uint16_t Ie_addr, uint16_t Ifg_addr, - uint16_t UCAxRXIFG, /* We rely on xIE and xIFG at same bit positions */ - uint16_t UCAxTXIFG + uint16_t UCxxRXIFG, /* We rely on xIE and xIFG at same bit positions */ + uint16_t UCxxTXIFG ) @safe() { provides interface HplMsp430UsciReg as Registers; } @@ -242,62 +242,62 @@ implementation /* RENDER(Ie); */ async command bool Registers.getIeRx() { - return READ_FLAG(UCxxIe, UCAxRXIFG); + return READ_FLAG(UCxxIe, UCxxRXIFG); } async command void Registers.setIeRx() { - SET_FLAG(UCxxIe, UCAxRXIFG); + SET_FLAG(UCxxIe, UCxxRXIFG); } async command void Registers.clrIeRx() { - CLR_FLAG(UCxxIe, UCAxRXIFG); + CLR_FLAG(UCxxIe, UCxxRXIFG); } async command bool Registers.getIeTx() { - return READ_FLAG(UCxxIe, UCAxTXIFG); + return READ_FLAG(UCxxIe, UCxxTXIFG); } async command void Registers.setIeTx() { - SET_FLAG(UCxxIe, UCAxTXIFG); + SET_FLAG(UCxxIe, UCxxTXIFG); } async command void Registers.clrIeTx() { - CLR_FLAG(UCxxIe, UCAxTXIFG); + CLR_FLAG(UCxxIe, UCxxTXIFG); } /* RENDER(Ifg); */ async command bool Registers.getIfgRx() { - return READ_FLAG(UCxxIfg, UCAxRXIFG); + return READ_FLAG(UCxxIfg, UCxxRXIFG); } async command void Registers.setIfgRx() { - SET_FLAG(UCxxIfg, UCAxRXIFG); + SET_FLAG(UCxxIfg, UCxxRXIFG); } async command void Registers.clrIfgRx() { - CLR_FLAG(UCxxIfg, UCAxRXIFG); + CLR_FLAG(UCxxIfg, UCxxRXIFG); } async command bool Registers.getIfgTx() { - return READ_FLAG(UCxxIfg, UCAxTXIFG); + return READ_FLAG(UCxxIfg, UCxxTXIFG); } async command void Registers.setIfgTx() { - SET_FLAG(UCxxIfg, UCAxTXIFG); + SET_FLAG(UCxxIfg, UCxxTXIFG); } async command void Registers.clrIfgTx() { - CLR_FLAG(UCxxIfg, UCAxTXIFG); + CLR_FLAG(UCxxIfg, UCxxTXIFG); } } diff --git a/tos/chips/msp430/usci/Msp430SpiB1C.nc b/tos/chips/msp430/usci/Msp430SpiB1C.nc index 9cfd71db..93a9f22b 100644 --- a/tos/chips/msp430/usci/Msp430SpiB1C.nc +++ b/tos/chips/msp430/usci/Msp430SpiB1C.nc @@ -31,6 +31,23 @@ * 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 */ @@ -40,7 +57,7 @@ #include "Msp430Usci.h" -generic configuration Msp430SpiB1C() { +generic configuration Msp430SpiB1C(uint16_t blockSize) { provides { interface Resource; interface ResourceRequested; @@ -55,12 +72,12 @@ implementation { CLIENT_ID = unique(MSP430_USCIB1_RESOURCE) }; - components new Msp430SpiP() as SpiP; + components new Msp430SpiP(blockSize) as SpiP; SpiByte = SpiP; SpiPacket = SpiP; Configure = SpiP; - components Msp430UsciA0C as UsciC; + components Msp430UsciB1C as UsciC; Resource = UsciC.Resource[CLIENT_ID]; ResourceRequested = UsciC.ResourceRequested[CLIENT_ID]; ArbiterInfo = UsciC.ArbiterInfo; @@ -73,5 +90,5 @@ implementation { SpiP.STE -> IOC.UCB1STE; SpiP.SIMO -> IOC.UCB1SIMO; SpiP.SOMI -> IOC.UCB1SOMI; - SpiP.SCL -> IOC.UCB1SCL; + SpiP.CLK -> IOC.UCB1CLK; } diff --git a/tos/chips/msp430/usci/Msp430SpiP.nc b/tos/chips/msp430/usci/Msp430SpiP.nc index 33202005..5a23279c 100644 --- a/tos/chips/msp430/usci/Msp430SpiP.nc +++ b/tos/chips/msp430/usci/Msp430SpiP.nc @@ -30,10 +30,12 @@ /** * Spi implementation using a USCI device. * + * TODO: Implement error checking via UCxxSTAT + * * @author R. Steve McKown */ -generic module Msp430SpiP() { +generic module Msp430SpiP(uint16_t blockSize) { provides { interface SpiByte; interface SpiPacket; @@ -45,13 +47,16 @@ generic module Msp430SpiP() { interface HplMsp430GeneralIO as STE; interface HplMsp430GeneralIO as SIMO; interface HplMsp430GeneralIO as SOMI; - interface HplMsp430GeneralIO as SCL; + interface HplMsp430GeneralIO as CLK; interface AsyncConfigure as Configure; - interface Counter interface ArbiterInfo; } } implementation { + enum { + BLOCKSIZE_DEFAULT = 64 + }; + #define saveBits(pin, pos, dir, out, ren) { \ if (call pin.isOutput()) \ dir |= (1 << pos); \ @@ -76,18 +81,25 @@ implementation { call pin.makeInput(); \ } - uint8_t dir; /* Pin state storage to allow for proper unconfiguration */ - uint8_t out; - uint8_t ren; - uint8_t* sobuf; /* Original buffer ptr from UartStream.send() */ - uint8_t solen; /* Original buffer len from UartStream.send() */ - uint8_t* sbuf; /* Position of next char to send */ - uint8_t slen; /* Len of chars in sbuf to send */ - bool rxie; /* Set if rxie has been enabled to UartStream.receive() */ - uint8_t* robuf; /* Original receive buffer */ - uint8_t rolen; /* Original (maximum) receive len */ - uint8_t* rbuf; /* Position of next byte in which to receive a char */ - uint8_t rlen; /* Remaining length in receive buffer */ + /* Pin IO configuration storage for later restoration */ + uint8_t m_dir; + uint8_t m_out; + uint8_t m_ren; + + uint8_t* m_txBuf; + uint8_t* m_rxBuf; + uint16_t m_len; + 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() { @@ -97,7 +109,9 @@ implementation { call Registers.setCtl1(UCSWRST); - /* Force 3-pin SPI if config says I2C */ + /* 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); @@ -107,39 +121,65 @@ implementation { 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.clrStat(UCLISTEN); + call Registers.assignMctl(0); + if (config->uclisten) + call Registers.setStat(UCLISTEN); + else + call Registers.clrStat(UCLISTEN); - /* Save pin IO states */ - dir = out = ren = 0; - saveBits(RXD, 0, dir, out, ren); - saveBits(TXD, 1, dir, out, ren); + /* Save pin IO configuration */ + m_dir = m_out = m_ren = 0; + if (is4pin()) + saveBits(STE, 0, m_dir, m_out, m_ren); + saveBits(SIMO, 1, m_dir, m_out, m_ren); + saveBits(SOMI, 2, m_dir, m_out, m_ren); + saveBits(CLK, 3, m_dir, m_out, m_ren); - /* Configure RX pin for UART use */ - call RXD.makeInput(); - if (config->ren & USCI_REN_RX) { - if (config->ren & USCI_REN_RX_PULLUP) - call RXD.set(); + /* Configure pins for SPI use */ + if (is4pin()) { +#if 0 /* Unsure if REN on STE is a valid configuration */ + /* Configure STE pin for SPI use */ + if (config->ren & USCI_REN_STE) { + if (config->ren & USCI_REN_STE_PULLUP) + call STE.set(); + else + call STE.clr(); + call STE.enableRen(); + } +#endif + call STE.selectModuleFunc(); + } + call SOMI.makeInput(); + if (config->ren & USCI_REN_SOMI) { + if (config->ren & USCI_REN_SOMI_PULLUP) + call SOMI.set(); else - call RXD.clr(); - call RXD.enableRen(); + call SOMI.clr(); + call SOMI.enableRen(); } - call RXD.selectModuleFunc(); - -#if 0 /* pull-ups don't make sense on TXD, since it doesn't appear that - * enabling an open-drain emulation mode via USCI is possible. - */ - - /* Configure TX pin for UART use */ - if (config->ren & USCI_REN_TX) { - if (config->ren & USCI_REN_TX_PULLUP) - call TXD.set(); + call SOMI.selectModuleFunc(); +#if 0 /* Unsure if REN on SIMO is a valid configuration */ + /* Configure SIMO pin for SPI use */ + if (config->ren & USCI_REN_SIMO) { + if (config->ren & USCI_REN_SIMO_PULLUP) + call SIMO.set(); else - call TXD.clr(); - call TXD.enableRen(); + call SIMO.clr(); + call SIMO.enableRen(); } - call TXD.selectModuleFunc(); #endif + call SIMO.selectModuleFunc(); +#if 0 /* Unsure if REN on CLK is a valid configuration */ + /* Configure CLK pin for SPI use */ + if (config->ren & USCI_REN_CLK) { + if (config->ren & USCI_REN_CLK_PULLUP) + call CLK.set(); + else + call CLK.clr(); + call CLK.enableRen(); + } +#endif + call CLK.selectModuleFunc(); /* Clear interrupts; we'll add them as needed */ call Registers.clrIeRx(); @@ -156,142 +196,116 @@ implementation { /* Disable the device */ call Registers.setCtl1(UCSYNC); - /* Clear interrupts and interrupt flags */ + /* Clear interrupts and interrupt flags. We only used Rx */ call Registers.clrIeRx(); - call Registers.clrIeTx(); call Registers.clrIfgRx(); - call Registers.clrIfgTx(); /* Restore pins to their preconfigured state */ #if 0 - restoreBits(RXD, 0, dir, out, ren); - restoreBits(TXD, 0, dir, out, ren); + if (is4pin()) + restoreBits(STE, 0, m_dir, m_out, m_ren); + restoreBits(SIMO, 1, m_dir, m_out, m_ren); + restoreBits(SOMI, 1, m_dir, m_out, m_ren); + restoreBits(CLK, 1, m_dir, m_out, m_ren); #endif - call RXD.selectIOFunc(); - call TXD.selectIOFunc(); + if (is4pin()) + call STE.selectIOFunc(); + call SIMO.selectIOFunc(); + call SOMI.selectIOFunc(); + call CLK.selectIOFunc(); } } - async command error_t UartByte.send(uint8_t byte) + async command uint8_t SpiByte.write(uint8_t byte) { - /* FIXME: race with UartStream.send() */ - atomic { - if (sobuf) - return FAIL; - while (call Registers.getStat(UCBUSY)); + if (isBusy()) + return 0; + else { + while (!call Registers.getIfgTx()); call Registers.setTxbuf(byte); - return SUCCESS; + while(!call Registers.getIfgRx()); + return call Registers.getRxbuf(); } } - async command error_t UartStream.send(uint8_t* buf, uint16_t len) + void sendData() { - if (sobuf || !buf || !len) - return FAIL; - sobuf = buf; - solen = len; - call Registers.setIeTx(); - call Registers.setTxbuf(*sobuf); - slen = solen - 1; - if (slen) - sbuf = sobuf + 1; - return SUCCESS; - } + /* We don't need to check Registers.getIfgTx() (aks UCxxTXIFG), as + * sendData() is only called after peripheral init or receipt of the rx() + * interrupt. SPI on msp430 guarantees UCxxTXIFG is asserted in both of + * these cases. + */ + atomic { + uint16_t end = m_pos + (blockSize ? blockSize : BLOCKSIZE_DEFAULT); + uint8_t tmp; - async event void Interrupts.tx() - { - while (slen && call Registers.getIfgTx()) { - call Registers.setTxbuf(*sbuf); - if (--slen) - sbuf++; - } - if (slen == 0 && sobuf) { - call Registers.clrIeTx(); - call Registers.clrIfgTx(); - sobuf = 0; - signal UartStream.sendDone(sobuf, solen, SUCCESS); + if (end > m_len) + end = m_len; + call Registers.setTxbuf((m_txBuf) ? m_txBuf[m_pos] : 0); + while (++m_pos < end) { + while (!call Registers.getIfgRx()); + if (m_rxBuf) + m_rxBuf[m_pos - 1] = call Registers.getRxbuf(); + else + tmp = call Registers.getRxbuf(); + call Registers.setTxbuf((m_txBuf) ? m_txBuf[m_pos] : 0); + } } } - async command error_t UartStream.enableReceiveInterrupt() - { - if (!robuf) - call Registers.clrIfgRx(); - call Registers.setIeRx(); - rxie = FALSE; - return SUCCESS; - } - - async command error_t UartStream.disableReceiveInterrupt() + async command error_t SpiPacket.send(uint8_t* txBuf, uint8_t* rxBuf, + uint16_t len) { - if (!robuf) { - call Registers.clrIeRx(); - call Registers.clrIfgRx(); - } else - rxie = TRUE; - return SUCCESS; - } - - async command error_t UartByte.receive(uint8_t* byte, uint8_t timeout) - { - uint16_t t; - - /* FIXME: race with UartStream.receive() */ - if (robuf || !byte) + if (isBusy() || (!txBuf && !rxBuf) || len == 0) 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(); + else { + atomic { + m_txBuf = txBuf; + m_rxBuf = rxBuf; + m_len = len; + m_pos = 0; + call Registers.setIeRx(); + sendData(); return SUCCESS; } } - return FAIL; } - async command error_t UartStream.receive(uint8_t* buf, uint16_t len) + async event void Interrupts.tx() {} + + task void signalSendDone() { - if (robuf || !buf || !len) - return FAIL; - robuf = rbuf = buf; - rolen = rlen = len; - if (!call Registers.getIeRx()) { - call Registers.clrIfgRx(); - call Registers.setIeRx(); - rxie = TRUE; - } else - rxie = FALSE; + atomic { + signal SpiPacket.sendDone(m_txBuf, m_rxBuf, m_len, SUCCESS); + m_len = 0; + } } async event void Interrupts.rx(uint8_t byte) { - if (robuf) { - /* receive() takes precedence if active */ - while (rlen && call Registers.getIfgRx()) { - *rbuf = byte; - if (--rlen) - rbuf++; - } - if (rlen == 0 && robuf) { - if (rxie) { - call Registers.clrIeRx(); - call Registers.clrIfgRx(); - } - robuf = 0; - signal UartStream.receiveDone(robuf, rolen, SUCCESS); - } - } else - signal UartStream.receivedByte(byte); + if (m_rxBuf) + m_rxBuf[m_pos - 1] = call Registers.getRxbuf(); + else + call Registers.getRxbuf(); + + if (m_pos < m_len) + sendData(); + else { + call Registers.clrIeRx(); + post signalSendDone(); /* Don't signal from ISR context */ + } } + 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: UCMODE_0, /* async, lsb first, 8N1 */ - ctl1: UCSWRST|UCSSEL_1, /* clock spi from SMCLK */ - brx: UBRX_32768HZ_9600, - mctl: UMCTL_32768HZ_9600, /* ??? */ + 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 }; @@ -303,11 +317,4 @@ implementation { async event void Interrupts.i2cCal() {} async event void Interrupts.brk() {} async event void Interrupts.i2cNak() {} - 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 ) {} } diff --git a/tos/chips/msp430/usci/Msp430UartP.nc b/tos/chips/msp430/usci/Msp430UartP.nc index 35582046..17fbfd19 100644 --- a/tos/chips/msp430/usci/Msp430UartP.nc +++ b/tos/chips/msp430/usci/Msp430UartP.nc @@ -30,6 +30,9 @@ /** * Uart implementation using a USCI device. * + * TODO: Implement blocking like in Msp430UartSpiP.nc. + * Implement error checking via UCAxSTAT. + * * @author R. Steve McKown */ @@ -74,18 +77,22 @@ implementation { call pin.makeInput(); \ } - uint8_t dir; /* Pin state storage to allow for proper unconfiguration */ - uint8_t out; - uint8_t ren; - uint8_t* sobuf; /* Original buffer ptr from UartStream.send() */ - uint8_t solen; /* Original buffer len from UartStream.send() */ - uint8_t* sbuf; /* Position of next char to send */ - uint8_t slen; /* Len of chars in sbuf to send */ - bool rxie; /* Set if rxie has been enabled to UartStream.receive() */ - uint8_t* robuf; /* Original receive buffer */ - uint8_t rolen; /* Original (maximum) receive len */ - uint8_t* rbuf; /* Position of next byte in which to receive a char */ - uint8_t rlen; /* Remaining length in receive buffer */ + /* Pin IO configuration storage for later restoration */ + uint8_t m_dir; + uint8_t m_out; + uint8_t m_ren; + + uint8_t* m_sobuf; /* Original buffer ptr from UartStream.send() */ + uint8_t m_solen; /* Original buffer len from UartStream.send() */ + uint8_t* m_sbuf; /* Position of next char to send */ + uint8_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 */ + uint8_t m_rolen; /* Original (maximum) receive len */ + uint8_t* m_rbuf; /* Position of next byte in which to receive a char */ + uint8_t m_rlen; /* Remaining length in receive buffer */ + + sfrb(MYBRX, 219U); async command void ResourceConfigure.configure() { @@ -103,12 +110,15 @@ implementation { call Registers.assignIrtctl(config->irtctl); call Registers.assignIrrctl(config->irrctl); call Registers.assignAbctl(config->abctl); - call Registers.clrStat(UCLISTEN); + if (config->uclisten) + call Registers.setStat(UCLISTEN); + else + call Registers.clrStat(UCLISTEN); - /* Save pin IO states */ - dir = out = ren = 0; - saveBits(RXD, 0, dir, out, ren); - saveBits(TXD, 1, dir, out, ren); + /* Save pin IO configuration */ + m_dir = m_out = m_ren = 0; + saveBits(RXD, 0, m_dir, m_out, m_ren); + saveBits(TXD, 1, m_dir, m_out, m_ren); /* Configure RX pin for UART use */ call RXD.makeInput(); @@ -122,7 +132,7 @@ implementation { call RXD.selectModuleFunc(); #if 0 /* pull-ups don't make sense on TXD, since it doesn't appear that - * enabling an open-drain emulation mode via USCI is possible. + * enabling an open-drain emulation mode via USCI is not possible. */ /* Configure TX pin for UART use */ @@ -159,8 +169,8 @@ implementation { /* Restore pins to their preconfigured state */ #if 0 - restoreBits(RXD, 0, dir, out, ren); - restoreBits(TXD, 0, dir, out, ren); + restoreBits(RXD, 0, m_dir, m_out, m_ren); + restoreBits(TXD, 0, m_dir, m_out, m_ren); #endif call RXD.selectIOFunc(); call TXD.selectIOFunc(); @@ -171,9 +181,9 @@ implementation { { /* FIXME: race with UartStream.send() */ atomic { - if (sobuf) + if (m_sobuf) return FAIL; - while (call Registers.getStat(UCBUSY)); + while (!call Registers.getIfgTx()); call Registers.setTxbuf(byte); return SUCCESS; } @@ -181,40 +191,42 @@ implementation { async command error_t UartStream.send(uint8_t* buf, uint16_t len) { - if (sobuf || !buf || !len) - return FAIL; - sobuf = buf; - solen = len; - call Registers.setIeTx(); - call Registers.setTxbuf(*sobuf); - slen = solen - 1; - if (slen) - sbuf = sobuf + 1; - return SUCCESS; + atomic { + if (m_sobuf || !buf || !len) + return FAIL; + m_sobuf = buf; + m_solen = len; + call Registers.setIeTx(); + call Registers.setTxbuf(*m_sobuf); + m_slen = m_solen - 1; + if (m_slen) + m_sbuf = m_sobuf + 1; + return SUCCESS; + } } async event void Interrupts.tx() { - while (slen && call Registers.getIfgTx()) { - call Registers.setTxbuf(*sbuf); - if (--slen) - sbuf++; + while (m_slen && call Registers.getIfgTx()) { + call Registers.setTxbuf(*m_sbuf); + if (--m_slen) + m_sbuf++; } - if (slen == 0 && sobuf) { + if (m_slen == 0 && m_sobuf) { call Registers.clrIeTx(); call Registers.clrIfgTx(); - sobuf = 0; - signal UartStream.sendDone(sobuf, solen, SUCCESS); + m_sobuf = 0; + signal UartStream.sendDone(m_sobuf, m_solen, SUCCESS); } } async command error_t UartStream.enableReceiveInterrupt() { atomic { - if (!robuf) + if (!m_robuf) call Registers.clrIfgRx(); call Registers.setIeRx(); - rxie = FALSE; + m_rxie = FALSE; return SUCCESS; } } @@ -222,11 +234,11 @@ implementation { async command error_t UartStream.disableReceiveInterrupt() { atomic { - if (!robuf) { + if (!m_robuf) { call Registers.clrIeRx(); call Registers.clrIfgRx(); } else - rxie = TRUE; + m_rxie = TRUE; return SUCCESS; } } @@ -237,7 +249,7 @@ implementation { uint16_t t; /* FIXME: race with UartStream.receive() */ - if (robuf || !byte) + if (m_robuf || !byte) return FAIL; /* TODO: implement timeout, byte-time units. For now, 1-2 sec */ t = TBR; @@ -254,36 +266,36 @@ implementation { async command error_t UartStream.receive(uint8_t* buf, uint16_t len) { atomic { - if (robuf || !buf || !len) + if (m_robuf || !buf || !len) return FAIL; - robuf = rbuf = buf; - rolen = rlen = len; + m_robuf = m_rbuf = buf; + m_rolen = m_rlen = len; if (!call Registers.getIeRx()) { call Registers.clrIfgRx(); call Registers.setIeRx(); - rxie = TRUE; + m_rxie = TRUE; } else - rxie = FALSE; + m_rxie = FALSE; } } async event void Interrupts.rx(uint8_t byte) { atomic { - if (robuf) { + if (m_robuf) { /* receive() takes precedence if active */ - while (rlen && call Registers.getIfgRx()) { - *rbuf = byte; - if (--rlen) - rbuf++; + while (m_rlen && call Registers.getIfgRx()) { + *m_rbuf = byte; + if (--m_rlen) + m_rbuf++; } - if (rlen == 0 && robuf) { - if (rxie) { + if (m_rlen == 0 && m_robuf) { + if (m_rxie) { call Registers.clrIeRx(); call Registers.clrIfgRx(); } - robuf = 0; - signal UartStream.receiveDone(robuf, rolen, SUCCESS); + m_robuf = 0; + signal UartStream.receiveDone(m_robuf, m_rolen, SUCCESS); } } else signal UartStream.receivedByte(byte); @@ -294,12 +306,13 @@ implementation { { const static msp430_usci_uart_t def = { ctl0: UCMODE_0, /* async, lsb first, 8N1 */ - ctl1: UCSWRST|UCSSEL_3, /* clock uart from SMCLK */ + 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 }; diff --git a/tos/chips/msp430/usci/Msp430Usci.h b/tos/chips/msp430/usci/Msp430Usci.h index 50a0ca72..98c916d0 100644 --- a/tos/chips/msp430/usci/Msp430Usci.h +++ b/tos/chips/msp430/usci/Msp430Usci.h @@ -60,13 +60,35 @@ typedef enum typedef enum { USCI_REN_NONE = 0, - USCI_REN_RX = 0x08, - USCI_REN_RX_PULLUP = USCI_REN_RX + 0x01, - USCI_REN_RX_PULLDOWN = USCI_REN_RX + 0x02, + /* 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, - USCI_REN_TX = 0x80, - USCI_REN_TX_PULLUP = USCI_REN_TX + 0x10, - USCI_REN_TX_PULLDOWN = USCI_REN_TX + 0x20 + /* 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. */ @@ -91,16 +113,17 @@ typedef struct { uint8_t irtctl; uint8_t irrctl; uint8_t abctl; + bool uclisten; msp430_ren_t ren; -} __attribute__ ((packed)) msp430_usci_uart_t; +} msp430_usci_uart_t; typedef struct { uint8_t ctl0; uint8_t ctl1; uint16_t brx; - uint8_t mctl; /* ??? */ + bool uclisten; msp430_ren_t ren; -} __attribute__ ((packed)) msp430_usci_spi_t; +} msp430_usci_spi_t; typedef struct { uint8_t ctl0; @@ -109,7 +132,8 @@ typedef struct { uint8_t i2cie; uint8_t i2coa; uint8_t i2csa; + bool uclisten; msp430_ren_t ren; -} __attribute__ ((packed)) msp430_usci_i2c_t; +} msp430_usci_i2c_t; #endif diff --git a/tos/chips/msp430/usci/Msp430UsciA0C.nc b/tos/chips/msp430/usci/Msp430UsciA0C.nc index 2dffb832..5a5d1bd5 100644 --- a/tos/chips/msp430/usci/Msp430UsciA0C.nc +++ b/tos/chips/msp430/usci/Msp430UsciA0C.nc @@ -41,7 +41,7 @@ configuration Msp430UsciA0C { interface ResourceRequested as ResourceRequested[uint8_t]; interface ArbiterInfo; } - uses interface ResourceConfig as ResourceConfig[uint8_t]; + uses interface ResourceConfigure as ResourceConfigure[uint8_t]; } implementation { components new FcfsArbiterC(MSP430_USCIA0_RESOURCE) as ArbiterC; diff --git a/tos/chips/msp430/usci/Msp430UsciB0C.nc b/tos/chips/msp430/usci/Msp430UsciB0C.nc index a69c6fc9..e626fb16 100644 --- a/tos/chips/msp430/usci/Msp430UsciB0C.nc +++ b/tos/chips/msp430/usci/Msp430UsciB0C.nc @@ -41,7 +41,7 @@ configuration Msp430UsciB0C { interface ResourceRequested as ResourceRequested[uint8_t]; interface ArbiterInfo; } - uses interface ResourceConfig as ResourceConfig[uint8_t]; + uses interface ResourceConfigure as ResourceConfigure[uint8_t]; } implementation { components new FcfsArbiterC(MSP430_USCIB0_RESOURCE) as ArbiterC; diff --git a/tos/chips/msp430/usci/Msp430UsciB1C.nc b/tos/chips/msp430/usci/Msp430UsciB1C.nc index eec445f7..887af9d9 100644 --- a/tos/chips/msp430/usci/Msp430UsciB1C.nc +++ b/tos/chips/msp430/usci/Msp430UsciB1C.nc @@ -41,7 +41,7 @@ configuration Msp430UsciB1C { interface ResourceRequested as ResourceRequested[uint8_t]; interface ArbiterInfo; } - uses interface ResourceConfig as ResourceConfig[uint8_t]; + uses interface ResourceConfigure as ResourceConfigure[uint8_t]; } implementation { components new FcfsArbiterC(MSP430_USCIB1_RESOURCE) as ArbiterC;