summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugeniy Meshcheryakov <eugen@debian.org>2013-05-06 00:02:07 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-05-06 09:38:33 +0200
commit9bc1913e0923fcb3e65de616a2c6ce05948d2e78 (patch)
treecadb19866ce10961f79b67a8ac74eb4d5e049660
parentbsp/lm3s69xx: More access macros for UART data register (diff)
downloadrtems-9bc1913e0923fcb3e65de616a2c6ce05948d2e78.tar.bz2
bsp/lm3s69xx: Use interrupts for UART receive
This makes continuous UART polling unnecessary.
-rw-r--r--c/src/lib/libbsp/arm/lm3s69xx/console/uart.c59
1 files 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 <libchip/sersupp.h>
#include <bsp/syscon.h>
#include <bsp/lm3s69xx.h>
+#include <rtems/irq-extension.h>
+#include <assert.h>
+
+#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
};