sim: add uart dma mode & use work instead of loop.

Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd 2023-02-03 18:44:03 +08:00 committed by archer
parent 739688f6c6
commit 1cc6e4b1fa
27 changed files with 233 additions and 119 deletions

View File

@ -106,6 +106,7 @@ config ARCH_SIM
select ONESHOT
select SERIAL_CONSOLE
select SERIAL_IFLOWCONTROL
select SCHED_HPWORK
---help---
Linux/Cygwin user-mode simulation.

View File

@ -504,6 +504,14 @@ endif
menu "Simulated UART"
config SIM_UART_DMA
bool "SIM UART use DMA mode"
default y
select SERIAL_TXDMA
select SERIAL_RXDMA
---help---
console use DMA mode or single char mode
config SIM_UART_NUMBER
int "Number of simulated UART ports"
default 0

View File

@ -131,25 +131,37 @@ void host_uart_close(int fd)
}
/****************************************************************************
* Name: host_uart_putc
* Name: host_uart_puts
****************************************************************************/
int host_uart_putc(int fd, int ch)
ssize_t host_uart_puts(int fd, const char *buf, size_t size)
{
return write(fd, &ch, 1) == 1 ? ch : -1;
ssize_t ret;
do
{
ret = write(fd, buf, size);
}
while (ret < 0 && errno == EINTR);
return ret < 0 ? -errno : ret;
}
/****************************************************************************
* Name: host_uart_getc
* Name: host_uart_gets
****************************************************************************/
int host_uart_getc(int fd)
ssize_t host_uart_gets(int fd, char *buf, size_t size)
{
int ret;
unsigned char ch;
ssize_t ret;
ret = read(fd, &ch, 1);
return ret < 0 ? ret : ch;
do
{
ret = read(fd, buf, size);
}
while (ret < 0 && errno == EINTR);
return ret < 0 ? -errno : ret;
}
/****************************************************************************

View File

@ -166,10 +166,6 @@ static int sim_loop_task(int argc, char **argv)
sched_lock();
/* Handle UART data availability */
sim_uartloop();
#if defined(CONFIG_SIM_TOUCHSCREEN) || defined(CONFIG_SIM_AJOYSTICK) || \
defined(CONFIG_SIM_BUTTONS)
/* Drive the X11 event loop */

View File

@ -209,19 +209,18 @@ void sim_timer_update(void);
/* sim_uart.c ***************************************************************/
void sim_uartinit(void);
void sim_uartloop(void);
/* sim_hostuart.c ***********************************************************/
void host_uart_start(void);
int host_uart_open(const char *pathname);
void host_uart_close(int fd);
int host_uart_putc(int fd, int ch);
int host_uart_getc(int fd);
bool host_uart_checkin(int fd);
bool host_uart_checkout(int fd);
int host_uart_setcflag(int fd, unsigned int cflag);
int host_uart_getcflag(int fd, unsigned int *cflag);
void host_uart_start(void);
int host_uart_open(const char *pathname);
void host_uart_close(int fd);
ssize_t host_uart_puts(int fd, const char *buf, size_t size);
ssize_t host_uart_gets(int fd, char *buf, size_t size);
bool host_uart_checkin(int fd);
bool host_uart_checkout(int fd);
int host_uart_setcflag(int fd, unsigned int cflag);
int host_uart_getcflag(int fd, unsigned int *cflag);
/* sim_deviceimage.c ********************************************************/

View File

