diff --git a/drivers/drivers_initialize.c b/drivers/drivers_initialize.c index 8431d0c6c5b..1bcef10a1d7 100644 --- a/drivers/drivers_initialize.c +++ b/drivers/drivers_initialize.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -180,6 +181,10 @@ void drivers_initialize(void) syslog_console_init(); #endif +#ifdef CONFIG_UART_HOSTFS + uart_hostfs_init(); +#endif + #ifdef CONFIG_PSEUDOTERM_SUSV1 /* Register the master pseudo-terminal multiplexor device */ diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 66f1ba62302..2cc09c51546 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -53,6 +53,33 @@ config SERIAL_GDBSTUB_PATH ---help--- The path to the serial device that will be used for GDB stub. +config UART_HOSTFS + bool "Use hostfs read/write on UART_HOSTFS_DEVPATH as uart console" + depends on FS_HOSTFS + default n + select SERIAL_RXDMA + select SERIAL_TXDMA + +config UART_HOSTFS_DEVPATH + string "The host device node that will be used by" + depends on UART_HOSTFS + default "/dev/tty" + +config UART_HOSTFS_RXBUFSIZE + int "Uart hostfs receive buffer size" + default 256 + depends on UART_HOSTFS + +config UART_HOSTFS_TXBUFSIZE + int "Uart hostfs transmit buffer size" + default 256 + depends on UART_HOSTFS + +config UART_HOSTFS_DELAY_USEC + int "Uart hostfs polling interval in microseconds" + default 1000 + depends on UART_HOSTFS + menuconfig UART_PL011 bool "PL011 Chip support" default n diff --git a/drivers/serial/Make.defs b/drivers/serial/Make.defs index 7a8f9cfb749..5be882d039d 100644 --- a/drivers/serial/Make.defs +++ b/drivers/serial/Make.defs @@ -48,6 +48,10 @@ ifeq ($(CONFIG_RPMSG_UART),y) CSRCS += uart_rpmsg.c endif +ifeq ($(CONFIG_UART_HOSTFS),y) + CSRCS += uart_hostfs.c +endif + # Pseudo-terminal support ifeq ($(CONFIG_PSEUDOTERM),y) diff --git a/drivers/serial/uart_hostfs.c b/drivers/serial/uart_hostfs.c new file mode 100644 index 00000000000..32a459c9c9a --- /dev/null +++ b/drivers/serial/uart_hostfs.c @@ -0,0 +1,302 @@ +/**************************************************************************** + * drivers/serial/uart_hostfs.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define UART_WDOG_DELAY USEC2TICK(CONFIG_UART_HOSTFS_DELAY_USEC) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct uart_hostfs_priv_s +{ + int fd; + bool rxint; + struct wdog_s wdog; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int uart_hostfs_setup(FAR struct uart_dev_s *dev); +static void uart_hostfs_shutdown(FAR struct uart_dev_s *dev); +static int uart_hostfs_attach(FAR struct uart_dev_s *dev); +static void uart_hostfs_detach(FAR struct uart_dev_s *dev); +static int uart_hostfs_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); +static void uart_hostfs_rxint(FAR struct uart_dev_s *dev, bool enable); +static bool uart_hostfs_rxavailable(FAR struct uart_dev_s *dev); +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool uart_hostfs_rxflowcontrol(FAR struct uart_dev_s *dev, + unsigned int nbuffered, bool upper); +#endif +static void uart_hostfs_dmatxavail(FAR struct uart_dev_s *dev); +static void uart_hostfs_dmasend(FAR struct uart_dev_s *dev); +static void uart_hostfs_dmarxfree(FAR struct uart_dev_s *dev); +static void uart_hostfs_dmareceive(FAR struct uart_dev_s *dev); +static void uart_hostfs_send(FAR struct uart_dev_s *dev, int ch); +static void uart_hostfs_txint(FAR struct uart_dev_s *dev, bool enable); +static bool uart_hostfs_txready(FAR struct uart_dev_s *dev); +static bool uart_hostfs_txempty(FAR struct uart_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_uart_hostfs_ops = +{ + .setup = uart_hostfs_setup, + .shutdown = uart_hostfs_shutdown, + .attach = uart_hostfs_attach, + .detach = uart_hostfs_detach, + .ioctl = uart_hostfs_ioctl, + .rxint = uart_hostfs_rxint, + .rxavailable = uart_hostfs_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = uart_hostfs_rxflowcontrol, +#endif + .dmatxavail = uart_hostfs_dmatxavail, + .dmasend = uart_hostfs_dmasend, + .dmarxfree = uart_hostfs_dmarxfree, + .dmareceive = uart_hostfs_dmareceive, + .send = uart_hostfs_send, + .txint = uart_hostfs_txint, + .txready = uart_hostfs_txready, + .txempty = uart_hostfs_txempty, +}; + +static char g_uart_hostfs_rxbuf[CONFIG_UART_HOSTFS_RXBUFSIZE]; +static char g_uart_hostfs_txbuf[CONFIG_UART_HOSTFS_TXBUFSIZE]; + +static struct uart_hostfs_priv_s g_uart_hostfs_priv; + +static struct uart_dev_s g_uart_hostfs_dev = +{ + .ops = &g_uart_hostfs_ops, + .priv = &g_uart_hostfs_priv, + .xmit = + { + .size = CONFIG_UART_HOSTFS_TXBUFSIZE, + .buffer = g_uart_hostfs_txbuf, + }, + .recv = + { + .size = CONFIG_UART_HOSTFS_RXBUFSIZE, + .buffer = g_uart_hostfs_rxbuf, + }, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int uart_hostfs_setup(FAR struct uart_dev_s *dev) +{ + FAR struct uart_hostfs_priv_s *priv = dev->priv; + + priv->fd = host_open(CONFIG_UART_HOSTFS_DEVPATH, O_RDWR | O_NONBLOCK, + 0666); + return priv->fd; +} + +static void uart_hostfs_shutdown(FAR struct uart_dev_s *dev) +{ + FAR struct uart_hostfs_priv_s *priv = dev->priv; + + if (priv->fd > 0) + { + host_close(priv->fd); + priv->fd = -1; + } +} + +static int uart_hostfs_attach(FAR struct uart_dev_s *dev) +{ + return OK; +} + +static void uart_hostfs_detach(FAR struct uart_dev_s *dev) +{ +} + +static int uart_hostfs_ioctl(FAR struct file *filep, int cmd, + unsigned long arg) +{ + return -ENOTTY; +} + +static void uart_hostfs_wdog(wdparm_t arg) +{ + FAR struct uart_dev_s *dev = (FAR struct uart_dev_s *)arg; + FAR struct uart_hostfs_priv_s *priv = dev->priv; + + if (priv->rxint) + { + uart_dmarxfree(dev); + } + + wd_start(&priv->wdog, UART_WDOG_DELAY, uart_hostfs_wdog, (wdparm_t)dev); +} + +static void uart_hostfs_rxint(FAR struct uart_dev_s *dev, bool enable) +{ + FAR struct uart_hostfs_priv_s *priv = dev->priv; + + priv->rxint = enable; + if (enable) + { + wd_start(&priv->wdog, 0, uart_hostfs_wdog, (wdparm_t)dev); + } + else + { + wd_cancel(&priv->wdog); + } +} + +static bool uart_hostfs_rxavailable(FAR struct uart_dev_s *dev) +{ + return true; +} + +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool uart_hostfs_rxflowcontrol(FAR struct uart_dev_s *dev, + unsigned int nbuffered, bool upper) +{ + FAR struct uart_buffer_s *rxbuf = &dev->recv; + + return nbuffered == rxbuf->size; +} +#endif + +static void uart_hostfs_dmatxavail(FAR struct uart_dev_s *dev) +{ + uart_xmitchars_dma(dev); +} + +static void uart_hostfs_dmasend(FAR struct uart_dev_s *dev) +{ + FAR struct uart_hostfs_priv_s *priv = dev->priv; + FAR struct uart_dmaxfer_s *xfer = &dev->dmatx; + int ret; + + xfer->nbytes = 0; + ret = host_write(priv->fd, xfer->buffer, xfer->length); + if (ret > 0) + { + xfer->nbytes = ret; + + if (ret == xfer->length && xfer->nlength > 0) + { + ret = host_write(priv->fd, xfer->nbuffer, xfer->nlength); + if (ret > 0) + { + xfer->nbytes += ret; + } + } + } + + uart_xmitchars_done(dev); +} + +static void uart_hostfs_dmarxfree(FAR struct uart_dev_s *dev) +{ + uart_recvchars_dma(dev); +} + +static void uart_hostfs_dmareceive(FAR struct uart_dev_s *dev) +{ + FAR struct uart_hostfs_priv_s *priv = dev->priv; + FAR struct uart_dmaxfer_s *xfer = &dev->dmarx; + ssize_t ret; + + xfer->nbytes = 0; + ret = host_read(priv->fd, xfer->buffer, xfer->length); + if (ret > 0) + { + xfer->nbytes = ret; + + if (ret == xfer->length && xfer->nlength > 0) + { + ret = host_read(priv->fd, xfer->nbuffer, xfer->nlength); + if (ret > 0) + { + xfer->nbytes += ret; + } + } + } + + uart_recvchars_done(dev); +} + +static void uart_hostfs_send(FAR struct uart_dev_s *dev, int ch) +{ + FAR struct uart_hostfs_priv_s *priv = dev->priv; + char c = ch; + + host_write(priv->fd, &c, 1); +} + +static void uart_hostfs_txint(FAR struct uart_dev_s *dev, bool enable) +{ +} + +static bool uart_hostfs_txready(FAR struct uart_dev_s *dev) +{ + return true; +} + +static bool uart_hostfs_txempty(FAR struct uart_dev_s *dev) +{ + return true; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void uart_hostfs_init(void) +{ + uart_register("/dev/console", &g_uart_hostfs_dev); +} + +int up_putc(int ch) +{ + FAR struct uart_dev_s *dev = &g_uart_hostfs_dev; + + uart_hostfs_send(dev, ch); + return ch; +} diff --git a/include/nuttx/serial/uart_hostfs.h b/include/nuttx/serial/uart_hostfs.h new file mode 100644 index 00000000000..e0e1555f725 --- /dev/null +++ b/include/nuttx/serial/uart_hostfs.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * include/nuttx/serial/uart_hostfs.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SERIAL_UART_HOSTFS_H +#define __INCLUDE_NUTTX_SERIAL_UART_HOSTFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_UART_HOSTFS + +void uart_hostfs_init(void); + +#endif + +#endif /* __INCLUDE_NUTTX_SERIAL_UART_HOSTFS_H */