Created
May 12, 2011 21:07
-
-
Save RickKimball/969447 to your computer and use it in GitHub Desktop.
Simple USCI UART Test code for msp430-gcc uniarch and msp430g2553 hardware
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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)/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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<typename T, int MAX_ITEMS> | |
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<uint8_t, 16> ringbuffer_ui8_16; // ringbuffer, max of 16 uint8_t values | |
typedef ringbuffer<uint8_t, 32> Ringbuffer_uint8_32; // ringbuffer, max of 32 uint8_t values | |
#endif /* RINGBUFFER_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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 <msp430.h> | |
#include <legacymsp430.h> | |
#include <stdint.h> | |
#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<ringbuffer_ui8_16> 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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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<typename T_STORAGE> | |
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 */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment