Jump to content

amstan

Members
  • Content Count

    41
  • Joined

  • Last visited


Reputation Activity

  1. Like
    amstan reacted to Rickta59 in Full-duplex hardware UART for launchpad   
    Now that I have a freshly minted uniarch version of msp430-gcc, I wanted to test it out and make sure the newly added support for the msp430g2553 chip really worked. I took my softserial full duplex code and twisted it around some to take advantage of gcc. I also exercised some of my favorite features of gcc, specifically templates, just to make sure they work in the uniarch version.
     
    Yeah, as I get further into the msp430 world I've decided I don't really like TI's version of eclipse + CDT too much. Along my path to enlightenment I have left the CCS blanket and wrapped myself in the latest Eclipse+CDT (Helios) with msp430-gcc running on Ubuntu. Unfortunately, the code below probably won't compile with CCS. However, I'm sure at some point someone will port the uniarch version of mspgcc over to cygwin.
     
    One of the nice thing about the 2553 vs the 2231 is the 2553 chip has a hardware UART builtin. No more stolen TimerA cycles for me. I'm doing the serial dance with hardware now. Attached you will find the code and a Makefile.
     
    Notes about hardware USCI UART: You have to flip your TX/RX jumpers on your launchpad. This has been talked about elsewhere on the forums. I'm just using a couple of F-M jumper wires going to my msp430g2553 on a breadboard.
     
    You can read the announcement about uniarch and support for the newer chips over on the mailing list:
    http://sourceforge.net/mailarchive/foru ... pgcc-users
     
    The latest version of the following source code can be found here: https://gist.github.com/969447
     
    I took a snapshot of the code:

    /** * usci_serial.cpp - simple example using USCI UART + ringbuffer + command line monitor * * This code was written to test the new uniarch version of msp430-gcc. I wanted * to make sure it could generate code for the msp430g2553 running on the TI * launchpad. * * This code mplements a command line interface over the USB-CDC serial at * 9600-8-N-1. To test you must swap the RX/TX pins on your launchpad to use * the hardware USCI UART. I disconnected those jumpers on my launchpad and used * a couple of F-M jumper wires to run the msp430g2553 from a breadboard. * P1.1=RXD and P1.2=TXD ( this is the opposite of the msp430g2231 default setup ) * * * License: Do with this code what you want. However, don't blame * me if you connect it to a heart pump and it stops. This source * is provided as is with no warranties. It probably has bugs!! * You have been warned! * * Author: Rick Kimball * email: rick@kimballsoftware.com * Version: 1.00 Initial version 05-12-2011 */ #include #include #include #include "config.h" #include "ringbuffer.h" #include "usci_serial.h" /** * create a ring buffer that holds up to 16 uint8_t bytes * * Note: you could change the ringbuffer_ui8_16 typedef to * make it smaller or larger, just be consistent with what * you provide the Serial template */ ringbuffer_ui8_16 usci_buffer = { 0, 0, { 0 } }; Serial usci0 = { usci_buffer }; /** * USCI0RX_ISR - USCI UART receive character ISR handler * * we get an interrupt when a new character arrives via * the USCI UART receive pin. We just stuff it into * our buffer and let the main routine consume it. */ interrupt(USCIAB0RX_VECTOR) USCI0RX_ISR(void) { /** * Note: a side effect of reading UCA0RXBUF * is the rx interrupt flag is cleared */ usci_buffer.push_back(UCA0RXBUF); } /** * main - echo back to the user whatever they type */ int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = CALBC1_16MHZ; // set DCO clock for MCLK and SMCLK DCOCTL = CALDCO_16MHZ; usci0.init(); __bis_SR_register(GIE); // interrupts enabled usci0.xmit("\r\nMSP430G2553 Monitor\r\n$ "); while (true) { while (!usci0.empty()) { volatile int c; c = usci0.recv(); usci0.xmit((uint8_t) c); } } }
     

    /** * config.h - configure baud rates, MCLK frequency * * License: Do with this code what you want. However, don't blame * me if you connect it to a heart pump and it stops. This source * is provided as is with no warranties. It probably has bugs!! * You have been warned! * * Author: Rick Kimball * email: rick@kimballsoftware.com * Version: 1.00 Initial version 05-12-2011 */ #ifndef CONFIG_H_ #define CONFIG_H_ #define F_CPU 16000000 // use calibrated 16MHZ clock #ifdef __MSPGCC__ #define _enable_interrupts() __bis_status_register(GIE) #define _disable_interrupts() __bic_status_register(GIE) #endif #endif
     

    /* * ringbuffer.h - template for a circular buffer * * License: Do with this code what you want. However, don't blame * me if you connect it to a heart pump and it stops. This source * is provided as is with no warranties. It probably has bugs!! * You have been warned! * * Author: Rick Kimball * email: rick@kimballsoftware.com * Version: 1.00 Initial version 05-12-2011 */ #ifndef RINGBUFFER_H_ #define RINGBUFFER_H_ /** * ringbuffer - a template based interrupt safe circular buffer structure with functions */ template struct ringbuffer { volatile int head; volatile int tail; volatile T buffer[MAX_ITEMS]; /** * empty() - checks the buffer for data * * returns true if empty, false if there is data */ inline bool empty() { bool isEmpty; _disable_interrupts(); // prevent inconsistent reads isEmpty = (head == tail); _enable_interrupts(); return isEmpty; } /** * push_back() - append a byte to the buffer is possible * assumed to be called from the recv interrupt */ inline void push_back(T c) { int i = (unsigned int) (head + 1) % MAX_ITEMS; if (i != tail) { buffer[head] = c; head = i; } } /** * pop_front() - remove a value from front of ring buffer */ inline T pop_front() { T c = -1; _disable_interrupts(); // disable interrupts to protect head and tail values // This prevents the RX_ISR from modifying them // while we are trying to read and modify // if the head isn't ahead of the tail, we don't have any characters if (head != tail) { c = (T) buffer[tail]; tail = (unsigned int) (tail + 1) % MAX_ITEMS; } _enable_interrupts(); // ok .. let everyone at them return c; } }; typedef ringbuffer ringbuffer_ui8_16; // ringbuffer, max of 16 uint8_t values typedef ringbuffer Ringbuffer_uint8_32; // ringbuffer, max of 32 uint8_t values #endif /* RINGBUFFER_H_ */

    /** * usci_serial.cpp - simple example using USCI UART + ringbuffer + command line monitor * * This code was written to test the new uniarch version of msp430-gcc. I wanted * to make sure it could generate code for the msp430g2553 running on the TI * launchpad. * * This code mplements a command line interface over the USB-CDC serial at * 9600-8-N-1. To test you must swap the RX/TX pins on your launchpad to use * the hardware USCI UART. I disconnected those jumpers on my launchpad and used * a couple of F-M jumper wires to run the msp430g2553 from a breadboard. * P1.1=RXD and P1.2=TXD ( this is the opposite of the msp430g2231 default setup ) * * * License: Do with this code what you want. However, don't blame * me if you connect it to a heart pump and it stops. This source * is provided as is with no warranties. It probably has bugs!! * You have been warned! * * Author: Rick Kimball * email: rick@kimballsoftware.com * Version: 1.00 Initial version 05-12-2011 */ #include #include #include #include "config.h" #include "ringbuffer.h" #include "usci_serial.h" /** * create a ring buffer that holds up to 16 uint8_t bytes * * Note: you could change the ringbuffer_ui8_16 typedef to * make it smaller or larger, just be consistent with what * you provide the Serial template */ ringbuffer_ui8_16 usci_buffer = { 0, 0, { 0 } }; Serial usci0 = { usci_buffer }; /** * USCI0RX_ISR - USCI UART receive character ISR handler * * we get an interrupt when a new character arrives via * the USCI UART receive pin. We just stuff it into * our buffer and let the main routine consume it. */ interrupt(USCIAB0RX_VECTOR) USCI0RX_ISR(void) { /** * Note: a side effect of reading UCA0RXBUF * is the rx interrupt flag is cleared */ usci_buffer.push_back(UCA0RXBUF); } /** * main - echo back to the user whatever they type */ int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = CALBC1_16MHZ; // set DCO clock for MCLK and SMCLK DCOCTL = CALDCO_16MHZ; usci0.init(); __bis_SR_register(GIE); // interrupts enabled usci0.xmit("\r\nMSP430G2553 Monitor\r\n$ "); while (true) { while (!usci0.empty()) { volatile int c; c = usci0.recv(); usci0.xmit((uint8_t) c); } } }
    #ifndef HW_SERIAL_H #define HW_SERIAL_H /** * Serial - simple access to USCI UART hardware * code implements interrupt driven input * and poll driven output. * * License: Do with this code what you want. However, don't blame * me if you connect it to a heart pump and it stops. This source * is provided as is with no warranties. It probably has bugs!! * You have been warned! * * Author: Rick Kimball * email: rick@kimballsoftware.com * Version: 1.00 Initial version 05-12-2011 */ template struct Serial { T_STORAGE &_recv_buffer; /** * init - setup the USCI UART hardware for 9600-8-N-1 * P1.1 = RX PIN, P1.2 = TX PIN */ inline void init() { P1SEL = BIT1 + BIT2; // P1.1=RXD, P1.2=TXD P1SEL2 = BIT1 + BIT2; // P1.1=RXD, P1.2=TXD UCA0CTL1 |= UCSSEL_2; // use SMCLK for USCI clock UCA0BR0 = 130; // 16MHz 9600 UCA0BR1 = 6; // 16MHz 9600 UCA0MCTL = UCBRS1 + UCBRS0; // Modulation UCBRSx = 3 UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** IE2 |= UCA0RXIE; // Enable USCI0RX_ISR interrupt } inline bool empty() { return _recv_buffer.empty(); } inline int recv() { return _recv_buffer.pop_front(); } void xmit(uint8_t c) { while (!(IFG2 & UCA0TXIFG)) ; // USCI_A0 TX buffer ready? UCA0TXBUF = (uint8_t) c; // TX -> RXed character } void xmit(const char *s) { while (*s) { xmit((uint8_t) *s); ++s; } } }; #endif /* HW_SERIAL_H */

    # # Makefile - usci_serial # # License: Do with this code what you want. However, don't blame # me if you connect it to a heart pump and it stops. This source # is provided as is with no warranties. It probably has bugs!! # You have been warned! # # Author: Rick Kimball # email: rick@kimballsoftware.com # Version: 1.00 Initial version 05-12-2011 CC=msp430-gcc CXX=msp430-g++ MCU=msp430g2553 CFLAGS=-mmcu=$(MCU) -O2 -g -Wall APP=usci_serial TARGET=Debug all: $(TARGET)/$(APP).elf $(TARGET)/$(APP).elf: $(TARGET)/$(APP).o $(CC) $(CFLAGS) -o $(TARGET)/$(APP).elf $(TARGET)/$(APP).o msp430-objdump -DS $(TARGET)/$(APP).elf >$(TARGET)/$(APP).lst msp430-size $(TARGET)/$(APP).elf $(TARGET)/$(APP).o: config.h ringbuffer.h $(APP).cpp $(APP).h $(CC) $(CFLAGS) -c -o $(TARGET)/$(APP).o $(APP).cpp install: mspdebug -q --force-reset rf2500 "prog $(TARGET)/$(APP).elf" clean: rm -f $(TARGET)/$(APP).o $(TARGET)/$(APP).elf $(TARGET)/$(APP).lst mkdir -p $(TARGET)/
×
×
  • Create New...