Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Documentation/platforms/sim/sim/boards/sim/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2173,10 +2173,23 @@ nxscope

Configuration demonstrating NxScope stream over simulated UART interface.

The simulated UART must be created on host before running NuttX::
If ``CONFIG_SIM_UART_PTY`` is disabled, the simulated UART peer must be
created on the host before running NuttX::

socat PTY,link=/dev/ttySIM0 PTY,link=/dev/ttyNX0

In that mode ``CONFIG_SIM_UART0_NAME`` is both the NuttX device name and
the host path that the sim UART backend opens. This works when the host
path is stable, but it is inconvenient for automated tests and generated
PTYs: the peer device must exist before the UART is opened, and changing
the host path requires changing the NuttX configuration.

If ``CONFIG_SIM_UART_PTY`` is enabled, NuttX creates the host
pseudoterminal when the simulated UART is opened and prints the host
PTY slave path. The configured ``SIM_UARTx_NAME`` remains the NuttX
device name, while the host PTY path is allocated at runtime and can be
passed to the external simulator or test program.

See :doc:`/applications/examples/nxscope/index` and
:doc:`/applications/logging/nxscope/index` for more details.

Expand Down
60 changes: 48 additions & 12 deletions arch/sim/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,11 @@ config SIM_UART_NUMBER
Anything sent to the one of these ports will be relayed
automatically to the other, and vice-versa.

If SIM_UART_PTY is enabled, NuttX creates the simulated
host pseudoterminal itself. In that mode SIM_UARTx_NAME is
only the NuttX device name, and the host pseudoterminal path
is printed when the port is opened.

config SIM_UART_BUFFER_SIZE
int "UART buffer size"
default 256
Expand All @@ -784,49 +789,80 @@ config SIM_UART_BUFFER_SIZE

Note that all ports will have the same buffer size.

config SIM_UART_PTY
bool "Create host pseudoterminals for simulated UART ports"
default n
depends on HOST_LINUX && SIM_UART_NUMBER >= 1
---help---
Open a new host pseudoterminal for each simulated UART
instead of opening an existing host serial device. The
UART remains registered in NuttX using SIM_UARTx_NAME, and
the host PTY slave path is printed when the port is opened.

The existing behavior requires the host endpoint named by
SIM_UARTx_NAME to exist before the simulated UART is opened.
This makes automated tests awkward when the peer endpoint is
a generated PTY with a host-dependent path, because the host
path must be prepared up front and encoded in the NuttX
configuration. With this option enabled, the sim UART
backend owns the host PTY allocation and reports the actual
slave path at runtime, while keeping the NuttX device name
stable for applications.

If disabled, SIM UART keeps the existing behavior and opens
the host device path specified by SIM_UARTx_NAME directly.

config SIM_UART0_NAME
string "UART port 0 name"
default "/dev/ttySIM0"
depends on SIM_UART_NUMBER >= 1
---help---
This is the name of the simulated UART port.
The port will be mounted in NuttX under this name.
The port will be registered in NuttX under this name.

A UART port must also exist on the host system
with the exact same name specified here.
If SIM_UART_PTY is disabled, a UART port must also exist on
the host system with the exact same name specified here. If
SIM_UART_PTY is enabled, the host pseudoterminal is allocated
automatically and printed when this port is opened.

config SIM_UART1_NAME
string "UART port 1 name"
default "/dev/ttySIM1"
depends on SIM_UART_NUMBER >= 2
---help---
This is the name of the simulated UART port.
The port will be mounted in NuttX under this name.
The port will be registered in NuttX under this name.

A UART port must also exist on the host system
with the exact same name specified here.
If SIM_UART_PTY is disabled, a UART port must also exist on
the host system with the exact same name specified here. If
SIM_UART_PTY is enabled, the host pseudoterminal is allocated
automatically and printed when this port is opened.

config SIM_UART2_NAME
string "UART port 2 name"
default "/dev/ttySIM2"
depends on SIM_UART_NUMBER >= 3
---help---
This is the name of the simulated UART port.
The port will be mounted in NuttX under this name.
The port will be registered in NuttX under this name.

A UART port must also exist on the host system
with the exact same name specified here.
If SIM_UART_PTY is disabled, a UART port must also exist on
the host system with the exact same name specified here. If
SIM_UART_PTY is enabled, the host pseudoterminal is allocated
automatically and printed when this port is opened.

