From 67aed03b1ddca94196685d90ddaa7026bbafd0f6 Mon Sep 17 00:00:00 2001 From: Mariano Alvira Date: Tue, 9 Mar 2010 18:23:40 -0500 Subject: [PATCH] added interrupt based uarts. --- lib/include/uart1.h | 43 ++++++++++++++++++++++++++++++++++-------- lib/uart1.c | 37 +++++++++++++++++++++++++++++++++--- src/default_lowlevel.c | 25 +++++++++++++++++++++++- src/default_lowlevel.h | 2 ++ tests/config.h | 9 +++++++-- tests/flasher.c | 29 +++++++++++++++------------- tests/nvm-read.c | 2 +- tests/nvm-write.c | 2 +- tests/printf.c | 2 +- tests/put.c | 6 ++++-- tests/rftest-rx.c | 2 +- tests/rftest-tx.c | 2 +- tests/romimg.c | 4 ++-- tests/sleep.c | 2 +- tests/tests.c | 18 ------------------ tests/tests.h | 1 - tests/uart1-loopback.c | 9 ++++----- 17 files changed, 134 insertions(+), 61 deletions(-) diff --git a/lib/include/uart1.h b/lib/include/uart1.h index ee8337ef6..b45866a71 100644 --- a/lib/include/uart1.h +++ b/lib/include/uart1.h @@ -3,16 +3,43 @@ #include -#define UART1_CON ((volatile uint32_t *) 0x80005000) -#define UART1_STAT ((volatile uint32_t *) 0x80005004) -#define UART1_DATA ((volatile uint32_t *) 0x80005008) -#define UR1CON ((volatile uint32_t *) 0x8000500c) -#define UT1CON ((volatile uint32_t *) 0x80005010) -#define UART1_CTS ((volatile uint32_t *) 0x80005014) -#define UART1_BR ((volatile uint32_t *) 0x80005018) +#define UCON (0) +/* UCON bits */ +#define UCON_SAMP 10 +#define UCON_SAMP_8X 0 +#define UCON_SAMP_16X 1 +#define USTAT (0x04) +#define UDATA (0x08) +#define URXCON (0x0c) +#define UTXCON (0x10) +#define UCTS (0x14) +#define UBRCNT (0x18) + +#define UART1_BASE (0x80005000) +#define UART2_BASE (0x8000b000) + +#define UART1_UCON ((volatile uint32_t *) ( UART1_BASE + UCON )) +#define UART1_USTAT ((volatile uint32_t *) ( UART1_BASE + USTAT )) +#define UART1_UDATA ((volatile uint32_t *) ( UART1_BASE + UDATA )) +#define UART1_URXCON ((volatile uint32_t *) ( UART1_BASE + URXCON )) +#define UART1_UTXCON ((volatile uint32_t *) ( UART1_BASE + UTXCON )) +#define UART1_UCTS ((volatile uint32_t *) ( UART1_BASE + UCTS )) +#define UART1_UBRCNT ((volatile uint32_t *) ( UART1_BASE + UBRCNT )) + +#define UART2_UCON ((volatile uint32_t *) ( UART2_BASE + UCON )) +#define UART2_USTAT ((volatile uint32_t *) ( UART2_BASE + USTAT )) +#define UART2_UDATA ((volatile uint32_t *) ( UART2_BASE + UDATA )) +#define UART2_URXCON ((volatile uint32_t *) ( UART2_BASE + URXCON )) +#define UART2_UTXCON ((volatile uint32_t *) ( UART2_BASE + UTXCON )) +#define UART2_UCTS ((volatile uint32_t *) ( UART2_BASE + UCTS )) +#define UART2_UBRCNT ((volatile uint32_t *) ( UART2_BASE + UBRCNT )) + +extern volatile uint32_t u1_head, u1_tail; void uart1_putc(char c); +#define uart1_can_get() (*UART1_URXCON > 0) +uint8_t uart1_getc(void); + -#define uart1_can_get() (*UR1CON > 0) #endif diff --git a/lib/uart1.c b/lib/uart1.c index 3d821b3cd..8d650784c 100644 --- a/lib/uart1.c +++ b/lib/uart1.c @@ -1,6 +1,37 @@ -#include +#include +#include + +volatile char u1_tx_buf[1024]; +volatile uint32_t u1_head, u1_tail; + +void uart1_isr(void) { + while( *UART1_UTXCON != 0 ) { + if (u1_head == u1_tail) { + disable_irq(UART1); + return; + } + *UART1_UDATA = u1_tx_buf[u1_tail]; + u1_tail++; + if (u1_tail >= sizeof(u1_tx_buf)) + u1_tail = 0; + } + enable_irq(UART1); +} void uart1_putc(char c) { - while(*UT1CON == 31); /* wait for there to be room in the buffer */ - *UART1_DATA = c; + uint32_t h = u1_head; + h = u1_head + 1; + if (h >= sizeof(u1_tx_buf)) + h = 0; + if (h == u1_tail) /* drop chars when no room */ + return; + u1_tx_buf[u1_head] = c; + u1_head = h; + + uart1_isr(); +} + +uint8_t uart1_getc(void) { + while(uart1_can_get() == 0) { continue; } + return *UART1_UDATA; } diff --git a/src/default_lowlevel.c b/src/default_lowlevel.c index c1df5c9fe..33b9928d0 100644 --- a/src/default_lowlevel.c +++ b/src/default_lowlevel.c @@ -1,5 +1,5 @@ +#include #include -#include void default_vreg_init(void) { volatile uint32_t i; @@ -9,3 +9,26 @@ void default_vreg_init(void) { // while((((*(volatile uint32_t *)(0x80003018))>>17) & 1) !=1) { continue; } /* wait for the bypass to take */ *CRM_VREG_CNTL = 0x00000ff8; /* start the regulators */ } + +void uart1_init(uint16_t inc, uint16_t mod, uint8_t samp) { + uint8_t i; + + /* UART must be disabled to set the baudrate */ + *UART1_UCON = 0; + *UART1_UBRCNT = ( inc << 16 ) | mod; + + /* see Section 11.5.1.2 Alternate Modes */ + /* you must enable the peripheral first BEFORE setting the function in GPIO_FUNC_SEL */ + /* From the datasheet: "The peripheral function will control operation of the pad IF */ + /* THE PERIPHERAL IS ENABLED. */ + *UART1_UCON = (1 << 0) | (1 << 1); /* enable receive, transmit */ + if(samp == UCON_SAMP_16X) + set_bit(*UART1_UCON,UCON_SAMP); + *GPIO_FUNC_SEL0 = ( (0x01 << (14*2)) | (0x01 << (15*2)) ); /* set GPIO15-14 to UART (UART1 TX and RX)*/ + + /* interrupt when 28 bytes are free */ + *UART1_UTXCON = 28; + + u1_head = 0; u1_tail = 0; + enable_irq(UART1); +} diff --git a/src/default_lowlevel.h b/src/default_lowlevel.h index 90400d03a..fc58c9cb8 100644 --- a/src/default_lowlevel.h +++ b/src/default_lowlevel.h @@ -3,4 +3,6 @@ void default_vreg_init(void); +void uart1_init(uint16_t inc, uint16_t mod, uint8_t samp); + #endif diff --git a/tests/config.h b/tests/config.h index a0b7f38bb..73a4bb4da 100644 --- a/tests/config.h +++ b/tests/config.h @@ -2,9 +2,14 @@ #define CONFIG_H /* Baud rate */ -/* INC = 767; MOD = 9999 works: 115200 @ 24 MHz 16 bit sample */ -#define INC 767 #define MOD 9999 +/* 230400 bps, INC=767, MOD=9999, 24Mhz 16x samp */ +/* 115200 bps, INC=767, MOD=9999, 24Mhz 8x samp */ +#define INC 767 +/* 921600 bps, MOD=9999, 24Mhz 16x samp */ +//#define INC 3071 +#define SAMP UCON_SAMP_8X +//#define SAMP UCON_SAMP_16X /* use uart1 for console */ #define uart_init uart1_init diff --git a/tests/flasher.c b/tests/flasher.c index 25e2d3419..7deabafb1 100644 --- a/tests/flasher.c +++ b/tests/flasher.c @@ -19,7 +19,16 @@ #define dbg_put_hex32(...) #endif -uint8_t getc(void); +uint8_t getc(void) +{ + volatile uint8_t c; + while(*UART1_URXCON == 0); + + c = *UART1_UDATA; + return c; +} + + void flushrx(void); uint32_t to_u32(volatile uint32_t *c); @@ -41,7 +50,8 @@ void main(void) { volatile uint32_t addr,data; - uart_init(INC, MOD); + uart_init(INC, MOD, SAMP); + disable_irq(UART1); vreg_init(); @@ -73,7 +83,7 @@ void main(void) { /* read the length */ for(i=0; i<4; i++) { - c = getc(); + c = uart1_getc(); /* bail if the first byte of the length is zero */ len += (c<<(i*8)); } @@ -158,8 +168,8 @@ void main(void) { void flushrx(void) { volatile uint8_t c; - while(*UR1CON !=0) { - c = *UART1_DATA; + while(*UART1_URXCON !=0) { + c = *UART1_UDATA; } } @@ -199,12 +209,5 @@ uint32_t to_u32(volatile uint32_t *c) return ret; } -uint8_t getc(void) -{ - volatile uint8_t c; - while(*UR1CON == 0); - - c = *UART1_DATA; - return c; -} + diff --git a/tests/nvm-read.c b/tests/nvm-read.c index 60ee5692e..40939aac4 100644 --- a/tests/nvm-read.c +++ b/tests/nvm-read.c @@ -10,7 +10,7 @@ void main(void) { uint32_t buf[READ_NBYTES/4]; uint32_t i; - uart_init(INC, MOD); + uart_init(INC, MOD, SAMP); print_welcome("nvm-read"); diff --git a/tests/nvm-write.c b/tests/nvm-write.c index 880525767..260580417 100644 --- a/tests/nvm-write.c +++ b/tests/nvm-write.c @@ -10,7 +10,7 @@ void main(void) { uint32_t buf[WRITE_NBYTES/4]; uint32_t i; - uart_init(INC, MOD); + uart_init(INC, MOD, SAMP); print_welcome("nvm-write"); diff --git a/tests/printf.c b/tests/printf.c index 937e6f72e..10cbd4d1c 100644 --- a/tests/printf.c +++ b/tests/printf.c @@ -15,7 +15,7 @@ int main(void) int mi; // char buf[80]; - uart_init(INC, MOD); + uart_init(INC, MOD, SAMP); mi = (1 << (bs-1)) + 1; printf("%s\n", ptr); diff --git a/tests/put.c b/tests/put.c index 348da13f0..15dfec507 100644 --- a/tests/put.c +++ b/tests/put.c @@ -5,8 +5,10 @@ const uint8_t hex[16]={'0','1','2','3','4','5','6','7', '8','9','a','b','c','d','e','f'}; void putchr(char c) { - while(*UT1CON == 31); /* wait for there to be room in the buffer */ - *UART1_DATA = c; + while(*UART1_UTXCON == 31); + /* wait for there to be room in the buffer */ +// while( *UART1_UTXCON == 0 ) { continue; } + *UART1_UDATA = c; } void putstr(char *s) { diff --git a/tests/rftest-rx.c b/tests/rftest-rx.c index 401f17b28..20550a044 100644 --- a/tests/rftest-rx.c +++ b/tests/rftest-rx.c @@ -25,7 +25,7 @@ void main(void) { /* trim the reference osc. to 24MHz */ pack_XTAL_CNTL(CTUNE_4PF, CTUNE, FTUNE, IBIAS); - uart_init(INC,MOD); + uart_init(INC, MOD, SAMP); vreg_init(); diff --git a/tests/rftest-tx.c b/tests/rftest-tx.c index f0825ea9a..b77f84679 100644 --- a/tests/rftest-tx.c +++ b/tests/rftest-tx.c @@ -35,7 +35,7 @@ void main(void) { /* trim the reference osc. to 24MHz */ pack_XTAL_CNTL(CTUNE_4PF, CTUNE, FTUNE, IBIAS); - uart_init(INC,MOD); + uart_init(INC, MOD, SAMP); vreg_init(); diff --git a/tests/romimg.c b/tests/romimg.c index 3b50ddab9..8e651ed34 100644 --- a/tests/romimg.c +++ b/tests/romimg.c @@ -7,10 +7,10 @@ void main(void) { volatile uint8_t *data; - uart_init(INC, MOD); + uart_init(INC, MOD, SAMP); for(data = DUMP_BASE; data < ((uint8_t *)(DUMP_BASE+DUMP_LEN)); data++) { - putchr(*data); + uart1_putc(*data); } while(1); diff --git a/tests/sleep.c b/tests/sleep.c index b7f2b9bb3..03444e2c7 100644 --- a/tests/sleep.c +++ b/tests/sleep.c @@ -6,7 +6,7 @@ void main(void) { - uart_init(INC,MOD); + uart_init(INC,MOD,SAMP); *mem32(0x00401ffc) = 0x01234567; *mem32(0x00407ffc) = 0xdeadbeef; diff --git a/tests/tests.c b/tests/tests.c index 9bb300ce2..bd64642c6 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -4,24 +4,6 @@ #include "put.h" #include "tests.h" -void uart1_init(uint16_t inc, uint16_t mod) { - /* Restore UART regs. to default */ - /* in case there is still bootloader state leftover */ - - *UART1_CON = 0x0000c800; /* mask interrupts, 16 bit sample --- helps explain the baud rate */ - - /* INC = 767; MOD = 9999 works: 115200 @ 24 MHz 16 bit sample */ - *UART1_BR = (inc << 16) | mod; - - /* see Section 11.5.1.2 Alternate Modes */ - /* you must enable the peripheral first BEFORE setting the function in GPIO_FUNC_SEL */ - /* From the datasheet: "The peripheral function will control operation of the pad IF */ - /* THE PERIPHERAL IS ENABLED. */ - *UART1_CON = 0x00000003; /* enable receive and transmit */ - *GPIO_FUNC_SEL0 = ( (0x01 << (14*2)) | (0x01 << (15*2)) ); /* set GPIO15-14 to UART (UART1 TX and RX)*/ - -} - void print_welcome(char* testname) { printf("mc1322x-test: %s\n\r",testname); printf("board: %s\n\r", STR2(BOARD)); diff --git a/tests/tests.h b/tests/tests.h index 29158c330..bcd75ef00 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -6,7 +6,6 @@ #define NL "\033[K\r\n" -void uart1_init(uint16_t inc, uint16_t mod); void print_welcome(char* testname); void dump_regs(uint32_t base, uint32_t len); void print_packet(volatile packet_t *p); diff --git a/tests/uart1-loopback.c b/tests/uart1-loopback.c index dfa51356c..38d135427 100644 --- a/tests/uart1-loopback.c +++ b/tests/uart1-loopback.c @@ -5,16 +5,15 @@ #include "config.h" void main(void) { + volatile char c; - uart1_init(INC,MOD); + uart1_init(INC,MOD,SAMP); - uint8_t c; while(1) { - if(*UART1_CON > 0) { + if(uart1_can_get()) { /* Receive buffer isn't empty */ /* read a byte and write it to the transmit buffer */ - c = *UART1_DATA; - *UART1_DATA = c; + uart1_putc(uart1_getc()); } }