[PATCH 12/15] HiFive1: add UART support
Denis Obrezkov
denisobrezkov at gmail.com
Mon Aug 21 20:46:14 UTC 2017
2017-08-17 17:21 GMT+02:00 Gedare Bloom <gedare at rtems.org>:
> Remove the extra blank lines, and consider adding some helper
> functions (for enable/disable UARTx, for example)
>
> On Wed, Aug 16, 2017 at 11:13 AM, Denis Obrezkov
> <denisobrezkov at gmail.com> wrote:
> > ---
> > .../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/hifiv
> e1/console/fe310-uart.c
> > create mode 100644 c/src/lib/libbsp/riscv32/hifiv
> e1/include/fe310-gpio.h
> > create mode 100644 c/src/lib/libbsp/riscv32/hifiv
> e1/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
> >
> > _______________________________________________
> > devel mailing list
> > devel at rtems.org
> > http://lists.rtems.org/mailman/listinfo/devel
>
My example was TMS570's console code, but, honestly, I don't like that the
console code
and uart code are mixed together. Though, again, I have no time to
reimplement it now,
but I agree that uart part should be separated from the console abstraction.
--
Regards, Denis Obrezkov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20170821/16ff8480/attachment-0001.html>
More information about the devel
mailing list