config SIM_UART3_NAME
string "UART port 3 name"
default "/dev/ttySIM3"
depends on SIM_UART_NUMBER >= 4
---help---
This is the name of the simulated UART port.
The port will be mounted in NuttX under this name.
The port will be registered in NuttX under this name.

A UART port must also exist on the host system
with the exact same name specified here.
If SIM_UART_PTY is disabled, a UART port must also exist on
the host system with the exact same name specified here. If
SIM_UART_PTY is enabled, the host pseudoterminal is allocated
automatically and printed when this port is opened.

config SIM_RAM_UART
bool "SIM RAM UART Device"
Expand Down
57 changes: 55 additions & 2 deletions arch/sim/src/sim/posix/sim_hostuart.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Included Files
****************************************************************************/

#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdbool.h>
#include <unistd.h>
Expand Down Expand Up @@ -130,6 +131,58 @@ int host_uart_open(const char *pathname)
return fd;
}

/****************************************************************************
* Name: host_uart_openpty
****************************************************************************/

int host_uart_openpty(const char *name)
{
#ifdef CONFIG_HOST_LINUX
unsigned int ptyno;
int lock = 0;
int oflags;
int ret;
int fd;

oflags = O_RDWR | O_NOCTTY | O_NONBLOCK;
#ifdef O_CLOEXEC
oflags |= O_CLOEXEC;
#endif
fd = open("/dev/ptmx", oflags);
if (fd < 0)
{
return -errno;
}

ret = ioctl(fd, TIOCGPTN, &ptyno);
if (ret < 0)
{
ret = -errno;
goto errout;
}

ret = ioctl(fd, TIOCSPTLCK, &lock);
if (ret < 0)
{
ret = -errno;
goto errout;
}

setrawmode(fd);

printf("%s connected to pseudotty: /dev/pts/%u\n", name, ptyno);

return fd;

errout:
close(fd);
return ret;
#else
(void)name;
return -ENOSYS;
#endif
}

/****************************************************************************
* Name: host_uart_close
****************************************************************************/
Expand Down Expand Up @@ -229,7 +282,7 @@ bool host_uart_checkin(int fd)

pfd.fd = fd;
pfd.events = POLLIN;
return poll(&pfd, 1, 0) == 1;
return poll(&pfd, 1, 0) == 1 && (pfd.revents & POLLIN) != 0;
}

/****************************************************************************
Expand All @@ -242,7 +295,7 @@ bool host_uart_checkout(int fd)

pfd.fd = fd;
pfd.events = POLLOUT;
return poll(&pfd, 1, 0) == 1;
return poll(&pfd, 1, 0) == 1 && (pfd.revents & POLLOUT) != 0;
}

/****************************************************************************
Expand Down
1 change: 1 addition & 0 deletions arch/sim/src/sim/sim_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ void sim_uartinit(void);

void host_uart_start(void);
int host_uart_open(const char *pathname);
int host_uart_openpty(const char *name);
void host_uart_close(int fd);
int host_uart_puts(int fd, const char *buf, size_t size);
int host_uart_gets(int fd, char *buf, size_t size);
Expand Down
17 changes: 13 additions & 4 deletions arch/sim/src/sim/sim_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,17 +307,26 @@ static void uart_nputs(int fd, const char *buf, size_t size)
* Name: tty_setup
*
* Description:
* Configure the UART baud, bits, parity, fifos, etc. This
* method is called the first time that the serial port is
* opened.
* Open and configure the host endpoint for the simulated UART.
* This method is called the first time that the serial port is opened.
*
****************************************************************************/

static int tty_setup(struct uart_dev_s *dev)
{
struct tty_priv_s *priv = dev->priv;

priv->fd = host_uart_open(priv->path);
#ifdef CONFIG_SIM_UART_PTY
if (!dev->isconsole)
{
priv->fd = host_uart_openpty(priv->path);
}
else
#endif
{
priv->fd = host_uart_open(priv->path);
}

return priv->fd;
}

Expand Down
10 changes: 10 additions & 0 deletions arch/sim/src/sim/win/sim_hostuart.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ int host_uart_open(const char *pathname)
return -ENOSYS;
}

/****************************************************************************
* Name: host_uart_openpty
****************************************************************************/

int host_uart_openpty(const char *name)
{
(void)name;
return -ENOSYS;
}

/****************************************************************************
* Name: host_uart_close
****************************************************************************/
Expand Down
Loading