MYNEWT-671 UART support in sim Currently, sim always maps UARTs to ptys. This change allows the application to specify a file (e.g., /dev/...) to map a UART to.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/653a6974 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/653a6974 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/653a6974 Branch: refs/heads/nrf_cputime Commit: 653a6974083f9918fc105b568559995dde6d7713 Parents: 7894657 Author: Christopher Collins <[email protected]> Authored: Wed Mar 8 19:39:20 2017 -0800 Committer: Christopher Collins <[email protected]> Committed: Wed Mar 15 11:17:54 2017 -0700 ---------------------------------------------------------------------- hw/mcu/native/include/mcu/native_bsp.h | 2 + hw/mcu/native/src/hal_uart.c | 65 ++++++- hw/mcu/native/src/native_uart_cfg.c | 234 ++++++++++++++++++++++++++ hw/mcu/native/src/native_uart_cfg_priv.h | 12 ++ 4 files changed, 310 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/653a6974/hw/mcu/native/include/mcu/native_bsp.h ---------------------------------------------------------------------- diff --git a/hw/mcu/native/include/mcu/native_bsp.h b/hw/mcu/native/include/mcu/native_bsp.h index c8b6e13..dd79487 100644 --- a/hw/mcu/native/include/mcu/native_bsp.h +++ b/hw/mcu/native/include/mcu/native_bsp.h @@ -25,6 +25,8 @@ extern "C" { extern const struct hal_flash native_flash_dev; +int uart_set_dev(int port, const char *dev_str); + #ifdef __cplusplus } #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/653a6974/hw/mcu/native/src/hal_uart.c ---------------------------------------------------------------------- diff --git a/hw/mcu/native/src/hal_uart.c b/hw/mcu/native/src/hal_uart.c index 4c2c076..d9328aa 100644 --- a/hw/mcu/native/src/hal_uart.c +++ b/hw/mcu/native/src/hal_uart.c @@ -17,6 +17,7 @@ * under the License. */ +#include "defs/error.h" #include "os/os.h" #include "hal/hal_uart.h" #include "bsp/bsp.h" @@ -33,6 +34,10 @@ #include <assert.h> #include <unistd.h> #include <string.h> +#include <termios.h> +#include <errno.h> + +#include "native_uart_cfg_priv.h" #define UART_CNT 2 @@ -51,6 +56,8 @@ struct uart { void *u_func_arg; }; +const char *native_uart_dev_strs[UART_CNT]; + /* * XXXX should try to use O_ASYNC/SIGIO for byte arrival notification, * so we wouldn't need an OS for pseudo ttys. @@ -231,7 +238,7 @@ set_nonblock(int fd) } static int -uart_set_attr(int fd) +uart_pty_set_attr(int fd) { struct termios tios; @@ -268,7 +275,7 @@ uart_pty(int port) return -1; } - if (uart_set_attr(loop_slave)) { + if (uart_pty_set_attr(loop_slave)) { goto err; } @@ -281,6 +288,37 @@ err: return -1; } +/** + * Opens an external device terminal (/dev/cu.<...>). + */ +static int +uart_open_dev(int port, int32_t baudrate, uint8_t databits, + uint8_t stopbits, enum hal_uart_parity parity, + enum hal_uart_flow_ctl flow_ctl) +{ + const char *filename; + int fd; + int rc; + + filename = native_uart_dev_strs[port]; + assert(filename != NULL); + + fd = open(filename, O_RDWR); + if (fd < 0) { + return -1; + } + + rc = uart_dev_set_attr(fd, baudrate, databits, + stopbits, parity, flow_ctl); + if (rc != 0) { + return rc; + } + + dprintf(1, "uart%d at %s\n", port, filename); + + return fd; +} + void hal_uart_start_tx(int port) { @@ -363,12 +401,19 @@ hal_uart_config(int port, int32_t baudrate, uint8_t databits, uint8_t stopbits, return -1; } - uart->u_fd = uart_pty(port); + if (native_uart_dev_strs[port] == NULL) { + uart->u_fd = uart_pty(port); + } else { + uart->u_fd = uart_open_dev(port, baudrate, databits, stopbits, + parity, flow_ctl); + } + if (uart->u_fd < 0) { return -1; } set_nonblock(uart->u_fd); + uart_open_log(); uart->u_open = 1; return 0; @@ -405,4 +450,18 @@ hal_uart_init(int port, void *arg) return (0); } +int +uart_set_dev(int port, const char *dev_str) +{ + if (port < 0 || port >= UART_CNT) { + return SYS_EINVAL; + } + + if (uarts[port].u_open) { + return SYS_EBUSY; + } + native_uart_dev_strs[port] = dev_str; + + return 0; +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/653a6974/hw/mcu/native/src/native_uart_cfg.c ---------------------------------------------------------------------- diff --git a/hw/mcu/native/src/native_uart_cfg.c b/hw/mcu/native/src/native_uart_cfg.c new file mode 100644 index 0000000..4f9dcef --- /dev/null +++ b/hw/mcu/native/src/native_uart_cfg.c @@ -0,0 +1,234 @@ +/* + * 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. + */ + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <inttypes.h> +#include <termios.h> + +#include "defs/error.h" +#include "native_uart_cfg_priv.h" + +/* uint64 is used here to accommodate speed_t, whatever that is. */ +static const uint64_t uart_baud_table[][2] = { +#ifdef B50 + { 50, B50 }, +#endif +#ifdef B75 + { 75, B75 }, +#endif +#ifdef B110 + { 110, B110 }, +#endif +#ifdef B134 + { 134, B134 }, +#endif +#ifdef B150 + { 150, B150 }, +#endif +#ifdef B200 + { 200, B200 }, +#endif +#ifdef B300 + { 300, B300 }, +#endif +#ifdef B600 + { 600, B600 }, +#endif +#ifdef B1200 + { 1200, B1200 }, +#endif +#ifdef B1800 + { 1800, B1800 }, +#endif +#ifdef B2400 + { 2400, B2400 }, +#endif +#ifdef B4800 + { 4800, B4800 }, +#endif +#ifdef B9600 + { 9600, B9600 }, +#endif +#ifdef B19200 + { 19200, B19200 }, +#endif +#ifdef B38400 + { 38400, B38400 }, +#endif +#ifdef B57600 + { 57600, B57600 }, +#endif +#ifdef B115200 + { 115200, B115200 }, +#endif +#ifdef B230400 + { 230400, B230400 }, +#endif +#ifdef B460800 + { 460800, B460800 }, +#endif +#ifdef B500000 + { 500000, B500000 }, +#endif +#ifdef B576000 + { 576000, B576000 }, +#endif +#ifdef B921600 + { 921600, B921600 }, +#endif +#ifdef B1000000 + { 1000000, B1000000 }, +#endif +#ifdef B1152000 + { 1152000, B1152000 }, +#endif +#ifdef B1500000 + { 1500000, B1500000 }, +#endif +#ifdef B2000000 + { 2000000, B2000000 }, +#endif +#ifdef B2500000 + { 2500000, B2500000 }, +#endif +#ifdef B3000000 + { 3000000, B3000000 }, +#endif +#ifdef B3500000 + { 3500000, B3500000 }, +#endif +#ifdef B3710000 + { 3710000, B3710000 }, +#endif +#ifdef B4000000 + { 4000000, B4000000 }, +#endif +}; +#define UART_BAUD_TABLE_SZ (sizeof uart_baud_table / sizeof uart_baud_table[0]) + +/** + * Returns 0 on failure. + */ +speed_t +uart_baud_to_speed(int_least32_t baud) +{ + int i; + + for (i = 0; i < UART_BAUD_TABLE_SZ; i++) { + if (uart_baud_table[i][0] == baud) { + return uart_baud_table[i][1]; + } + } + + return 0; +} + +/** + * Configures an external device terminal (/dev/cu.<...>). + */ +int +uart_dev_set_attr(int fd, int32_t baudrate, uint8_t databits, + uint8_t stopbits, enum hal_uart_parity parity, + enum hal_uart_flow_ctl flow_ctl) +{ + struct termios tty; + speed_t speed; + int rc; + + assert(fd >= 0); + + memset(&tty, 0, sizeof(tty)); + cfmakeraw(&tty); + + speed = uart_baud_to_speed(baudrate); + if (speed == 0) { + fprintf(stderr, "invalid baud rate: %d\n", (int)baudrate); + assert(0); + } + + tty.c_cflag |= (speed | CLOCAL | CREAD); + + /* Disable flow control. */ + tty.c_cflag &= ~CRTSCTS; + + errno = 0; + rc = cfsetospeed(&tty, speed); + if (rc != 0) { + fprintf(stderr, "cfsetospeed failed; %d (%s) baudrate=%d\n", + errno, strerror(errno), (int)baudrate); + return -1; + } + + errno = 0; + rc = cfsetispeed(&tty, speed); + if (rc != 0) { + fprintf(stderr, "cfsetispeed failed; %d (%s) baudrate=%d\n", + errno, strerror(errno), (int)baudrate); + return -1; + } + + switch (databits) { + case 7: + tty.c_cflag |= CS7; + + switch (parity) { + case HAL_UART_PARITY_ODD: + tty.c_cflag |= PARENB; + tty.c_cflag |= PARODD; + tty.c_cflag &= ~CSTOPB; + tty.c_cflag &= ~CSIZE; + break; + + case HAL_UART_PARITY_EVEN: + tty.c_cflag |= PARENB; + tty.c_cflag &= ~PARODD; + tty.c_cflag &= ~CSTOPB; + tty.c_cflag &= ~CSIZE; + break; + + default: + return SYS_EINVAL; + } + + case 8: + if (parity != HAL_UART_PARITY_NONE) { + return SYS_EINVAL; + } + tty.c_cflag |= CS8; + tty.c_cflag &= ~PARENB; + tty.c_cflag &= ~CSTOPB; + tty.c_cflag &= ~CSIZE; + break; + + default: + return SYS_EINVAL; + } + + rc = tcsetattr(fd, TCSANOW, &tty); + if (rc != 0) { + dprintf(1, "tcsetattr failed; %d (%s)\n", errno, strerror(errno)); + return -1; + } + + return 0; +} + http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/653a6974/hw/mcu/native/src/native_uart_cfg_priv.h ---------------------------------------------------------------------- diff --git a/hw/mcu/native/src/native_uart_cfg_priv.h b/hw/mcu/native/src/native_uart_cfg_priv.h new file mode 100644 index 0000000..243cd45 --- /dev/null +++ b/hw/mcu/native/src/native_uart_cfg_priv.h @@ -0,0 +1,12 @@ +#ifndef H_NATIVE_UART_CFG_PRIV_ +#define H_NATIVE_UART_CFG_PRIV_ + +#include <termios.h> +#include "hal/hal_uart.h" + +speed_t uart_baud_to_speed(int_least32_t baud); +int uart_dev_set_attr(int fd, int32_t baudrate, uint8_t databits, + uint8_t stopbits, enum hal_uart_parity parity, + enum hal_uart_flow_ctl flow_ctl); + +#endif