@ -25,6 +25,7 @@
#include <nuttx/config.h>
#include <nuttx/serial/serial.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/wqueue.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
@ -36,23 +37,12 @@
* Pre-processor Definitions
****************************************************************************/
#define SIM_UART_WORK_DELAY USEC2TICK(1000)
#ifndef CONFIG_SIM_UART_BUFFER_SIZE
#define CONFIG_SIM_UART_BUFFER_SIZE 256
#endif
#define TTY_RECVSEND(port) \
if (g_##port##_priv.fd >= 0) \
{ \
if (g_##port##_priv.rxint) \
{ \
uart_recvchars(&g_##port##_dev); \
} \
if (g_##port##_priv.txint) \
{ \
uart_xmitchars(&g_##port##_dev); \
} \
} \
/****************************************************************************
* Private Types
****************************************************************************/
@ -61,19 +51,23 @@ struct tty_priv_s
{
/* tty-port path name */
const char *path;
const char *path;
/* The file descriptor. It is returned by open */
int fd;
int fd;
/* TX interrupt enable or not */
bool txint;
bool txint;
/* RX interrupt enable or not */
bool rxint;
bool rxint;
/* Work queue for transmit */
struct work_s worker;
};
/****************************************************************************
@ -91,6 +85,12 @@ static void tty_rxint(struct uart_dev_s *dev, bool enable);
static bool tty_rxavailable(struct uart_dev_s *dev);
static bool tty_rxflowcontrol(struct uart_dev_s *dev,
unsigned int nbuffered, bool upper);
#ifdef CONFIG_SIM_UART_DMA
static void tty_dmatxavail(FAR struct uart_dev_s *dev);
static void tty_dmasend(FAR struct uart_dev_s *dev);
static void tty_dmarxfree(FAR struct uart_dev_s *dev);
static void tty_dmareceive(FAR struct uart_dev_s *dev);
#endif
static void tty_send(struct uart_dev_s *dev, int ch);
static void tty_txint(struct uart_dev_s *dev, bool enable);
static bool tty_txready(struct uart_dev_s *dev);
@ -111,6 +111,12 @@ static const struct uart_ops_s g_tty_ops =
.rxint = tty_rxint,
.rxavailable = tty_rxavailable,
.rxflowcontrol = tty_rxflowcontrol,
#ifdef CONFIG_SIM_UART_DMA
.dmatxavail = tty_dmatxavail,
.dmasend = tty_dmasend,
.dmarxfree = tty_dmarxfree,
.dmareceive = tty_dmareceive,
#endif
.send = tty_send,
.txint = tty_txint,
.txready = tty_txready,
@ -388,9 +394,52 @@ static int tty_ioctl(struct file *filep, int cmd, unsigned long arg)
static int tty_receive(struct uart_dev_s *dev, uint32_t *status)
{
struct tty_priv_s *priv = dev->priv;
char ch = 0;
*status = 0;
return host_uart_getc(priv->fd);
host_uart_gets(priv->fd, &ch, 1);
return ch;
}
/****************************************************************************
* Name: tty_work
*
* Description:
* Notify DMA that there is data to be transferred in the TX buffer
*
****************************************************************************/
static void tty_work(void *arg)
{
struct uart_dev_s *dev = arg;
struct tty_priv_s *priv = dev->priv;
if (priv->fd < 0)
{
return;
}
if (priv->txint && host_uart_checkout(dev->isconsole ? 1 : priv->fd))
{
#ifdef CONFIG_SIM_UART_DMA
uart_xmitchars_dma(dev);
#else
uart_xmitchars(dev);
#endif
}
if (priv->rxint && host_uart_checkin(priv->fd))
{
#ifdef CONFIG_SIM_UART_DMA
uart_recvchars_dma(dev);
#else
uart_recvchars(dev);
#endif
}
work_queue(HPWORK, &priv->worker,
tty_work, dev, SIM_UART_WORK_DELAY);
}
/****************************************************************************
@ -406,6 +455,10 @@ static void tty_rxint(struct uart_dev_s *dev, bool enable)
struct tty_priv_s *priv = dev->priv;
priv->rxint = enable;
if (enable)
{
work_queue(HPWORK, &priv->worker, tty_work, dev, 0);
}
}
/****************************************************************************
@ -445,6 +498,101 @@ static bool tty_rxflowcontrol(struct uart_dev_s *dev,
return false;
}
#ifdef CONFIG_SIM_UART_DMA
/****************************************************************************
* Name: tty_dmatxavail
*
* Description:
* Notify DMA that there is data to be transferred in the TX buffer
*
****************************************************************************/
static void tty_dmatxavail(FAR struct uart_dev_s *dev)
{
}
/****************************************************************************
* Name: tty_dmasend
*
* Description:
* Start transfer bytes from the TX circular buffer using DMA
*
****************************************************************************/
static void tty_dmasend(FAR struct uart_dev_s *dev)
{
struct tty_priv_s *priv = dev->priv;
struct uart_dmaxfer_s *xfer = &dev->dmatx;
int fd = dev->isconsole ? 1 : priv->fd;
int ret;
xfer->nbytes = 0;
ret = host_uart_puts(fd, xfer->buffer, xfer->length);
if (ret > 0)
{
xfer->nbytes = ret;
if (ret == xfer->length && xfer->nlength > 0)
{
ret = host_uart_puts(fd, xfer->nbuffer, xfer->nlength);
if (ret > 0)
{
xfer->nbytes += ret;
}
}
}
uart_xmitchars_done(dev);
}
/****************************************************************************
* Name: tty_dmarxfree
*
* Description:
* Notify DMA that there is free space in the RX buffer
*
****************************************************************************/
static void tty_dmarxfree(FAR struct uart_dev_s *dev)
{
}
/****************************************************************************
* Name: tty_dmareceive
*
* Description:
* Start receive bytes from the RX circular buffer using DMA
*
****************************************************************************/
static void tty_dmareceive(FAR struct uart_dev_s *dev)
{
struct tty_priv_s *priv = dev->priv;
struct uart_dmaxfer_s *xfer = &dev->dmarx;
int ret;
xfer->nbytes = 0;
ret = host_uart_gets(priv->fd, xfer->buffer, xfer->length);
if (ret > 0)
{
xfer->nbytes = ret;
if (ret == xfer->length && xfer->nlength > 0)
{
ret = host_uart_gets(priv->fd, xfer->nbuffer, xfer->nlength);
if (ret > 0)
{
xfer->nbytes += ret;
}
}
}
uart_recvchars_done(dev);
}
#endif
/****************************************************************************
* Name: tty_send
*
@ -456,8 +604,9 @@ static bool tty_rxflowcontrol(struct uart_dev_s *dev,
static void tty_send(struct uart_dev_s *dev, int ch)
{
struct tty_priv_s *priv = dev->priv;
char c = ch;
host_uart_putc(dev->isconsole ? 1 : priv->fd, ch);
host_uart_puts(dev->isconsole ? 1 : priv->fd, &c, 1);
}
/****************************************************************************
@ -473,10 +622,9 @@ static void tty_txint(struct uart_dev_s *dev, bool enable)
struct tty_priv_s *priv = dev->priv;
priv->txint = enable;
if (enable)
{
uart_xmitchars(dev);
work_queue(HPWORK, &priv->worker, tty_work, dev, 0);
}
}
@ -547,29 +695,25 @@ void sim_uartinit(void)
}
/****************************************************************************
* Name: sim_uartloop
* Name: up_nputs
*
* Description:
* This is a low-level helper function used to support debug.
*
****************************************************************************/
void sim_uartloop(void)
void up_nputs(const char *str, size_t len)
{
#ifdef USE_DEVCONSOLE
TTY_RECVSEND(console)
#endif
#ifdef CONFIG_SIM_UART0_NAME
TTY_RECVSEND(tty0)
#endif
#ifdef CONFIG_SIM_UART1_NAME
TTY_RECVSEND(tty1)
#endif
#ifdef CONFIG_SIM_UART2_NAME
TTY_RECVSEND(tty2)
#endif
#ifdef CONFIG_SIM_UART3_NAME
TTY_RECVSEND(tty3)
if (str[len - 1] == '\n')
{
host_uart_puts(1, str, len - 1);
host_uart_puts(1, "\r\n", 2);
}
else
{
host_uart_puts(1, str, len);
}
#endif
}
@ -580,28 +724,9 @@ void sim_uartloop(void)
int up_putc(int ch)
{
#ifdef USE_DEVCONSOLE
if (ch == '\n')
{
tty_send(&g_console_dev, '\r');
}
tty_send(&g_console_dev, ch);
char c = ch;
up_nputs(&c, 1);
#endif
return 0;
}
/****************************************************************************
* Name: up_nputs
*
* Description:
* This is a low-level helper function used to support debug.
*
****************************************************************************/
void up_nputs(const char *str, size_t len)
{
while (len-- > 0 && *str)
{
up_putc(*str++);
}
}

View File

@ -78,33 +78,28 @@ void host_uart_close(int fd)
* Name: host_uart_putc
****************************************************************************/
int host_uart_putc(int fd, int ch)
ssize_t host_uart_puts(int fd, const char *buf, size_t size)
{
DWORD nwritten;
int ret;
if (WriteConsole(g_stdout_handle, &ch, 1, &nwritten, NULL))
{
return ch;
}
ret = WriteConsole(g_stdout_handle, buf, size, &nwritten, NULL);
return -EIO;
return ret == 0 ? -EIO : nwritten;
}
/****************************************************************************
* Name: host_uart_getc
****************************************************************************/
int host_uart_getc(int fd)
ssize_t host_uart_gets(int fd, char *buf, size_t size)
{
unsigned char ch;
DWORD nread;
int ret;
if (ReadConsole(g_stdin_handle, &ch, 1, &nread, 0))
{
return ch;
}
ret = ReadConsole(g_stdin_handle, buf, size, &nread, 0);
return -EIO;
return ret == 0 ? -EIO : nread;
}
/****************************************************************************

View File

@ -72,7 +72,6 @@ CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_BACKTRACE=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_START_MONTH=6
CONFIG_START_YEAR=2008
CONFIG_SYSTEM_DUMPSTACK=y

View File

@ -63,7 +63,6 @@ CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_BACKTRACE=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_START_MONTH=6
CONFIG_START_YEAR=2008

View File

@ -81,7 +81,6 @@ CONFIG_PATH_INITIAL="/bin"
CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=2048
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_SPORADIC=y
CONFIG_SCHED_WAITPID=y
CONFIG_START_MONTH=6

View File

@ -57,7 +57,6 @@ CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=2048
CONFIG_PSEUDOFS_ATTRIBUTES=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_HPWORK=y
CONFIG_SERIAL_TERMIOS=y
CONFIG_SIG_DEFAULT=y
CONFIG_START_MONTH=6

View File

@ -63,7 +63,6 @@ CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_BACKTRACE=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_START_MONTH=6
CONFIG_START_YEAR=2008

View File

@ -26,8 +26,6 @@ CONFIG_MTD_READAHEAD=y
CONFIG_MTD_WRBUFFER=y
CONFIG_RAMMTD=y
CONFIG_RAMMTD_FLASHSIM=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_HPWORKPRIORITY=192
CONFIG_START_DAY=29
CONFIG_START_MONTH=4
CONFIG_START_YEAR=2011

View File

@ -62,7 +62,6 @@ CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_BACKTRACE=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SIM_WALLTIME_SIGNAL=y
CONFIG_START_MONTH=6

View File

@ -59,7 +59,6 @@ CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_BACKTRACE=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SIM_FBHEIGHT=480
CONFIG_SIM_FBWIDTH=640
CONFIG_SIM_X11FB=y

View File

@ -49,7 +49,6 @@ CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=2048
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_BACKTRACE=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SIM_UART0_NAME="./ttySIM0"
CONFIG_SIM_UART_BUFFER_SIZE=1024

View File

@ -45,8 +45,6 @@ CONFIG_NXWM_BACKGROUND_IMAGE=""
CONFIG_NXWM_TASKBAR_LEFT=y
CONFIG_NX_BLOCKING=y
CONFIG_NX_KBD=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_HPWORKPRIORITY=192
CONFIG_SCHED_WAITPID=y
CONFIG_SIM_FBBPP=32
CONFIG_SIM_X11FB=y

View File

@ -60,7 +60,6 @@ CONFIG_PTHREAD_STACK_DEFAULT=4096
CONFIG_RAM_SIZE=393216
CONFIG_RAM_START=0x20400000
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_STANDARD_SERIAL=y
CONFIG_START_DAY=10

View File

@ -83,7 +83,6 @@ CONFIG_PTHREAD_STACK_DEFAULT=4096
CONFIG_RAM_SIZE=393216
CONFIG_RAM_START=0x20400000
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_STANDARD_SERIAL=y
CONFIG_START_DAY=10

View File

@ -64,7 +64,6 @@ CONFIG_RTC_RPMSG=y
CONFIG_RTC_RPMSG_SERVER_NAME="server"
CONFIG_SCHED_CHILD_STATUS=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SENSORS=y
CONFIG_SENSORS_RPMSG=y

View File

@ -83,7 +83,6 @@ CONFIG_RTC_RPMSG=y
CONFIG_RTC_RPMSG_SERVER=y
CONFIG_SCHED_CHILD_STATUS=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SENSORS=y
CONFIG_SENSORS_RPMSG=y

View File

@ -59,7 +59,6 @@ CONFIG_PSEUDOFS_ATTRIBUTES=y
CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_START_MONTH=6
CONFIG_START_YEAR=2008

View File

@ -60,7 +60,6 @@ CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_CRITMONITOR=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_INSTRUMENTATION=y
CONFIG_SCHED_INSTRUMENTATION_FILTER=y
CONFIG_SCHED_INSTRUMENTATION_SYSCALL=y

View File

@ -83,7 +83,6 @@ CONFIG_PTHREAD_STACK_DEFAULT=4096
CONFIG_RAM_SIZE=393216
CONFIG_RAM_START=0x20400000
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_STANDARD_SERIAL=y
CONFIG_START_DAY=10

View File

@ -95,7 +95,6 @@ CONFIG_READLINE_CMD_HISTORY=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_CHILD_STATUS=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SERIAL_TERMIOS=y
CONFIG_SIG_DEFAULT=y
CONFIG_SIG_EVTHREAD=y

View File

@ -28,6 +28,5 @@ CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_READLINE=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SYSTEM_NSH=y

View File

@ -46,7 +46,6 @@ CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_CHILDSTATUS=2
CONFIG_SCHED_CHILD_STATUS=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SIM_HOSTFS=y