[PATCH 12/15] HiFive1: add UART support
Denis Obrezkov
denisobrezkov at gmail.com
Wed Aug 16 15:13:03 UTC 2017
---
.../libbsp/riscv32/hifive1/console/fe310-uart.c | 215 +++++++++++++++++++++
.../libbsp/riscv32/hifive1/include/fe310-gpio.h | 41 ++++
.../libbsp/riscv32/hifive1/include/fe310-uart.h | 38 ++++
3 files changed, 294 insertions(+)
create mode 100644 c/src/lib/libbsp/riscv32/hifive1/console/fe310-uart.c
create mode 100644 c/src/lib/libbsp/riscv32/hifive1/include/fe310-gpio.h
create mode 100644 c/src/lib/libbsp/riscv32/hifive1/include/fe310-uart.h
diff --git a/c/src/lib/libbsp/riscv32/hifive1/console/fe310-uart.c b/c/src/lib/libbsp/riscv32/hifive1/console/fe310-uart.c
new file mode 100644
index 0000000..1784ff7
--- /dev/null
+++ b/c/src/lib/libbsp/riscv32/hifive1/console/fe310-uart.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2017 Denis Obrezkov <denisobrezkov at gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/console.h>
+#include <rtems/termiostypes.h>
+#include <termios.h>
+#include <bsp/prci.h>
+#include <bsp/fe310-uart.h>
+#include <bsp/fe310-gpio.h>
+#include <bsp/fe310.h>
+#include <bsp/fatal.h>
+#include <bsp/console-polled.h>
+
+static void fe310_console_putc (char ch);
+
+fe310_uart_context driver_context = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("FE310_UART0"),
+ .device_name = "/dev/console",
+ .regs = (volatile fe310_uart_t *) &FE310_UART0,
+};
+
+
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code sc;
+ const rtems_termios_device_handler *handler = &fe310_uart_handler_polled;
+
+ /*
+ * Initialize the Termios infrastructure. If Termios has already
+ * been initialized by another device driver, then this call will
+ * have no effect.
+ */
+ rtems_termios_initialize();
+ fe310_uart_context * ctx = &driver_context;
+ /*
+ * Install this device in the file system and Termios. In order
+ * to use the console (i.e. being able to do printf, scanf etc.
+ * on stdin, stdout and stderr), one device must be registered as
+ * "/dev/console" (CONSOLE_DEVICE_NAME).
+ */
+ sc = rtems_termios_device_install(
+ ctx->device_name,
+ handler,
+ NULL,
+ &ctx->base
+ );
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ bsp_fatal(BSP_FATAL_CONSOLE_NO_DEV);
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+
+static bool fe310_uart_first_open (
+ rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
+ rtems_libio_open_close_args_t *args
+)
+{
+ volatile fe310_gpio_t * gpio;
+ fe310_uart_context * ctx;
+ rtems_status_code sc;
+
+
+ /* Configure GPIO to be UART */
+ gpio = (volatile fe310_gpio_t *)&FE310_GPIO;
+ gpio->iof_sel &= ~IOF0_UART0_MASK;
+ gpio->iof_en |= ~IOF0_UART0_MASK;
+
+
+ sc = rtems_termios_set_initial_baud (tty, B115200);
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ return false;
+ }
+
+ /* Set up a baud rate and enable tx and rx */
+ ctx = (fe310_uart_context *) base;
+ (ctx->regs)->div = hifive1_default_freq / 115200 - 1;
+ (ctx->regs)->txctrl |= 1;
+ (ctx->regs)->rxctrl |= 1;
+ return true;
+};
+
+static void fe310_uart_last_close (
+ rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ rtems_libio_open_close_args_t *args
+)
+{
+ return;
+}
+
+static int fe310_uart_poll_read (
+ rtems_termios_device_context *base
+)
+{
+ fe310_uart_context * ctx = (fe310_uart_context*) base;
+ size_t i;
+
+ if (((ctx->regs->rxdata) & 0x80000000) != 0) {
+ return -1;
+ } else {
+ return ctx->regs->rxdata;
+ }
+}
+
+static uint32_t freq = 0;
+
+static ssize_t fe310_uart_poll_write (
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t n
+)
+{
+
+ fe310_uart_context * ctx = (fe310_uart_context*) base;
+ size_t i;
+
+
+ volatile fe310_gpio_t * gpio;
+ rtems_status_code sc;
+
+ gpio = (volatile fe310_gpio_t *)&FE310_GPIO;
+ gpio->iof_sel &= ~IOF0_UART0_MASK;
+ gpio->iof_en |= ~IOF0_UART0_MASK;
+
+ gpio->iof_sel &= ~IOF0_UART1_MASK;
+ gpio->iof_en |= ~IOF0_UART1_MASK;
+
+
+ (ctx->regs)->div = hifive1_default_freq / 115200 - 1;
+ (ctx->regs)->txctrl |= 1;
+ (ctx->regs)->rxctrl |= 1;
+
+
+
+ for (i = 0; i < n; ++i) {
+ while (((ctx->regs->txdata) & 0x80000000) != 0) {
+ ;
+ }
+ ctx->regs->txdata = buf[i];
+ }
+ return n;
+}
+
+static void fe310_console_putc (char ch) {
+ fe310_uart_poll_write ( (rtems_termios_device_context *)&driver_context, &ch, 1);
+}
+
+static bool fe310_uart_set_attributes(
+ rtems_termios_device_context *base,
+ const struct termios *term
+)
+{
+ return true;
+}
+
+const rtems_termios_device_handler fe310_uart_handler_polled = {
+ .first_open = fe310_uart_first_open,
+ .last_close = fe310_uart_last_close,
+ .poll_read = fe310_uart_poll_read,
+ .write = fe310_uart_poll_write,
+ .set_attributes = fe310_uart_set_attributes,
+ .ioctl = NULL,
+ .mode = TERMIOS_POLLED
+};
+
+void console_outbyte_polled(
+ int port,
+ char ch
+)
+{
+ fe310_console_putc(ch);
+}
+
+int console_inbyte_nonblocking(
+ int port
+)
+{
+ return -1;
+}
+
+void console_initialize_hardware (void)
+{
+ volatile fe310_gpio_t * gpio;
+ volatile fe310_uart_t * uregs = (volatile fe310_uart_t *) &FE310_UART0;
+ rtems_status_code sc;
+
+ gpio = (volatile fe310_gpio_t *)&FE310_GPIO;
+ gpio->iof_sel &= ~IOF0_UART0_MASK;
+ gpio->iof_en |= ~IOF0_UART0_MASK;
+
+
+ uregs->div = hifive1_default_freq / 115200 - 1;
+ uregs->txctrl |= 1;
+ return;
+
+}
+
+
+#include <rtems/bspIo.h>
+BSP_output_char_function_type BSP_output_char = fe310_console_putc;
+
diff --git a/c/src/lib/libbsp/riscv32/hifive1/include/fe310-gpio.h b/c/src/lib/libbsp/riscv32/hifive1/include/fe310-gpio.h
new file mode 100644
index 0000000..d5332fc
--- /dev/null
+++ b/c/src/lib/libbsp/riscv32/hifive1/include/fe310-gpio.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Denis Obrezkov <denisobrezkov at gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef FE310_GPIO_H
+#define FE310_GPIO_H
+
+
+#include <rtems/termiostypes.h>
+#include <rtems/irq.h>
+
+#define IOF0_UART0_MASK 0x00030000
+#define IOF0_UART1_MASK 0x00300000
+
+typedef struct {
+ uint32_t value;
+ uint32_t input_en;
+ uint32_t output_en;
+ uint32_t port;
+ uint32_t pue;
+ uint32_t ds;
+ uint32_t rise_ie;
+ uint32_t rise_ip;
+ uint32_t fall_ie;
+ uint32_t fall_ip;
+ uint32_t high_ie;
+ uint32_t high_ip;
+ uint32_t low_ie;
+ uint32_t low_ip;
+ uint32_t iof_en;
+ uint32_t iof_sel;
+ uint32_t out_xor;
+} fe310_gpio_t;
+
+
+
+#endif /* FE310_GPIO_H */
diff --git a/c/src/lib/libbsp/riscv32/hifive1/include/fe310-uart.h b/c/src/lib/libbsp/riscv32/hifive1/include/fe310-uart.h
new file mode 100644
index 0000000..78210b4
--- /dev/null
+++ b/c/src/lib/libbsp/riscv32/hifive1/include/fe310-uart.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Denis Obrezkov <denisobrezkov at gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef FE310_UART_H
+#define FE310_UART_H
+
+
+#include <rtems/termiostypes.h>
+#include <rtems/irq.h>
+
+typedef struct {
+ uint32_t txdata;
+ uint32_t rxdata;
+ uint32_t txctrl;
+ uint32_t rxctrl;
+ uint32_t ie;
+ uint32_t ip;
+ uint32_t div;
+} fe310_uart_t;
+
+/* Low-level driver specific data structure */
+typedef struct {
+ rtems_termios_device_context base;
+ const char *device_name;
+ volatile fe310_uart_t *regs;
+} fe310_uart_context;
+
+
+extern const rtems_termios_device_handler fe310_uart_handler_polled;
+
+extern fe310_uart_context driver_context;
+
+#endif /* FE310_UART_H */
--
2.1.4
More information about the devel
mailing list