uart: native_posix: Add support for another serial port

The second serial port (UART_1) can be used for connecting to
host serial port. This is used for example by PPP (Point-to-Point
Protocol) implementation in which case the pppd running in Linux host
connects to a pty that is linked to UART_1 in Zephyr.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2019-04-15 10:10:02 +03:00 committed by Anas Nashif
parent 538e12e5c3
commit f521996d71
3 changed files with 115 additions and 41 deletions

View file

@ -536,8 +536,13 @@ The following peripherals are currently provided with this board:
UART
*****
This driver can be configured to either create and link the UART to a new
pseudoterminal (i.e. ``/dev/pts<nbr>``), or to map the UART input and
This driver can be configured with :option:`CONFIG_UART_NATIVE_POSIX`
to instantiate up to two UARTs. By default only one UART is enabled.
With :option:`CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE`
you can enable the second one.
For the first UART, it can link it to a new
pseudoterminal (i.e. ``/dev/pts<nbr>``), or map the UART input and
output to the executable's ``stdin`` and ``stdout``.
This is chosen by selecting either
:option:`CONFIG_NATIVE_UART_0_ON_OWN_PTY` or
@ -557,8 +562,8 @@ to it. This can be done, for example with the command::
where ``/dev/<ttyn>`` should be replaced with the actual TTY device.
You may also chose to automatically attach a terminal emulator to it by
passing the command line option ``-attach_uart`` to the executable.
You may also chose to automatically attach a terminal emulator to the first UART
by passing the command line option ``-attach_uart`` to the executable.
The command used for attaching to the new shell can be set with the command line
option ``-attach_uart_cmd=<"cmd">``. Where the default command is given by
:option:`CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD`.

View file

@ -5,9 +5,10 @@ config UART_NATIVE_POSIX
select SERIAL_HAS_DRIVER
depends on ARCH_POSIX
help
This enables a UART driver for the POSIX ARCH. The driver can be configured
This enables a UART driver for the POSIX ARCH with up to 2 UARTs.
For the first UART port, the driver can be configured
to either connect to the terminal from which native_posix was run, or into
one dedicated pseudoterminal for this UART.
one dedicated pseudoterminal for that UART.
if UART_NATIVE_POSIX
@ -15,8 +16,8 @@ config UART_NATIVE_POSIX_PORT_0_NAME
string "Port 0 Device Name"
default "UART_0"
help
This is the device name for UART, and is included in the device
struct.
This is the device name for the first UART, and is included in the
device struct.
choice
prompt "Native UART Port 0 connection"
@ -25,36 +26,52 @@ choice
config NATIVE_UART_0_ON_OWN_PTY
bool "Connect the UART to its own pseudo terminal"
help
Connect the UART to its own pseudoterminal. This is the preferred option
for users who want to use Zephyr's shell.
Moreover this option does not conflict with any other native_posix backend
which may use the calling shell standard input/output.
Connect this UART to its own pseudoterminal. This is the preferred
option for users who want to use Zephyr's shell.
Moreover this option does not conflict with any other native_posix
backend which may use the calling shell standard input/output.
config NATIVE_UART_0_ON_STDINOUT
bool "Connect the UART to the invoking shell stdin/stdout"
help
Connect the UART to the stdin & stdout of the calling shell/terminal which
invoked the native_posix executable. This is good enough for automated
testing, or when feeding from a file/pipe.
Note that other, non UART messages, will also be printed to the terminal.
This option should NOT be used in conjunction with
Connect this UART to the stdin & stdout of the calling shell/terminal
which invoked the native_posix executable. This is good enough for
automated testing, or when feeding from a file/pipe.
Note that other, non UART messages, will also be printed to the
terminal. This option should NOT be used in conjunction with
NATIVE_POSIX_STDIN_CONSOLE
It is strongly discouraged to try to use this option with the new shell
interactively, as the default terminal configuration is NOT appropriate
for interactive use.
It is strongly discouraged to try to use this option with the new
shell interactively, as the default terminal configuration is NOT
appropriate for interactive use.
endchoice
config UART_NATIVE_POSIX_PORT_1_ENABLE
bool "Enable second UART port"
help
Useful if you need to have another serial connection to host.
This is used for example in PPP (Point-to-Point Protocol)
implementation.
config UART_NATIVE_POSIX_PORT_1_NAME
string "Port 1 Device Name"
default "UART_1"
depends on UART_NATIVE_POSIX_PORT_1_ENABLE
help
This is the device name for UART, and is included in the device
struct.
config NATIVE_UART_AUTOATTACH_DEFAULT_CMD
string "Default command to attach the UART to a new terminal"
default "xterm -e screen %s &"
help
If the native_posix executable is called with the --attach_uart command line
option, this will be the default command which will be run to attach a new
terminal to it.
Note that this command must have one, and only one, '%s' as placeholder for
the pseudoterminal device name (e.g. /dev/pts/35)
This is only applicable if a UART is configured to use its own PTY with
NATIVE_UART_x_ON_OWN_PTY.
If the native_posix executable is called with the --attach_uart
command line option, this will be the default command which will be
run to attach a new terminal to the 1st UART.
Note that this command must have one, and only one, '%s' as
placeholder for the pseudoterminal device name (e.g. /dev/pts/35)
This is only applicable if the UART_0 is configured to use its own
PTY with NATIVE_UART_0_ON_OWN_PTY.
The 2nd UART will not be affected by this option.
endif # UART_NATIVE_POSIX

