From 9bc1913e0923fcb3e65de616a2c6ce05948d2e78 Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Mon, 6 May 2013 00:02:07 +0200 Subject: bsp/lm3s69xx: Use interrupts for UART receive This makes continuous UART polling unnecessary. --- c/src/lib/libbsp/arm/lm3s69xx/console/uart.c | 59 ++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/c/src/lib/libbsp/arm/lm3s69xx/console/uart.c b/c/src/lib/libbsp/arm/lm3s69xx/console/uart.c index 4d916662c2..dc7a443966 100644 --- a/c/src/lib/libbsp/arm/lm3s69xx/console/uart.c +++ b/c/src/lib/libbsp/arm/lm3s69xx/console/uart.c @@ -19,6 +19,10 @@ #include #include #include +#include +#include + +#define LM3S69XX_UART_FIFO_DEPTH 16 static volatile lm3s69xx_uart *get_uart_regs(int minor) { @@ -43,8 +47,36 @@ static uint32_t get_baud_div(uint32_t baud) return (clock4 + baud - 1) / baud; } +static void irq_handler(void *arg) +{ + int minor = (int)arg; + console_data *cd = &Console_Port_Data [minor]; + volatile lm3s69xx_uart *uart = get_uart_regs(minor); + + do { + char buf[LM3S69XX_UART_FIFO_DEPTH]; + int i = 0; + uint32_t status = uart->fr; + + while (((status & UARTFR_RXFE) == 0) && (i < LM3S69XX_UART_FIFO_DEPTH)) { + uint32_t d = uart->dr; + + if ((d & UARTDR_ERROR_MSK) == 0) { + buf[i] = UARTDR_DATA_GET(d); + i++; + } + + status = uart->fr; + } + + if (i > 0) + rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i); + } while (uart->mis != 0); +} + static void initialize(int minor) { + const console_tbl *ct = Console_Port_Tbl[minor]; volatile lm3s69xx_uart *uart = get_uart_regs(minor); unsigned int num = get_uart_number(minor); @@ -58,6 +90,10 @@ static void initialize(int minor) uart->lcrh = UARTLCRH_WLEN(0x3) | UARTLCRH_FEN; uart->ctl = UARTCTL_RXE | UARTCTL_TXE | UARTCTL_UARTEN; + + int rv = rtems_interrupt_handler_install(ct->ulIntVector, "UART", + RTEMS_INTERRUPT_UNIQUE, irq_handler, (void *)minor); + assert(rv == RTEMS_SUCCESSFUL); } static int first_open(int major, int minor, void *arg) @@ -65,27 +101,26 @@ static int first_open(int major, int minor, void *arg) rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; console_data *cd = &Console_Port_Data [minor]; + volatile lm3s69xx_uart *uart = get_uart_regs(minor); cd->termios_data = tty; rtems_termios_set_initial_baud(tty, LM3S69XX_UART_BAUD); - return 0; -} + /* Drain the RX FIFO. */ + while ((uart->fr & UARTFR_RXFE) == 0) + (void)uart->dr; + + uart->im = UARTI_RX | UARTI_RT; -static int last_close(int major, int minor, void *arg) -{ return 0; } -static int read_polled(int minor) +static int last_close(int major, int minor, void *arg) { volatile lm3s69xx_uart *uart = get_uart_regs(minor); + uart->im = 0; - if ((uart->fr & UARTFR_RXFE) != 0) { - return -1; - } else { - return UARTDR_DATA(uart->dr); - } + return 0; } static void write_polled(int minor, char c) @@ -123,10 +158,10 @@ const console_fns lm3s69xx_uart_fns = { .deviceProbe = libchip_serial_default_probe, .deviceFirstOpen = first_open, .deviceLastClose = last_close, - .deviceRead = read_polled, + .deviceRead = NULL, .deviceWrite = write_support_polled, .deviceInitialize = initialize, .deviceWritePolled = write_polled, .deviceSetAttributes = set_attribues, - .deviceOutputUsesInterrupts = false + .deviceOutputUsesInterrupts = TERMIOS_POLLED }; -- cgit v1.2.3