[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