View file

@ -20,6 +20,10 @@
/*
* UART driver for POSIX ARCH based boards.
* It can support up to two UARTs.
*
* For the first UART:
*
* It can either be connected to the process STDIN+STDOUT
* OR
* to a dedicated pseudo terminal
@ -41,11 +45,22 @@ static bool auto_attach;
static const char default_cmd[] = CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD;
static char *auto_attach_cmd;
static struct uart_driver_api np_uart_driver_api = {
static struct native_uart_status native_uart_status_0;
static struct uart_driver_api np_uart_driver_api_0 = {
.poll_out = np_uart_poll_out,
.poll_in = np_uart_tty_poll_in,
};
#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE)
static struct native_uart_status native_uart_status_1;
static struct uart_driver_api np_uart_driver_api_1 = {
.poll_out = np_uart_poll_out,
.poll_in = np_uart_tty_poll_in,
};
#endif /* CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE */
struct native_uart_status {
int out_fd; /* File descriptor used for output */
int in_fd; /* File descriptor used for input */
@ -84,7 +99,9 @@ static void attach_to_tty(const char *slave_tty)
* If auto_attach was set, it will also attempt to connect a new terminal
* emulator to its slave side.
*/
static int open_tty(void)
static int open_tty(struct native_uart_status *driver_data,
const char *uart_name,
bool do_auto_attach)
{
int master_pty;
char *slave_pty_name;
@ -160,9 +177,10 @@ static int open_tty(void)
ERROR("Could not change terminal driver settings\n");
}
posix_print_trace("UART connected to pseudotty: %s\n", slave_pty_name);
posix_print_trace("%s connected to pseudotty: %s\n",
uart_name, slave_pty_name);
if (auto_attach) {
if (do_auto_attach) {
attach_to_tty(slave_pty_name);
}
@ -170,28 +188,29 @@ static int open_tty(void)
}
/**
* @brief Initialize the native_posix serial port
* @brief Initialize the first native_posix serial port
*
* @param dev UART device struct
* @param dev UART_0 device struct
*
* @return 0 (if it fails catastrophically, the execution is terminated)
*/
static int np_uart_init(struct device *dev)
static int np_uart_0_init(struct device *dev)
{
struct native_uart_status *d;
d = (struct native_uart_status *)dev->driver_data;
if (IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) {
int tty_fn = open_tty();
int tty_fn = open_tty(d, CONFIG_UART_NATIVE_POSIX_PORT_0_NAME,
auto_attach);
d->in_fd = tty_fn;
d->out_fd = tty_fn;
np_uart_driver_api.poll_in = np_uart_tty_poll_in;
np_uart_driver_api_0.poll_in = np_uart_tty_poll_in;
} else { /* NATIVE_UART_0_ON_STDINOUT */
d->in_fd = STDIN_FILENO;
d->out_fd = STDOUT_FILENO;
np_uart_driver_api.poll_in = np_uart_stdin_poll_in;
np_uart_driver_api_0.poll_in = np_uart_stdin_poll_in;
if (isatty(STDIN_FILENO)) {
WARN("The UART driver has been configured to map to the"
@ -207,6 +226,27 @@ static int np_uart_init(struct device *dev)
return 0;
}
#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE)
/*
* Initialize the 2nd UART port.
* This port will be always attached to its own new pseudoterminal.
*/
static int np_uart_1_init(struct device *dev)
{
struct native_uart_status *d;
int tty_fn;
d = (struct native_uart_status *)dev->driver_data;
tty_fn = open_tty(d, CONFIG_UART_NATIVE_POSIX_PORT_1_NAME, false);
d->in_fd = tty_fn;
d->out_fd = tty_fn;
return 0;
}
#endif
/*
* @brief Output a character towards the serial port
*
@ -296,13 +336,19 @@ static int np_uart_tty_poll_in(struct device *dev, unsigned char *p_char)
return 0;
}
static struct native_uart_status native_uart_status_0;
DEVICE_AND_API_INIT(uart_native_posix0,
CONFIG_UART_NATIVE_POSIX_PORT_0_NAME, &np_uart_init,
CONFIG_UART_NATIVE_POSIX_PORT_0_NAME, &np_uart_0_init,
(void *)&native_uart_status_0, NULL,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&np_uart_driver_api);
&np_uart_driver_api_0);
#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE)
DEVICE_AND_API_INIT(uart_native_posix1,
CONFIG_UART_NATIVE_POSIX_PORT_1_NAME, &np_uart_1_init,
(void *)&native_uart_status_1, NULL,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&np_uart_driver_api_1);
#endif /* CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE */
static void np_add_uart_options(void)
{
@ -341,6 +387,12 @@ static void np_cleanup_uart(void)
close(native_uart_status_0.in_fd);
}
}
#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE)
if (native_uart_status_1.in_fd != 0) {
close(native_uart_status_1.in_fd);
}
#endif
}
NATIVE_TASK(np_add_uart_options, PRE_BOOT_1, 11);