From 9b58ecb229fe2466638908e2e3c28f66f0439116 Mon Sep 17 00:00:00 2001 From: smckown Date: Mon, 8 Sep 2008 16:34:32 +0000 Subject: [PATCH] More USCI work. --- tos/chips/msp430/usci/HplMsp430UsciC.nc | 29 ++-- tos/chips/msp430/usci/HplMsp430UsciInt.nc | 6 +- tos/chips/msp430/usci/HplMsp430UsciIntP.nc | 11 +- tos/chips/msp430/usci/HplMsp430UsciReg.nc | 53 +++---- tos/chips/msp430/usci/HplMsp430UsciRegP.nc | 137 ++++++++++-------- tos/chips/msp430/usci/Msp430SpiB1C.nc | 2 + tos/chips/msp430/usci/Msp430UartA0C.nc | 2 + tos/chips/msp430/usci/Msp430UartA1C.nc | 75 ++++++++++ tos/chips/msp430/usci/Msp430UartP.nc | 90 ++++++++++-- tos/chips/msp430/usci/Msp430Usci.h | 65 +++++++-- tos/chips/msp430/usci/Msp430UsciA1C.nc | 2 +- tos/chips/msp430/usci/Msp430UsciConfigure.nc | 40 +++++ .../msp430/usci/Msp430UsciIntDispatchP.nc | 8 +- 13 files changed, 378 insertions(+), 142 deletions(-) create mode 100644 tos/chips/msp430/usci/Msp430UartA1C.nc create mode 100644 tos/chips/msp430/usci/Msp430UsciConfigure.nc diff --git a/tos/chips/msp430/usci/HplMsp430UsciC.nc b/tos/chips/msp430/usci/HplMsp430UsciC.nc index c6ac8b24..f8f84a9e 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciC.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciC.nc @@ -47,7 +47,7 @@ configuration HplMsp430UsciC { provides { -#if defined(__MSP430_HAS_USCIAB0__) || defined(__MSP430_HAS_USCI__) +#if defined(__MSP430_HAS_USCI_AB0__) || defined(__MSP430_HAS_USCI__) interface HplMsp430UsciReg as RegA0; interface HplMsp430UsciInt as IntA0; interface HplMsp430UsciReg as RegB0; @@ -62,11 +62,12 @@ configuration HplMsp430UsciC { } } implementation { -#if defined(__MSP430_HAS_USCI__) +#if defined(__MSP430_HAS_USCI_AB0__) components new HplMsp430UsciRegP(UCA0CTL0_, UCA0CTL1_, UCA0BR0_, UCA0BR1_, UCA0MCTL_, 0/*UCA0I2CIE_*/, UCA0STAT_, UCA0RXBUF_, UCA0TXBUF_, UCA0ABCTL_, UCA0IRTCTL_, UCA0IRRCTL_, 0/*UCA0I2COA_*/, 0/*UCA0I2CSA_*/, IE2_, IFG2_, - UCA0RXIFG, UCA0TXIFG) as RegA0P; + UCA0RXIFG, UCA0TXIFG) + as RegA0P; RegA0 = RegA0P.Reg; components new HplMsp430UsciRegP(UCB0CTL0_, UCB0CTL1_, UCB0BR0_, UCB0BR1_, @@ -75,19 +76,16 @@ implementation { UCB0I2CSA_, IE2_, IFG2_, UCB0RXIFG, UCB0TXIFG) as RegB0P; RegB0 = RegB0P.Reg; - components new HplMsp430UsciIntP(USCIRX_VECTOR, USCITX_VECTOR, UCA0RXIFG, - UCA0TXIFG, UCB0RXIFG, UCB0TXIFG, UCA0CTL0_, UCA0CTL1_, UCA0RXBUF_, - UCB0CTL0_, UCB0CTL1_, UCB0RXBUF_, IFG2_) as Int0P; + components new HplMsp430UsciIntP(USCIAB0RX_VECTOR, USCIAB0TX_VECTOR, + UCA0RXIFG, UCA0TXIFG, UCB0RXIFG, UCB0TXIFG, UCA0CTL0_, UCA0CTL1_, + UCA0RXBUF_, UCB0CTL0_, UCB0CTL1_, UCB0RXBUF_, IFG2_) as Int0P; IntA0 = Int0P.IntA; IntB0 = Int0P.IntB; - -#elif defined(__MSP430_HAS_USCIAB0__) - +#elif defined(__MSP430_HAS_USCI__) components new HplMsp430UsciRegP(UCA0CTL0_, UCA0CTL1_, UCA0BR0_, UCA0BR1_, UCA0MCTL_, 0/*UCA0I2CIE_*/, UCA0STAT_, UCA0RXBUF_, UCA0TXBUF_, UCA0ABCTL_, UCA0IRTCTL_, UCA0IRRCTL_, 0/*UCA0I2COA_*/, 0/*UCA0I2CSA_*/, IE2_, IFG2_, - UCA0RXIFG, UCA0TXIFG) - as RegA0P; + UCA0RXIFG, UCA0TXIFG) as RegA0P; RegA0 = RegA0P.Reg; components new HplMsp430UsciRegP(UCB0CTL0_, UCB0CTL1_, UCB0BR0_, UCB0BR1_, @@ -96,14 +94,14 @@ implementation { UCB0I2CSA_, IE2_, IFG2_, UCB0RXIFG, UCB0TXIFG) as RegB0P; RegB0 = RegB0P.Reg; - components new HplMsp430UsciIntP(USCIAB0RX_VECTOR, USCIAB0TX_VECTOR, - UCA0RXIFG, UCA0TXIFG, UCB0RXIFG, UCB0TXIFG, UCA0CTL0_, UCA0CTL1_, - UCA0RXBUF_, UCB0CTL0_, UCB0CTL1_, UCB0RXBUF_, IFG2_) as Int0P; + components new HplMsp430UsciIntP(USCIRX_VECTOR, USCITX_VECTOR, UCA0RXIFG, + UCA0TXIFG, UCB0RXIFG, UCB0TXIFG, UCA0CTL0_, UCA0CTL1_, UCA0RXBUF_, + UCB0CTL0_, UCB0CTL1_, UCB0RXBUF_, IFG2_) as Int0P; IntA0 = Int0P.IntA; IntB0 = Int0P.IntB; #endif -#if defined(__MSP430_HAS_USCIAB1__) +#if defined(__MSP430_HAS_USCI_AB1__) components new HplMsp430UsciRegP(UCA1CTL0_, UCA1CTL1_, UCA1BR0_, UCA1BR1_, UCA1MCTL_, 0/*UCA1I2CIE_*/, UCA1STAT_, UCA1RXBUF_, UCA1TXBUF_, UCA1ABCTL_, UCA1IRTCTL_, UCA1IRRCTL_, 0/*UCA1I2COA_*/, 0/*UCA1I2CSA_*/, IE2_, IFG2_, @@ -122,4 +120,5 @@ implementation { IntA1 = Int1P.IntA; IntB1 = Int1P.IntB; #endif +#endif } diff --git a/tos/chips/msp430/usci/HplMsp430UsciInt.nc b/tos/chips/msp430/usci/HplMsp430UsciInt.nc index 19e1e6df..6b73960e 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciInt.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciInt.nc @@ -37,7 +37,7 @@ * @author R. Steve McKown */ -#include "msp430usci.h" +#include "Msp430Usci.h" interface HplMsp430UsciInt { /** @@ -51,9 +51,9 @@ interface HplMsp430UsciInt { * Signals a character received for any USCI mode. The provider must reset * UCxIFG.UCxxRXIFG before signalling the event to the user. * - * @params c The character received. + * @params byte The character received. */ - async event void rx(char c); + async event void rx(uint8_t byte); /** * Signals that the device's transmit buffer is empty and can accept diff --git a/tos/chips/msp430/usci/HplMsp430UsciIntP.nc b/tos/chips/msp430/usci/HplMsp430UsciIntP.nc index dd17fd3a..a418bb27 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciIntP.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciIntP.nc @@ -33,9 +33,10 @@ * @author R. Steve McKown */ -#include "msp430usci.h" +#include "Msp430Usci.h" +#include "msp430hardware.h" -generic module HplMsp430UsciIntP( +module HplMsp430UsciInt0P( uint8_t USCIABxRX_VECTOR, uint8_t USCIABxTX_VECTOR, uint8_t UCAxRXIFG, @@ -51,8 +52,8 @@ generic module HplMsp430UsciIntP( uint8_t Ucxifg_addr ) @safe() { provides { - interface HplMsp430UsciInt as IntA; /* Interrupts for USCI_Ax */ - interface HplMsp430UsciInt as IntB; /* Interrupts for USCI_Bx */ + interface HplMsp430UsciInt as IntA; /* Interrupts for USCI_A0 */ + interface HplMsp430UsciInt as IntB; /* Interrupts for USCI_B0 */ } } @@ -66,6 +67,7 @@ implementation #define UCBxCTL1 (*TCAST(volatile uint8_t* ONE, Ucbxctl1_addr)) #define UCBxRXBUF (*TCAST(volatile uint8_t* ONE, Ucbxrxbuf_addr)) +#if 0 MSP430REG_NORACE(UCxIFG); MSP430REG_NORACE(UCAxCTL0); MSP430REG_NORACE(UCAxCTL1); @@ -73,6 +75,7 @@ implementation MSP430REG_NORACE(UCBxCTL0); MSP430REG_NORACE(UCBxCTL1); MSP430REG_NORACE(UCBxRXBUF); +#endif /* This USCI_Ax and USCI_Bx interrupt vector signals receive events for UART * and SPI modes, and status events for I2C modes. Only Bx can do I2C. diff --git a/tos/chips/msp430/usci/HplMsp430UsciReg.nc b/tos/chips/msp430/usci/HplMsp430UsciReg.nc index 1d338485..3f4536c8 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciReg.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciReg.nc @@ -39,7 +39,7 @@ interface HplMsp430UsciReg { /** * Return the current mode. */ - command msp430usci_mode_t getMode(); + command msp430_usci_mode_t getMode(); /** * Prepare to set the mode. If the device supports the requested mode, its @@ -57,7 +57,7 @@ interface HplMsp430UsciReg { * * @return The pointer to the device's UCxxCTL0 register. */ - command uint8_t* ptrCtl0(); + command volatile uint8_t* ptrCtl0(); /** * Get bits from the UCxxCTL0 register associated with the USCI device. @@ -96,7 +96,7 @@ interface HplMsp430UsciReg { * Manipulate bits in the UCxxCTL1 register. See the methods that manipulate * UCxxCTL0 for more information. */ - command uint8_t* ptrCtl1(uint8_t mask); + command volatile uint8_t* ptrCtl1(); command uint8_t getCtl1(uint8_t mask); command void setCtl1(uint8_t mask); command void clrCtl1(uint8_t mask); @@ -106,7 +106,7 @@ interface HplMsp430UsciReg { * Manipulate bits in the UCxxBR0 register. See the methods that manipulate * UCxxCTL0 for more information. */ - command uint8_t* ptrBr0(uint8_t mask); + command volatile uint8_t* ptrBr0(); command uint8_t getBr0(uint8_t mask); command void setBr0(uint8_t mask); command void clrBr0(uint8_t mask); @@ -116,7 +116,7 @@ interface HplMsp430UsciReg { * Manipulate bits in the UCxxBR1 register. See the methods that manipulate * UCxxCTL0 for more information. */ - command uint8_t* ptrBr1(uint8_t mask); + command volatile uint8_t* ptrBr1(); command uint8_t getBr1(uint8_t mask); command void setBr1(uint8_t mask); command void clrBr1(uint8_t mask); @@ -127,7 +127,7 @@ interface HplMsp430UsciReg { * UCxxCTL0 for more information. These methods perform no operation on * providers implementing a USCI_Bx device. */ - command uint8_t* ptrMctl(uint8_t mask); + command volatile uint8_t* ptrMctl(); command uint8_t getMctl(uint8_t mask); command void setMctl(uint8_t mask); command void clrMctl(uint8_t mask); @@ -138,7 +138,7 @@ interface HplMsp430UsciReg { * manipulate UCxxCTL0 for more information. These methods perform no * operation on providers implementing a USCI_Ax device. */ - command uint8_t* ptrI2Cie(uint8_t mask); + command volatile uint8_t* ptrI2Cie(); command uint8_t getI2Cie(uint8_t mask); command void setI2Cie(uint8_t mask); command void clrI2Cie(uint8_t mask); @@ -148,7 +148,7 @@ interface HplMsp430UsciReg { * Manipulate bits in the UCxxSTAT register. See the methods that manipulate * UCxxCTL0 for more information. */ - command uint8_t* ptrStat(uint8_t mask); + command volatile uint8_t* ptrStat(); command uint8_t getStat(uint8_t mask); command void setStat(uint8_t mask); command void clrStat(uint8_t mask); @@ -157,7 +157,7 @@ interface HplMsp430UsciReg { /** * Return pointer to the UCAxxRXBUF register used by the USCI device. */ - command uint8_t* ptrRxbuf(); + command volatile uint8_t* ptrRxbuf(); /** * Read the contents of the UCAxxRXBUF register. This register cannot be @@ -168,7 +168,7 @@ interface HplMsp430UsciReg { /** * Return pointer to the UCAxxTXBUF register used by the USCI device. */ - command uint8_t* ptrTxbuf(); + command volatile uint8_t* ptrTxbuf(); /** * Read the contents of the UCAxxTXBUF register. @@ -185,7 +185,7 @@ interface HplMsp430UsciReg { * manipulate UCxxCTL0 for more information. These methods perform no * operation on providers implementing a USCI_Bx device. */ - command uint8_t* ptrAbctl(uint8_t mask); + command volatile uint8_t* ptrAbctl(); command uint8_t getAbctl(uint8_t mask); command void setAbctl(uint8_t mask); command void clrAbctl(uint8_t mask); @@ -196,7 +196,7 @@ interface HplMsp430UsciReg { * manipulate UCxxCTL0 for more information. These methods perform no * operation on providers implementing a USCI_Bx device. */ - command uint8_t* ptrIrtctl(uint8_t mask); + command volatile uint8_t* ptrIrtctl(); command uint8_t getIrtctl(uint8_t mask); command void setIrtctl(uint8_t mask); command void clrIrtctl(uint8_t mask); @@ -207,7 +207,7 @@ interface HplMsp430UsciReg { * manipulate UCxxCTL0 for more information. These methods perform no * operation on providers implementing a USCI_Bx device. */ - command uint8_t* ptrIrrctl(uint8_t mask); + command volatile uint8_t* ptrIrrctl(); command uint8_t getIrrctl(uint8_t mask); command void setIrrctl(uint8_t mask); command void clrIrrctl(uint8_t mask); @@ -218,7 +218,7 @@ interface HplMsp430UsciReg { * manipulate UCxxCTL0 for more information. These methods perform no * operation on providers implementing a USCI_Ax device. */ - command uint8_t* ptrI2Coa(uint8_t mask); + command volatile uint8_t* ptrI2Coa(); command uint8_t getI2Coa(uint8_t mask); command void setI2Coa(uint8_t mask); command void clrI2Coa(uint8_t mask); @@ -229,7 +229,7 @@ interface HplMsp430UsciReg { * manipulate UCxxCTL0 for more information. These methods perform no * operation on providers implementing a USCI_Ax device. */ - command uint8_t* ptrI2Csa(uint8_t mask); + command volatile uint8_t* ptrI2Csa(); command uint8_t getI2Csa(uint8_t mask); command void setI2Csa(uint8_t mask); command void clrI2Csa(uint8_t mask); @@ -239,19 +239,22 @@ interface HplMsp430UsciReg { * Manipulate bits in the UCxxIE register. See the methods that manipulate * UCxxCTL0 for more information. */ - command uint8_t* ptrIe(uint8_t mask); - command uint8_t getIe(uint8_t mask); - command void setIe(uint8_t mask); - command void clrIe(uint8_t mask); - command void assignIe(uint8_t mask, uint8_t value); + command bool getIeRx(); + command void setIeRx(); + command void clrIeRx(); + command bool getIeTx(); + command void setIeTx(); + command void clrIeTx(); /** * Manipulate bits in the UCxxIFG register. See the methods that manipulate * UCxxCTL0 for more information. */ - command uint8_t* ptrIfg(uint8_t mask); - command uint8_t getIfg(uint8_t mask); - command void setIfg(uint8_t mask); - command void clrIfg(uint8_t mask); - command void assignIfg(uint8_t mask, uint8_t value); + command bool getIfgRx(); + command void setIfgRx(); + command void clrIfgRx(); + command bool getIfgTx(); + command void setIfgTx(); + command void clrIfgTx(); + } diff --git a/tos/chips/msp430/usci/HplMsp430UsciRegP.nc b/tos/chips/msp430/usci/HplMsp430UsciRegP.nc index d67123ce..cde8ae1a 100644 --- a/tos/chips/msp430/usci/HplMsp430UsciRegP.nc +++ b/tos/chips/msp430/usci/HplMsp430UsciRegP.nc @@ -37,27 +37,28 @@ * @author R. Steve McKown */ -#include "msp430usci.h" +#include "Msp430Usci.h" +#include "msp430hardware.h" generic module HplMsp430UsciRegP( - uint8_t Ctl0_addr, - uint8_t Ctl1_addr, - uint8_t Br0_addr, - uint8_t Br1_addr, - uint8_t Mctl_addr, /* A devices only */ - uint8_t I2Cie_addr, /* B devices only */ - uint8_t Stat_addr, - uint8_t Rxbuf_addr, - uint8_t Txbuf_addr, - uint8_t Abctl_addr, /* A devices only */ - uint8_t Irtctl_addr, /* A devices only */ - uint8_t Irrctl_addr, /* A devices only */ - uint8_t I2Coa_addr, /* B devices only */ - uint8_t I2Csa_addr, /* B devices only */ - uint8_t Ie_addr, - uint8_t Ifg_addr, - uint8_t UCAxRXIFG, /* We rely on xIE and xIFG at same bit positions */ - uint8_t UCAxTXIFG, + uint16_t Ctl0_addr, + uint16_t Ctl1_addr, + uint16_t Br0_addr, + uint16_t Br1_addr, + uint16_t Mctl_addr, /* A devices only */ + uint16_t I2Cie_addr, /* B devices only */ + uint16_t Stat_addr, + uint16_t Rxbuf_addr, + uint16_t Txbuf_addr, + uint16_t Abctl_addr, /* A devices only */ + uint16_t Irtctl_addr, /* A devices only */ + uint16_t Irrctl_addr, /* A devices only */ + uint16_t I2Coa_addr, /* B devices only */ + 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 ) @safe() { provides interface HplMsp430UsciReg as Registers; } @@ -88,53 +89,62 @@ implementation (reg = ((reg) & ~(mask)) | ((value) & (mask))) #define RENDER(name) \ + command volatile uint8_t* Registers.ptr##name() { \ + return &UCxx##name; \ + } \ command uint8_t Registers.get##name(uint8_t mask) { \ return READ_FLAG(UCxx##name, mask); \ } \ command void Registers.set##name(uint8_t mask) { \ - return SET_FLAG(UCxx##name, mask); \ + SET_FLAG(UCxx##name, mask); \ } \ command void Registers.clr##name(uint8_t mask) { \ - return CLR_FLAG(UCxx##name, mask); \ + CLR_FLAG(UCxx##name, mask); \ } \ command void Registers.assign##name(uint8_t mask, uint8_t value) { \ - return ASSIGNBITS(UCxx##name, mask, value); \ + ASSIGNBITS(UCxx##name, mask, value); \ } #define RENDER_A(name) \ + command volatile uint8_t* Registers.ptr##name() { \ + return &UCAx##name; \ + } \ command uint8_t Registers.get##name(uint8_t mask) { \ if (IS_USCI_Ax) \ return READ_FLAG(UCAx##name, mask); \ } \ command void Registers.set##name(uint8_t mask) { \ if (IS_USCI_Ax) \ - return SET_FLAG(UCAx##name, mask); \ + SET_FLAG(UCAx##name, mask); \ } \ command void Registers.clr##name(uint8_t mask) { \ if (IS_USCI_Ax) \ - return CLR_FLAG(UCAx##name, mask); \ + CLR_FLAG(UCAx##name, mask); \ } \ command void Registers.assign##name(uint8_t mask, uint8_t value) { \ if (IS_USCI_Ax) \ - return ASSIGNBITS(UCAx##name, mask, value); \ + ASSIGNBITS(UCAx##name, mask, value); \ } #define RENDER_B(name) \ + command volatile uint8_t* Registers.ptr##name() { \ + return &UCBx##name; \ + } \ command uint8_t Registers.get##name(uint8_t mask) { \ if (IS_USCI_Bx) \ return READ_FLAG(UCBx##name, mask); \ } \ command void Registers.set##name(uint8_t mask) { \ if (IS_USCI_Bx) \ - return SET_FLAG(UCBx##name, mask); \ + SET_FLAG(UCBx##name, mask); \ } \ command void Registers.clr##name(uint8_t mask) { \ if (IS_USCI_Bx) \ - return CLR_FLAG(UCBx##name, mask); \ + CLR_FLAG(UCBx##name, mask); \ } \ command void Registers.assign##name(uint8_t mask, uint8_t value) { \ if (IS_USCI_Bx) \ - return ASSIGNBITS(UCBx##name, mask, value); \ + ASSIGNBITS(UCBx##name, mask, value); \ } #if 0 @@ -157,25 +167,25 @@ implementation MSP430REG_NORACE(UCxIfg); #endif - command msp430usci_mode_t Registers.getMode() + command msp430_usci_mode_t Registers.getMode() { if (READ_FLAG(UCxxCtl0, UCSYNC)) { - if (READ_FLAG(UCxxCtl0 == UCMODE_3)) - return UCSYNC_I2C; + if (READ_FLAG(UCxxCtl0, UCMODE_3) == UCMODE_3) + return USCI_I2C; else - return UCSYNC_SPI; + return USCI_SPI; } else { - return UCSYNC_UART; + return USCI_UART; } } command bool Registers.setMode(msp430_usci_mode_t mode) { - if (mode == UCSYNC_UART && IS_USCI_Bx) + if (mode == USCI_UART && IS_USCI_Bx) return FALSE; - if (mode == UCI2C && IS_USCI_Ax) + if (mode == USCI_I2C && IS_USCI_Ax) return FALSE; - SET_FLAG(UCxxCtl0, UCSYNC) + SET_FLAG(UCxxCtl0, UCSYNC); } RENDER(Ctl0); @@ -187,30 +197,30 @@ implementation RENDER(Stat); /* RENDER(Rxbuf); */ - command uint8_t* Registers.ptrRxbuf() + command volatile uint8_t* Registers.ptrRxbuf() { - return UCxxRXBuf; + return &UCxxRxbuf; } command uint8_t Registers.getRxbuf() { - return UCxxRXBuf; + return UCxxRxbuf; } /* RENDER(Txbuf); */ - command uint8_t* Registers.ptrTxbuf() + command volatile uint8_t* Registers.ptrTxbuf() { - return UCxxTXBuf; + return &UCxxTxbuf; } command uint8_t Registers.getTxbuf() { - return UCxxTXBuf; + return UCxxTxbuf; } command void Registers.setTxbuf(uint8_t byte) { - UCxxTXBuf = byte; + UCxxTxbuf = byte; } RENDER_A(Abctl); @@ -220,65 +230,64 @@ implementation RENDER_B(I2Csa); /* RENDER(Ie); */ - command bool getIeRx() + command bool Registers.getIeRx() { return READ_FLAG(UCxxIe, UCAxRXIFG); } - command void setIeRx() + command void Registers.setIeRx() { - return SET_FLAG(UCxxIe, UCAxRXIFG); + SET_FLAG(UCxxIe, UCAxRXIFG); } - command void clrIeRx() + command void Registers.clrIeRx() { - return CLR_FLAG(UCxxIe, UCAxRXIFG); + CLR_FLAG(UCxxIe, UCAxRXIFG); } - command bool getIeTx() + command bool Registers.getIeTx() { return READ_FLAG(UCxxIe, UCAxTXIFG); } - command void setIeTx() + command void Registers.setIeTx() { - return SET_FLAG(UCxxIe, UCAxTXIFG); + SET_FLAG(UCxxIe, UCAxTXIFG); } - command void clrIeTx() + command void Registers.clrIeTx() { - return CLR_FLAG(UCxxIe, UCAxTXIFG); + CLR_FLAG(UCxxIe, UCAxTXIFG); } /* RENDER(Ifg); */ - command bool getIeRx() + command bool Registers.getIfgRx() { return READ_FLAG(UCxxIfg, UCAxRXIFG); } - command void setIfgRx() + command void Registers.setIfgRx() { - return SET_FLAG(UCxxIfg, UCAxRXIFG); + SET_FLAG(UCxxIfg, UCAxRXIFG); } - command void clrIfgRx() + command void Registers.clrIfgRx() { - return CLR_FLAG(UCxxIfg, UCAxRXIFG); + CLR_FLAG(UCxxIfg, UCAxRXIFG); } - command bool getIfgTx() + command bool Registers.getIfgTx() { return READ_FLAG(UCxxIfg, UCAxTXIFG); } - command void setIfgTx() + command void Registers.setIfgTx() { - return SET_FLAG(UCxxIfg, UCAxTXIFG); + SET_FLAG(UCxxIfg, UCAxTXIFG); } - command void clrIfgTx() + command void Registers.clrIfgTx() { - return CLR_FLAG(UCxxIfg, UCAxTXIFG); + CLR_FLAG(UCxxIfg, UCAxTXIFG); } - } diff --git a/tos/chips/msp430/usci/Msp430SpiB1C.nc b/tos/chips/msp430/usci/Msp430SpiB1C.nc index 980f637f..0e20f519 100644 --- a/tos/chips/msp430/usci/Msp430SpiB1C.nc +++ b/tos/chips/msp430/usci/Msp430SpiB1C.nc @@ -38,6 +38,8 @@ #error "Target does not have a USCI_B1 peripheral (SPI)" #endif +#include "Msp430Usci.h" + configuration Msp430SpiB1C { provides { interface Resource; diff --git a/tos/chips/msp430/usci/Msp430UartA0C.nc b/tos/chips/msp430/usci/Msp430UartA0C.nc index 6bb97095..b9e6073c 100644 --- a/tos/chips/msp430/usci/Msp430UartA0C.nc +++ b/tos/chips/msp430/usci/Msp430UartA0C.nc @@ -38,6 +38,8 @@ #error "Target does not have a USCI_A0 peripheral (UART)" #endif +#include "Msp430Usci.h" + configuration Msp430UartA0C { provides { interface Resource; diff --git a/tos/chips/msp430/usci/Msp430UartA1C.nc b/tos/chips/msp430/usci/Msp430UartA1C.nc new file mode 100644 index 00000000..558a29b5 --- /dev/null +++ b/tos/chips/msp430/usci/Msp430UartA1C.nc @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2008, Titanium Mirror, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - 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 + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This configuration provides the interface for using USCI_A1 in its UART + * mode. + * + * @author R. Steve McKown + */ + +#if !defined(__MSP430_HAS_USCI_AB0__) +#error "Target does not have a USCI_A1 peripheral (UART)" +#endif + +#include "Msp430Usci.h" + +configuration Msp430UartA1C { + provides { + interface Resource; + interface ResourceRequested; + interface UartStream; + interface UartByte; + interface ArbiterInfo; /* ??? */ + } + uses interface Msp430UsciConfigure; +} +implementation { + enum { + CLIENT_ID = unique(MSP430_USCIA1_RESOURCE) + }; + + components new Msp430UartP() as UartP; + UartStream = UartP; + UartByte = UartP; + Msp430UsciConfigure = UartP; + + components new Msp430UsciA1C() as UsciC; + Resource = UsciC.Resource[CLIENT_ID]; + ResourceRequested = UsciC.ResourceRequested[CLIENT_ID]; + ArbiterInfo = UsciC.ArbiterInfo; + UartP -> UsciC.Registers; + UartP -> UsciC.Interrupts[CLIENT_ID]; + UartP -> UsciC.ArbiterInfo; + UsciC.ResourceConfigure[CLIENT_ID] -> UartP; + + components HplMsp430GeneralIOC as IOC; + UartP.RXD -> IOC.UCA1RXD; + UartP.TXD -> IOC.UCA1TXD; +} diff --git a/tos/chips/msp430/usci/Msp430UartP.nc b/tos/chips/msp430/usci/Msp430UartP.nc index f00e704f..550b1623 100644 --- a/tos/chips/msp430/usci/Msp430UartP.nc +++ b/tos/chips/msp430/usci/Msp430UartP.nc @@ -44,8 +44,8 @@ generic module Msp430UartP() { interface HplMsp430UsciInt as Interrupts; interface HplMsp430GeneralIO as RXD; interface HplMsp430GeneralIO as TXD; - interface Msp430UsciUartConfigure; /* maybe just Msp430UsciConfigure */ - interface Counter + interface Msp430UsciConfigure; + interface Counter; interface ArbiterInfo; } } @@ -87,43 +87,68 @@ implementation { uint8_t* rbuf; /* Position of next byte in which to receive a char */ uint8_t rlen; /* Remaining length in receive buffer */ - async command void ResourceConfigure.configure(); + async command void ResourceConfigure.configure() { + msp430_usci_config_t* config = call Msp430UsciConfigure.get(); + call Registers.setCtl0(UCSYNC); /* Save pin states */ dir = out = ren = 0; saveBits(RXD, 0, dir, out, ren); saveBits(TXD, 1, dir, out, ren); - /* FIXME: use Msp430UsciConfig to configure ports */ + + /* Configure USCI registers */ + call Registers.assignCtl0(0xff, config->uart.ctl0); + call Registers.assignCtl1(0xff, config->uart.ctl1|UCSWRST); + call Registers.assignBr0(0xff, config->uart.brx & 0xff); + call Registers.assignBr1(0xff, config->uart.brx >> 8); + call Registers.assignMctl(0xff, config->uart.mctl); + call Registers.assignIrtctl(0xff, config->uart.irtctl); + call Registers.assignIrrctl(0xff, config->uart.irrctl); + call Registers.assignAbctl(0xff, config->uart.abctl); /* FIXME: we may need to have REN/DIR stuff in the configuration... */ + + /* Configure pins for module function */ call RXD.selectModuleFunc(); call TXD.selectModuleFunc(); + /* Clear interrupts; we'll add them as needed */ call Registers.clrCtl1(UCRXEIE|UCBRKIE); call Registers.clrIeRx(); call Registers.clrIeTx(); + /* Enable the device */ call Registers.clrCtl0(UCSYNC); } - async command void ResourceConfigure.unconfigure(); + async command void ResourceConfigure.unconfigure() { /* Disable the device */ call Registers.setCtl0(UCSYNC); + /* Clear interrupts and interrupt flags */ call Registers.clrIeRx(); call Registers.clrIeTx(); call Registers.clrIfgRx(); call Registers.clrIfgTx(); - /* Restore pins to state just before configure() */ + + /* Restore pins to their preconfigured state */ restoreBits(RXD, 0, dir, out, ren); restoreBits(TXD, 0, dir, out, ren); call RXD.selectIOFunc(); call TXD.selectIOFunc(); } + async command error_t UartByte.send(uint8_t byte) + { + /* FIXME: race with UartStream.send() */ + if (sobuf) + return FAIL; + call Registers.setTxbuf(byte); + return SUCCESS; + } - async command error_t UartStream.send( uint8_t* buf, uint16_t len ) + async command error_t UartStream.send(uint8_t* buf, uint16_t len) { if (sobuf || !buf || !len) return FAIL; @@ -152,7 +177,7 @@ implementation { } } - async command error_t enableReceiveInterrupt() + async command error_t UartStream.enableReceiveInterrupt() { if (!robuf) call Registers.clrIfgRx(); @@ -161,7 +186,7 @@ implementation { return SUCCESS; } - async command error_t disableReceiveInterrupt() + async command error_t UartStream.disableReceiveInterrupt() { if (!robuf) { call Registers.clrIeRx(); @@ -171,13 +196,31 @@ implementation { return SUCCESS; } - async command error_t receive(uint8_t* buf, uint16_t len) + async command error_t UartByte.receive(uint8_t* byte, uint8_t timeout) + { + uint16_t t; + + /* FIXME: race with UartStream.receive() */ + if (robuf || !byte) + 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(); + return SUCCESS; + } + } + return FAIL; + } + + async command error_t UartStream.receive(uint8_t* buf, uint16_t len) { if (robuf || !buf || !len) return FAIL; robuf = rbuf = buf; rolen = rlen = len; - if (!call Registers.getIeRx) { + if (!call Registers.getIeRx()) { call Registers.clrIfgRx(); call Registers.setIeRx(); rxie = TRUE; @@ -205,4 +248,29 @@ implementation { } else signal UartStream.receivedByte(byte); } + + default async command msp430_usci_config_t* Msp430UsciConfigure.get() + { + static msp430_usci_config_t def = { + uart: { + ctl0: UCMODE_0, /* async, lsb first, 8N1 */ + ctl1: UCSWRST|UCSSEL_3, /* clock uart from SMCLK */ + brx: UBRX_1MHZ_9600, + mctl: UMCTL_1MHZ_9600, + irtctl: 0, + irrctl: 0, + abctl: 0 + /* FIXME: pullup/pulldown configuration... */ + } + }; + + return &def; + } + + async event void Interrupts.i2cStart() {} + async event void Interrupts.i2cStop() {} + async event void Interrupts.i2cCal() {} + async event void Interrupts.brk() {} + async event void Interrupts.i2cNak() {} + async event void Counter.overflow() {} } diff --git a/tos/chips/msp430/usci/Msp430Usci.h b/tos/chips/msp430/usci/Msp430Usci.h index d8a58938..4d0a2cd7 100644 --- a/tos/chips/msp430/usci/Msp430Usci.h +++ b/tos/chips/msp430/usci/Msp430Usci.h @@ -42,13 +42,13 @@ * @author R. Steve McKown */ -#ifndef MSP430USCI_h -#define MSP430USCI_h +#ifndef MSP430_USCI_h +#define MSP430_USCI_h -#define MSP430_HPLUSCIA0_RESOURCE "Msp430UsciA0.Resource" -#define MSP430_HPLUSCIB0_RESOURCE "Msp430UsciB0.Resource" -#define MSP430_HPLUSCIA1_RESOURCE "Msp430UsciA0.Resource" -#define MSP430_HPLUSCIB1_RESOURCE "Msp430UsciB0.Resource" +#define MSP430_USCIA0_RESOURCE "Msp430UsciA0.Resource" +#define MSP430_USCIB0_RESOURCE "Msp430UsciB0.Resource" +#define MSP430_USCIA1_RESOURCE "Msp430UsciA1.Resource" +#define MSP430_USCIB1_RESOURCE "Msp430UsciB1.Resource" /* Values of UCAxCTL0 only looking at the UCMODEx bits */ typedef enum @@ -58,6 +58,7 @@ typedef enum USCI_I2C } msp430_usci_mode_t; +#if 0 /* FIXME * There are different meanings to these fields based upon the mode * (uart/spi/etc) and the device (USCI_x0 or USCI_x1). @@ -73,7 +74,7 @@ typedef struct { unsigned int ucmsb: 1; /* MSB first select. 0=LSB(it) first, 1=MSB(it) first */ unsigned int ucpar: 1; /* Parity select. 0=odd parity, 1=even parity */ unsigned int ucpen: 1; /* Parity enable. 0=parity disabled, 1=parity enabled */ -} __attribute__ ((packed)) msp430_ucaxctl0_t ; +} __attribute__ ((packed)) msp430_usci_uart_ctl0_t ; typedef struct { unsigned int ucswrst: 1; // Software resent enable. 0=disabled (operational), 1=enabled (reset) */ @@ -82,8 +83,8 @@ typedef struct { unsigned int ucdorm: 1; // Dormant; USCI in sleep. 0=!dormant, 1=dormant */ unsigned int ucbrkie: 1; // Receive break sets UCAxRXIFG interrupt. 0=no, 1=yes */ unsigned int ucrxeie: 1; // Receive erroneous char sets UCAxRXIFG interrupt. 0=no, 1=yes */ - unsigned int ucucsselx: 2; // USCI clock source (BRCLK). 00=UCLK, 01=ACLK, 10=SMCLK, 11=SMCLK */ -} __attribute__ ((packed)) msp430_ucaxctl1_t; + unsigned int uccsselx: 2; // USCI clock source (BRCLK). 00=UCLK, 01=ACLK, 10=SMCLK, 11=SMCLK */ +} __attribute__ ((packed)) msp430_usci_uart_ctl1_t; typedef struct { unsigned int ucbusy:1; /* USCI busy; tx or rx in process. 0=no, 1=yes */ @@ -95,19 +96,19 @@ typedef struct { unsigned int ucoe:1; /* Overrun error flag. 0=no, 1=yes */ unsigned int ucfe:1; /* Framing error flag. 0=no, 1=yes */ unsigned int uclisten:1; /* Listen enable (loopback). 0=disabled, 1=enabled */ -} __attribute__ ((packed)) msp430_ucaxstat_t; +} __attribute__ ((packed)) msp430_usci_uart_stat_t; typdef struct { unsigned int uciren:1; /* IrDA decoder. 0=disabled, 1=enabled */ - unsigned int unirtxclk:1; /* IrDA transmit pulse clock select. 0=BRCLK, 1=BRCLK16 if ucos16=1 else BRCLK */ + unsigned int ucirtxclk:1; /* IrDA transmit pulse clock select. 0=BRCLK, 1=BRCLK16 if ucos16=1 else BRCLK */ unsigned ucirtxplx:6; /* Pulse length. t(pulse) = (ucirtxplx + 1)/(2 * f(irtxclk)) */ -} __attribute__ ((packed)) msp430_ucaxirtctl_t; +} __attribute__ ((packed)) msp430_usci_uart_irtctl_t; typedef struct { unsigned int ucirrxfe:1; /* IrDA recv filter. 0=disabled, 1=enabled */ unsigned int ucirrxpl:1; /* IrDA recv input ucaxrxd polarity. 0=high w/light pulse, 1=low */ unsigned int ucirrxflx:6; /* IrDA recv filter len. t(min) = (ucirrxflx + 4)/(2 * f(irtxclk)) */ -} __attribute__ ((packed)) msp430_ucaxirtctl_t; +} __attribute__ ((packed)) msp430_usci_uart_irrctl_t; typdef struct { unsigned int ucabden:1; /* Auto baud rate detect enable. 0=no, 1=yes (baud calc from break/sync) */ @@ -116,8 +117,42 @@ typdef struct { unsigned int ucstoe:1; /* Synch field timeout error. 0=no, 1=yes: sync len > measurable time */ unsigned int ucdelimx:1; /* Break/synch delimiter length in bit times. 00=1, 01=2, 10=3, 11=4 */ unsigned int reserved2:2; /* Reserved */ -} __attribute__ ((packed)) msp430_ucaxabctl_t; +} __attribute__ ((packed)) msp430_usci_uart_abctl_t; +#endif + +#if 0 /* We aren't using individual fields, but rather leveraging the defs + * provided by the compiler. Hence, bit fields aren't all that useful. + */ +typdef struct { + msp430_usci_uart_ctl0_t ctl0; + msp430_usci_uart_ctl0_t ctl1; + msp430_usci_uart_stat_t stat; + msp430_usci_uart_irtctl_t irtctl; + msp430_usci_uart_irrctl_t irrctl; + msp430_usci_uart_abctl_t abctl; +} __attribute__ ((packed)) msp430_usci_uart_t; +#else +typedef struct { + uint8_t ctl0; + uint8_t ctl1; + uint16_t brx; + uint8_t mctl; + uint8_t irtctl; + uint8_t irrctl; + uint8_t abctl; + /* FIXME: add support for configuring internal pull-up or pull-down on RXD pin */ +} __attribute__ ((packed)) msp430_usci_uart_t; +#endif + +/* Baud rates for UART mode */ +typedef enum { + /* UCOS16=0. UMCTL = UCBRFx << 4 + UCBRSx << 1 + UCOS16. */ + UBRX_1MHZ_9600=109, UMCTL_1MHZ_9600=(0 << 4) + (2 << 1) + 0, + UBRX_1MHZ_115200=9, UMCTL_1MHZ_115200=(0 << 4) + (1 << 1) + 0, +} msp430_usci_uart_rate_t; -/* FIXME: provide baud rate and configuration stuff */ +typedef union { + msp430_usci_uart_t uart; +} __attribute__ ((packed)) msp430_usci_config_t; #endif diff --git a/tos/chips/msp430/usci/Msp430UsciA1C.nc b/tos/chips/msp430/usci/Msp430UsciA1C.nc index 309c097b..bf9a9953 100644 --- a/tos/chips/msp430/usci/Msp430UsciA1C.nc +++ b/tos/chips/msp430/usci/Msp430UsciA1C.nc @@ -41,7 +41,7 @@ configuration Msp430UsciA1C { 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_USCIA1_RESOURCE) as ArbiterC; diff --git a/tos/chips/msp430/usci/Msp430UsciConfigure.nc b/tos/chips/msp430/usci/Msp430UsciConfigure.nc new file mode 100644 index 00000000..d7bab281 --- /dev/null +++ b/tos/chips/msp430/usci/Msp430UsciConfigure.nc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2008, Titanium Mirror, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - 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 + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Configuration interface for USCI devices. + * + * @author R. Steve McKown + */ + +#include "Msp430Usci.h" + +interface Msp430UsciConfigure { + async command msp430_usci_config_t* get(); +} diff --git a/tos/chips/msp430/usci/Msp430UsciIntDispatchP.nc b/tos/chips/msp430/usci/Msp430UsciIntDispatchP.nc index 3c776048..89424d32 100644 --- a/tos/chips/msp430/usci/Msp430UsciIntDispatchP.nc +++ b/tos/chips/msp430/usci/Msp430UsciIntDispatchP.nc @@ -34,7 +34,7 @@ */ generic module Msp430UsciIntDispatchP() @safe() { - provides interface HplMsp430UsciIntB as Interrupts[uint8_t id]; + provides interface HplMsp430UsciInt as Interrupts[uint8_t id]; uses { interface HplMsp430UsciInt as RawInt; interface ArbiterInfo; @@ -48,10 +48,10 @@ implementation { signal Interrupts.brk[call ArbiterInfo.userId()](); } - async event void RawInt.rx(char c) + async event void RawInt.rx(uint8_t byte) { if (call ArbiterInfo.inUse()) - signal Interrupts.rx[call ArbiterInfo.userId()](); + signal Interrupts.rx[call ArbiterInfo.userId()](byte); } async event void RawInt.tx() @@ -85,7 +85,7 @@ implementation { } default async event void Interrupts.brk[uint8_t id]() {} - default async event void Interrupts.rx[uint8_t id]() {} + default async event void Interrupts.rx[uint8_t id](uint8_t byte) {} default async event void Interrupts.tx[uint8_t id]() {} default async event void Interrupts.i2cCal[uint8_t id]() {} default async event void Interrupts.i2cNak[uint8_t id]() {} -- 2.39.2