From: Vladimir Burian Date: Fri, 4 Feb 2011 19:56:41 +0000 (+0100) Subject: Software modification to work whit HW UART X-Git-Url: https://rtime.felk.cvut.cz/gitweb/fpga/virtex2/uart.git/commitdiff_plain/e4d439f4b7c5af4364f93911c067d72627326e37?ds=sidebyside Software modification to work whit HW UART Code si almost all rewritten. --- diff --git a/software/README.txt b/software/README.txt deleted file mode 100644 index 79c251c..0000000 --- a/software/README.txt +++ /dev/null @@ -1,47 +0,0 @@ -what's this? ------------- -it's a simple example project for the MSP430 series MCU and the GCC port -of the mspgcc project. the project contains a makefile and uses assembler -and C sources. this time it is a software UART with Timer_A. - -this example shows the following features: - - Timer_A uart, full duplex - o same pins as BSL (P1.1 TX, P2.2 RX) - o it contains a reusable code - - - software FLL - the watch crystal is used as reference and the main clock - is adjusted to 1.536MHz on startup - - - use uprintf to print formated strings and do a printf - emulation that prints to the serial port. - - - the main loop is a simple line editor. when a return character - ('\r', usualy RETURN key) is received, it writes the received - characters from the buffer to the serial port. - connect a terminal at 9600,N,8,1 to try it out. - - - makefile - o compile and link - o include assembler files - o convert to intel hex format - o generate a listing with mixed C / assembly - -required hardware ------------------ - - - a MSP430F1121 or larger device (any from the F1x series) - connect pins P1.1 (TX) and P2.2 (RX) through level converters - to a terminal. you can also use a BSL hardware, the same pins - are used. - - - watch crystal 32.768kHz - - - optionaly a LED on P2.5 (470 Ohms series resistor to GND) - -disclaimer ----------- -this example is part of the mspgcc project http://mspgcc.sf.net -see license.txt for details. - -chris \ No newline at end of file diff --git a/software/fll.h b/software/fll.h deleted file mode 100644 index 6740ca8..0000000 --- a/software/fll.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef FLL_H -#define FLL_H - -void fllInit(void); //do an FLL loop to adjust system frequency - -#endif //FLL_H diff --git a/software/fll.s b/software/fll.s deleted file mode 100644 index 49e02c2..0000000 --- a/software/fll.s +++ /dev/null @@ -1,51 +0,0 @@ -#include "hardware.h" -.text -.global fllInit ; SW FLL to init DCO/SMCLK -frequency - .type fllInit, @function -fllInit: - mov.b #BCSCTL1_FLL, &BCSCTL1 ; Init basic clock control reg 1 - mov.b #BCSCTL2_FLL, &BCSCTL2 ; Init basic clock control reg 2 - mov #TACTL_FLL, &TACTL ; SMCLK is TA-clock / Timer stopped - bis #MC1, &TACTL ; Start timer: Continuos Mode - mov #CCTL2_FLL, &CCTL2 ; Init CCR2 and Clear capture flag - -.Lwait0:bit #CCIFG, &CCTL2 ; Test/Wait for capture flag - jz .Lwait0 ; May be used with INT / LPM0 later ? - mov &CCR2, r15 ; Store CCR2 init-value - bic #CCIFG, &CCTL2 ; Clear capture flag -.Lwait1:bit #CCIFG, &CCTL2 ; Test/Wait for capture flag - jz .Lwait1 ; May be used with INT / LPM0 later ? - bic #CCIFG, &CCTL2 ; Clear capture flag - mov.b &BCSCTL1, r14 ; Store current Rsel value - bic.b #0x0f8, r14 ; Mask for Rsel bits - mov.b &DCOCTL, r13 ; Store current DCO value - -.LfllUP:cmp.b #DCOCTL_MAX, r13 ; Needs Rsel to be increased ? - jne .LfllDN ; No - cmp.b #7, r14 ; Is max Rsel already selected ? - jge .LfllER ; Yes, Rsel can not be increased - inc.b &BCSCTL1 ; Increase Rsel - jmp .LfllRx ; Test DCO again - -.LfllDN:cmp.b #DCOCTL_MIN, r13 ; Needs Rsel to be decreased ? - jne .LfllCP ; No - cmp.b #0, r14 ; Is min Rsel already selected ? - jeq .LfllER ; Yes, Rsel can not be increased - dec.b &BCSCTL1 ; Decrease Rsel -.LfllRx:mov.b #60h, &DCOCTL ; Center DCO (may be optimized later ?) - jmp .Lwait0 ; Test DCO again -.LfllCP: - mov &CCR2, r12 ; Read captured value - sub r15, r12 ; Subtract last captured value - mov &CCR2, r15 ; Store CCR2 value for next pass - cmp #DCO_FSET, r12 ; DCO_FSET= SMCLK/(32768/4) - jl .LfllI ; - jeq .LfllOK ; -.LfllD: dec.b &DCOCTL ; Decrement value - jmp .Lwait0 ; -.LfllI: inc.b &DCOCTL ; Increment value - jmp .Lwait0 ; - -.LfllER: ; error, currently ingnored -.LfllOK:clr &CCTL2 ; stop CCR2 - ret ; diff --git a/software/hardware.h b/software/hardware.h index cb99613..9255487 100644 --- a/software/hardware.h +++ b/software/hardware.h @@ -1,9 +1,6 @@ #ifndef HARDWARE_H #define HARDWARE_H -#define __msp430_have_port3 -#define __MSP430_HAS_PORT3__ - #include #include #include @@ -18,66 +15,20 @@ sfrw(QCNTH,QCNTH_); #define QCNT_VECTOR 14 -//PINS -//PORT1 -#define TX BIT1 - -//PORT2 -#define RX BIT2 -#define LED BIT1 - -//Port Output Register 'P1OUT, P2OUT': -#define P1OUT_INIT TX //Init Output data of port1 -#define P2OUT_INIT 0 //Init Output data of port2 -#define P3OUT_INIT 0 //Init Output data of port3 - -//Port Direction Register 'P1DIR, P2DIR': -#define P1DIR_INIT TX //Init of Port1 Data-Direction Reg (Out=1 / Inp=0) -#define P2DIR_INIT ~RX //Init of Port2 Data-Direction Reg (Out=1 / Inp=0) -#define P3DIR_INIT 0xff //Init of Port3 Data-Direction Reg (Out=1 / Inp=0) - -//Selection of Port or Module -Function on the Pins 'P1SEL, P2SEL' -#define P1SEL_INIT 0 //P1-Modules: -#define P2SEL_INIT RX //P2-Modules: -#define P3SEL_INIT 0 //P3-Modules: - -//Interrupt capabilities of P1 and P2 -#define P1IE_INIT 0 //Interrupt Enable (0=dis 1=enabled) -#define P2IE_INIT 0 //Interrupt Enable (0=dis 1=enabled) -#define P1IES_INIT 0 //Interrupt Edge Select (0=pos 1=neg) -#define P2IES_INIT 0 //Interrupt Edge Select (0=pos 1=neg) - -#define IE_INIT 0 -#define WDTCTL_INIT WDTPW|WDTHOLD - -#define BCSCTL1_FLL XT2OFF|DIVA1|RSEL2|RSEL0 -#define BCSCTL2_FLL 0 -#define TACTL_FLL TASSEL_2|TACLR -#define CCTL2_FLL CM0|CCIS0|CAP - -#define TACTL_AFTER_FLL TASSEL_2|TACLR|ID_0 - -//#define BAUD 40 //9600 @3MHz div 8 -//#define BAUD 20 //19200 @3MHz div 8 -//#define BAUD 20 //9600 @1.5MHz div 8 -//#define BAUD 140 //9600 @1.5MHz div 8 - -//#define BAUD 2083 //9600 @20.0MHz div 1 -//#define BAUD 1042 //19200 @20.0MHz div 1 -//#define BAUD 521 //38400 @20.0MHz div 1 -//#define BAUD 347 //57600 @20.0MHz div 1 -//#define BAUD 174 //115200 @20.0MHz div 1 -//#define BAUD 87 //230400 @20.0MHz div 1 - -#define BAUD 208 //115200 @24.0MHz div 1 +//HW UART registers +#define UART_OFFSET 0x0100 -//Selection of 'Digitally Controlled Oszillator' (desired frquency in HZ, 1..3 MHz) -#define DCO_FREQ 1536000 //3072000/2 makes 9600 a bit more precise +#define UBAUD_ UART_OFFSET + 00 +#define UTX_ UART_OFFSET + 02 +#define URX_ UART_OFFSET + 04 +#define USTAT_ UART_OFFSET + 06 +#define UIE_ UART_OFFSET + 07 -//Automatic, do not edit -#define DCO_FSET (DCO_FREQ/8192) //DCO_FSET = DCO_FREQ / (32768/4) -#define DCOCTL_MAX 0xff // Used from FLL to check when Rsel must be changed -#define DCOCTL_MIN 0 // Used from FLL to check when Rsel must be changed +sfrw(UBAUD, UBAUD_); +sfrb(UTX, UTX_); +sfrb(URX, URX_); +sfrb(USTAT, USTAT_); +sfrb(UIE, UIE_); -#endif //HARDWARE_H +#endif diff --git a/software/main.c b/software/main.c index bf98951..1f2c2ef 100644 --- a/software/main.c +++ b/software/main.c @@ -1,25 +1,29 @@ -/* -see README.txt for details. +/** +This is a sample application for openMSP430 softcore MCU with external HW UART +peripheral and quadcount peripheral. -original by: chris +First of all "Hello world" is printed and then application works like echo and +also prints quadrature count whenever its value is changed (only whole turns +are reported). -modified by: Vladimir Burian +Baudrate is set to 115200. */ + #include "hardware.h" #include #include -#include "swuart.h" -#include "fll.h" +#include "uart.h" + /** QuadCounter value */ inline uint32_t qcount() { uint32_t result = 0; - + result |= QCNTL; result |= ((uint32_t)QCNTH << 16); - + return result; } @@ -31,100 +35,62 @@ interrupt(QCNT_VECTOR) qcount_isr() { } +/** +Print bits of byte in format b'xxxxxxxx' +*/ +void print_byte_flags(char flags) { + int i; + + putchar('b'); + putchar('\''); + + for (i = 8; i != 0; i--) { + if ((flags & 0x80) != 0) { + putchar('1'); + } else { + putchar('0'); + } + + flags = flags << 1; + } + + putchar('\''); + putchar('\n'); +} + + /** Delay function. */ -void delay(unsigned int d) { - while(d--) { +void delay(unsigned long int a, unsigned long int b) { + unsigned long int i; + + while (a--) { + i = b; + while (i--) { nop(); nop(); - } + } + } } + /** -Main function with init an an endless loop that is synced with the -interrupts trough the lowpower mode. +Main function with init and an endless loop. */ int main(void) { - int reading = 0; - int pos = 0; - char buf[40]; - int led = 0; - - WDTCTL = WDTCTL_INIT; //Init watchdog timer - - P1OUT = P1OUT_INIT; //Init output data of port1 - P1SEL = P1SEL_INIT; //Select port or module -function on port1 - P1DIR = P1DIR_INIT; //Init port direction register of port1 - P1IES = P1IES_INIT; //init port interrupts - P1IE = P1IE_INIT; - - P2OUT = P2OUT_INIT; //Init output data of port2 - P2SEL = P2SEL_INIT; //Select port or module -function on port2 - P2DIR = P2DIR_INIT; //Init port direction register of port2 - P2IES = P2IES_INIT; //init port interrupts - P2IE = P2IE_INIT; - - P3DIR = 0xff; - P3OUT = 0xff; //light LED during init - delay(65535); //Wait for watch crystal startup - delay(65535); -// fllInit(); //Init FLL to desired frequency using the 32k768 cystal as reference. - P3OUT = 0x00; //switch off LED - - TACTL = TACTL_AFTER_FLL; //setup timer (still stopped) - CCTL0 = CCIE|CAP|CM_2|CCIS_1|SCS; //select P2.2 with UART signal - CCTL1 = 0; // - CCTL2 = 0; // - TACTL |= MC1; //start timer - + + //UBAUD = 0x04E1; //24.00MHz - 9600 baud + UBAUD = 0x0067; //24.00MHz - 115200 baud + eint(); //enable interrupts - - printf("\r\n====== openMSP430 in action ======\r\n"); //say hello - printf("\r\nSimple Line Editor Ready\r\n"); //say hello - - printf("\n[QCount = 0x%08lX]\n", qcount()); - - while (1) { //main loop, never ends... - printf("> "); //show prompt - reading = 1; - while (reading) { //loop and read characters - LPM0; //sync, wakeup by irq - - led++; // Some lighting... - if (led==9) { - led = 0; - } - P3OUT = (0x01 << led); - - switch (rxdata) { - //process RETURN key - case '\r': - //case '\n': - printf("\r\n"); //finish line - buf[pos++] = 0; //to use printf... - printf(":%s\r\n", buf); - reading = 0; //exit read loop - pos = 0; //reset buffer - break; - //backspace - case '\b': - if (pos > 0) { //is there a char to delete? - pos--; //remove it in buffer - putchar('\b'); //go back - putchar(' '); //erase on screen - putchar('\b'); //go back - } - break; - //other characters - default: - //only store characters if buffer has space - if (pos < sizeof(buf)) { - putchar(rxdata); //echo - buf[pos++] = rxdata; //store - } - } - } + + + puts("Hello world\n"); + + for (;;) { + putchar(getchar()); } + } diff --git a/software/makefile b/software/makefile index ca0bdb8..11b5623 100644 --- a/software/makefile +++ b/software/makefile @@ -1,6 +1,6 @@ # makfile configuration NAME = ta_uart -OBJECTS = main.o swuart.o fll.o +OBJECTS = main.o uart.o CPU = msp430x1121 ASFLAGS = -mmcu=${CPU} -mforce-hwmul -x assembler-with-cpp -D_GNU_ASSEMBLER_ -c @@ -50,6 +50,5 @@ dist: FORCE: #project dependencies -main.o: main.c hardware.h -fll.o: fll.s hardware.h -swuart.o: swuart.s hardware.h +main.o: main.c uart.h hardware.h +uart.o: uart.h hardware.h diff --git a/software/miniterm.py b/software/miniterm.py deleted file mode 100644 index d0bd887..0000000 --- a/software/miniterm.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -#very simple serial terminal -#http://pyserial.sf.net package required -#input characters are sent directly, received characters are displays as is -#baudrate and echo configuartion is done through globals: - -# - -import sys, os, serial, threading, getopt -#EXITCHARCTER = '\x1b' #ESC -EXITCHARCTER = '\x04' #ctrl+d - -#first choosea platform dependant way to read single characters from the console -if os.name == 'nt': #sys.platform == 'win32': - import msvcrt - def getkey(): - while 1: - if echo: - z = msvcrt.getche() - else: - z = msvcrt.getch() - if z == '\0' or z == '\xe0': #functions keys - msvcrt.getch() - else: - return z - -elif os.name == 'posix': - #XXX: Untested code derrived from the Python FAQ.... -# import termios, TERMIOS, sys, os - import termios, sys, os - fd = sys.stdin.fileno() - old = termios.tcgetattr(fd) - new = termios.tcgetattr(fd) - new[3] = new[3] & ~TERMIOS.ICANON & ~TERMIOS.ECHO - new[6][TERMIOS.VMIN] = 1 - new[6][TERMIOS.VTIME] = 0 - termios.tcsetattr(fd, TERMIOS.TCSANOW, new) - s = '' # We'll save the characters typed and add them to the pool. - def getkey(): - c = os.read(fd, 1) - if echo: sys.stdout.write(c) - return c - def clenaup_console(): - termios.tcsetattr(fd, TERMIOS.TCSAFLUSH, old) - sys.exitfunc = clenaup_console #terminal modes have to be restored on exit... - -else: - raise "Sorry no implementation for your platform (%s) available." % sys.platform - - -def reader(): - """loop forever and copy serial->console""" - while 1: - sys.stdout.write(s.read()) - -def writer(): - """loop forever and copy console->serial""" - while 1: - c = getkey() - if c == EXITCHARCTER: break #exit on esc - s.write(c) #send character - if convert_outgoing_cr and c == '\r': - s.write('\n') - if echo: sys.stdout.write('\n') - - -#print a short help message -def usage(): - print >>sys.stderr, """USAGE: %s [options] - Simple Terminal Programm for the serial port. - - options: - -p, --port=PORT: port, a number, defualt = 0 or a device name - -b, --baud=BAUD: baudrate, default 9600 - -r, --rtscts: enable RTS/CTS flow control (default off) - -x, --xonxoff: enable software flow control (default off) - -e, --echo: enable local echo (default off) - -c, --cr: disable CR -> CR+LF translation - - """ % sys.argv[0] - -if __name__ == '__main__': - #parse command line options - try: - opts, args = getopt.getopt(sys.argv[1:], - "hp:b:rxec", - ["help", "port=", "baud=", "rtscts", "xonxoff", "echo", "cr"]) - except getopt.GetoptError: - # print help information and exit: - usage() - sys.exit(2) - - port = 0 - baudrate = 9600 - echo = 0 - convert_outgoing_cr = 1 - rtscts = 0 - xonxoff = 0 - for o, a in opts: - if o in ("-h", "--help"): #help text - usage() - sys.exit() - elif o in ("-p", "--port"): #specified port - try: - port = int(a) - except ValueError: - port = a - elif o in ("-b", "--baud"): #specified baudrate - try: - baudrate = int(a) - except ValueError: - raise ValueError, "Baudrate must be a integer number" - elif o in ("-r", "--rtscts"): - rtscts = 1 - elif o in ("-x", "--xonxoff"): - xonxoff = 1 - elif o in ("-e", "--echo"): - echo = 1 - elif o in ("-c", "--cr"): - convert_outgoing_cr = 0 - - try: - s = serial.Serial(port, baudrate, rtscts=rtscts, xonxoff=xonxoff) - except: - print "could not open port" - sys.exit(1) - print "--- Miniterm --- type Ctrl-D to quit" - #start serial->console thread - r = threading.Thread(target=reader) - r.setDaemon(1) - r.start() - #enter console->serial loop - writer() - - print "\n--- exit ---" diff --git a/software/swuart.h b/software/swuart.h deleted file mode 100644 index 140712f..0000000 --- a/software/swuart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef SWUART_H -#define SWUART_H - -void serPutc(char); //send one character over timer_a uart -extern char rxdata; -#endif //SWUART_H diff --git a/software/swuart.s b/software/swuart.s deleted file mode 100644 index dc17823..0000000 --- a/software/swuart.s +++ /dev/null @@ -1,78 +0,0 @@ -#include "hardware.h" - -;variables -.data - .comm rxdata,1,1 ;char var - .comm rxshift,1,1 ;char var - .comm rxbit,2,2 ;short var, aligned - -.text - -interrupt(TIMERA0_VECTOR) ;register interrupt vector -;interrupt handler to receive as Timer_A UART -.global ccr0 ;place a label afterwards so -ccr0: ;that it is used in the listing - add rxbit, r0 - jmp .Lrxstart ;start bit - jmp .Lrxdatabit ;D0 - jmp .Lrxdatabit ;D1 - jmp .Lrxdatabit ;D2 - jmp .Lrxdatabit ;D3 - jmp .Lrxdatabit ;D4 - jmp .Lrxdatabit ;D5 - jmp .Lrxdatabit ;D6 -; jmp .Lrxlastbit ;D7 that one is following anyway - -.Lrxlastbit: ;last bit, handle byte - bit #SCCI, &CCTL0 ;read last bit - rrc.b rxshift ;and save it - clr rxbit ;reset state - mov #CCIE|CAP|CM_2|CCIS_1|SCS, &CCTL0 ;restore capture mode - mov.b rxshift, rxdata ;copy received data - bic #CPUOFF|OSCOFF|SCG0|SCG1, 0(r1) ;exit all lowpower modes - ;here you might do other things too, like setting a flag - ;that the wakeup comes from the Timer_A UART. however - ;it should not take longer than one bit time, otherwise - ;charcetrs will be lost. - reti - -.Lrxstart: ;startbit, init - clr rxshift ;clear input buffer - add #(BAUD/2), &CCR0 ;startbit + 1.5 bits -> first bit - mov #CCIE|CCIS_1|SCS, &CCTL0;set compare mode, sample bits - jmp .Lrxex ;set state,... - -.Lrxdatabit: ;save databit - bit #SCCI, &CCTL0 ;measure databit - rrc.b rxshift ;rotate in databit - -.Lrxex: add #BAUD, &CCR0 ;one bit delay - incd rxbit ;setup next state - reti - -; void serPutc(char) -;use an other Capture/Compare than for receiving (full duplex). -;this one is without interrupts and OUTMOD, because only -;this way P1.1 can be used. P1.1 is prefered because the -;BSL is on that pin too. -.global putchar - .type putchar, @function -putchar: ;send a byte - mov #0, &CCTL1 ;select compare mode - mov #10, r13 ;ten bits: Start, 8 Data, Stop - rla r15 ;shift in start bit (0) - bis #0x0200, r15 ;set tenth bit (1), thats the stop bit - mov &TAR, &CCR1 ;set up start time -.Lt1lp: add #BAUD, &CCR1 ;set up for one bit - rrc r15 ;shift data trough carry - jc .Lt1 ;test carry bit -.Lt0: bic.b #TX, &P1OUT ;generate pulse - jmp .Ltc ; -.Lt1: bis.b #TX, &P1OUT ;just use the same amount of time as for a zero - jmp .Ltc ; -.Ltc: bit #CCIFG, &CCTL1 ;wait for compare - jz .Ltc ;loop until the bit is set - bic #CCIFG, &CCTL1 ;clear for next loop - dec r13 ;decrement bit counter - jnz .Lt1lp ;loop until all bits are transmitted - ret diff --git a/software/uart.c b/software/uart.c new file mode 100644 index 0000000..1c57831 --- /dev/null +++ b/software/uart.c @@ -0,0 +1,14 @@ +#include "hardware.h" +#include "uart.h" + +int putchar(int c) { + while (USTAT & 0x20) {} + UTX = c; + return 0; +} + +int getchar() { + while (!(USTAT & 0x10)) {} + return URX; +} + diff --git a/software/uart.h b/software/uart.h new file mode 100644 index 0000000..c3290b4 --- /dev/null +++ b/software/uart.h @@ -0,0 +1,9 @@ +#ifndef UART_H +#define UART_H + +int putchar(int c); + +int getchar(); + +#endif +