[PATCH 12/15] HiFive1: add UART support
Gedare Bloom
gedare at rtems.org
Thu Aug 17 15:21:31 UTC 2017
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/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
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
More information about the devel
mailing list