native: add UART driver based on /dev/tty
uart0 functionality is removed by #3164. This patch implements periph/uart, rather than deprecated uart0, using /dev/tty. To use with netdev2_tap simultaneously, this patch adds asynchronus read system and modifies netdev2_tap to use it. A TTY device is specified on command line with -c (COM) option, since -t was used by the old implementation. This patch also implements empty GPIO driver needed by the xbee driver.
This commit is contained in:
parent
4f17d2bd9c
commit
79d33897cb
|
@ -3,6 +3,8 @@ FEATURES_PROVIDED += periph_cpuid
|
|||
FEATURES_PROVIDED += periph_hwrng
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
FEATURES_PROVIDED += periph_gpio
|
||||
|
||||
# Various other features (if any)
|
||||
FEATURES_PROVIDED += config
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
/**
|
||||
* Multiple asynchronus read on file descriptors
|
||||
*
|
||||
* Copyright (C) 2015 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>,
|
||||
* Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* Ell-i open source co-operative
|
||||
* Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*
|
||||
* @ingroup native_cpu
|
||||
* @{
|
||||
* @file
|
||||
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "async_read.h"
|
||||
#include "native_internal.h"
|
||||
|
||||
static int _next_index;
|
||||
static int _fds[ASYNC_READ_NUMOF];
|
||||
static native_async_read_callback_t _native_async_read_callbacks[ASYNC_READ_NUMOF];
|
||||
|
||||
#ifdef __MACH__
|
||||
static pid_t _sigio_child_pids[ASYNC_READ_NUMOF];
|
||||
static void _sigio_child(int fd);
|
||||
#endif
|
||||
|
||||
static void _async_io_isr(void) {
|
||||
fd_set rfds;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
|
||||
int max_fd = 0;
|
||||
|
||||
for (int i = 0; i < _next_index; i++) {
|
||||
FD_SET(_fds[i], &rfds);
|
||||
|
||||
if (max_fd < _fds[i]) {
|
||||
max_fd = _fds[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (real_select(max_fd + 1, &rfds, NULL, NULL, NULL) > 0) {
|
||||
for (int i = 0; i < _next_index; i++) {
|
||||
if (FD_ISSET(_fds[i], &rfds)) {
|
||||
_native_async_read_callbacks[i](_fds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void native_async_read_setup(void) {
|
||||
register_interrupt(SIGIO, _async_io_isr);
|
||||
}
|
||||
|
||||
void native_async_read_cleanup(void) {
|
||||
unregister_interrupt(SIGIO);
|
||||
|
||||
#ifdef __MACH__
|
||||
for (int i = 0; i < _next_index; i++) {
|
||||
kill(_sigio_child_pids[i], SIGKILL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void native_async_read_continue(int fd) {
|
||||
(void) fd;
|
||||
#ifdef __MACH__
|
||||
for (int i = 0; i < _next_index; i++) {
|
||||
if (_fds[i] == fd) {
|
||||
kill(_sigio_child_pids[i], SIGCONT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void native_async_read_add_handler(int fd, native_async_read_callback_t handler) {
|
||||
if (_next_index >= ASYNC_READ_NUMOF) {
|
||||
err(EXIT_FAILURE, "native_async_read_add_handler(): too many callbacks");
|
||||
}
|
||||
|
||||
_fds[_next_index] = fd;
|
||||
_native_async_read_callbacks[_next_index] = handler;
|
||||
|
||||
#ifdef __MACH__
|
||||
/* tuntap signalled IO is not working in OSX,
|
||||
* * check http://sourceforge.net/p/tuntaposx/bugs/17/ */
|
||||
_sigio_child(_next_index);
|
||||
#else
|
||||
/* configure fds to send signals on io */
|
||||
if (fcntl(fd, F_SETOWN, _native_pid) == -1) {
|
||||
err(EXIT_FAILURE, "native_async_read_add_handler(): fcntl(F_SETOWN)");
|
||||
}
|
||||
/* set file access mode to non-blocking */
|
||||
if (fcntl(fd, F_SETFL, O_NONBLOCK | O_ASYNC) == -1) {
|
||||
err(EXIT_FAILURE, "native_async_read_add_handler(): fcntl(F_SETFL)");
|
||||
}
|
||||
#endif /* not OSX */
|
||||
|
||||
_next_index++;
|
||||
}
|
||||
|
||||
#ifdef __MACH__
|
||||
static void _sigio_child(int index)
|
||||
{
|
||||
int fd = _fds[index];
|
||||
pid_t parent = _native_pid;
|
||||
pid_t child;
|
||||
if ((child = real_fork()) == -1) {
|
||||
err(EXIT_FAILURE, "sigio_child: fork");
|
||||
}
|
||||
if (child > 0) {
|
||||
_sigio_child_pids[index] = child;
|
||||
|
||||
/* return in parent process */
|
||||
return;
|
||||
}
|
||||
|
||||
sigset_t sigmask;
|
||||
|
||||
sigemptyset(&sigmask);
|
||||
sigaddset(&sigmask, SIGCONT);
|
||||
sigprocmask(SIG_BLOCK, &sigmask, NULL);
|
||||
|
||||
/* watch tap interface and signal parent process if data is
|
||||
* available */
|
||||
fd_set rfds;
|
||||
while (1) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
if (real_select(fd + 1, &rfds, NULL, NULL, NULL) == 1) {
|
||||
kill(parent, SIGIO);
|
||||
}
|
||||
else {
|
||||
kill(parent, SIGKILL);
|
||||
err(EXIT_FAILURE, "osx_sigio_child: select");
|
||||
}
|
||||
|
||||
/* If SIGCONT is sent before calling pause(), the process stops
|
||||
* forever, so using sigwait instead. */
|
||||
|
||||
int sig;
|
||||
|
||||
sigemptyset(&sigmask);
|
||||
sigaddset(&sigmask, SIGCONT);
|
||||
sigwait(&sigmask, &sig);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup native_cpu
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Multiple asynchronus read on file descriptors
|
||||
*
|
||||
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*/
|
||||
#ifndef ASYNC_READ_H
|
||||
#define ASYNC_READ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum number of file descriptors
|
||||
*/
|
||||
#ifndef ASYNC_READ_NUMOF
|
||||
#define ASYNC_READ_NUMOF 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief asynchronus read callback type
|
||||
*/
|
||||
typedef void (*native_async_read_callback_t)(int fd);
|
||||
|
||||
/**
|
||||
* @brief initialize asynchronus read system
|
||||
*
|
||||
* This registers SIGIO signal handler.
|
||||
*/
|
||||
void native_async_read_setup(void);
|
||||
|
||||
/**
|
||||
* @brief shutdown asynchronus read system
|
||||
*
|
||||
* This deregisters SIGIO signal handler.
|
||||
*/
|
||||
void native_async_read_cleanup(void);
|
||||
|
||||
/**
|
||||
* @brief resume monitoring of file descriptors
|
||||
*
|
||||
* Call this function after reading file descriptors.
|
||||
*
|
||||
* @param[in] fd The file descriptor to monitor
|
||||
*/
|
||||
void native_async_read_continue(int fd);
|
||||
|
||||
/**
|
||||
* @brief start monitoring of file descriptor
|
||||
*
|
||||
* @param[in] fd The file descriptor to monitor
|
||||
* @param[in] handler The callback function to be called when the file
|
||||
* descriptor is ready to read.
|
||||
*/
|
||||
void native_async_read_add_handler(int fd, native_async_read_callback_t handler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/** @} */
|
|
@ -63,6 +63,15 @@
|
|||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief UART configuration
|
||||
* @{
|
||||
*/
|
||||
#ifndef UART_NUMOF
|
||||
#define UART_NUMOF (1U)
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup native_cpu
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief UART implementation based on /dev/tty devices on host
|
||||
*
|
||||
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*/
|
||||
|
||||
#ifndef TTY_UART_H
|
||||
#define TTY_UART_H
|
||||
|
||||
#include "periph/uart.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief register /dev/tty device to be used for UART
|
||||
*
|
||||
* @param[in] uart UART id
|
||||
* @param[in] name path name for /dev/tty device
|
||||
*/
|
||||
void tty_uart_setup(uart_t uart, const char *name);
|
||||
|
||||
/**
|
||||
* @brief closes files opened
|
||||
*/
|
||||
void uart_cleanup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/** @} */
|
|
@ -48,6 +48,8 @@
|
|||
|
||||
#include "native_internal.h"
|
||||
|
||||
#include "async_read.h"
|
||||
|
||||
#include "net/eui64.h"
|
||||
#include "net/netdev2.h"
|
||||
#include "net/netdev2/eth.h"
|
||||
|
@ -63,11 +65,6 @@
|
|||
/* support one tap interface for now */
|
||||
netdev2_tap_t netdev2_tap;
|
||||
|
||||
#ifdef __MACH__
|
||||
pid_t _sigio_child_pid;
|
||||
static void _sigio_child(netdev2_tap_t *dev);
|
||||
#endif
|
||||
|
||||
/* netdev2 interface */
|
||||
static int _init(netdev2_t *netdev);
|
||||
static int _send(netdev2_t *netdev, const struct iovec *vector, int n);
|
||||
|
@ -210,9 +207,9 @@ static int _recv(netdev2_t *netdev2, char *buf, int len, void *info)
|
|||
"That's not me => Dropped\n",
|
||||
hdr->dst[0], hdr->dst[1], hdr->dst[2],
|
||||
hdr->dst[3], hdr->dst[4], hdr->dst[5]);
|
||||
#ifdef __MACH__
|
||||
kill(_sigio_child_pid, SIGCONT);
|
||||
#endif
|
||||
|
||||
native_async_read_continue(dev->tap_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* work around lost signals */
|
||||
|
@ -233,9 +230,7 @@ static int _recv(netdev2_t *netdev2, char *buf, int len, void *info)
|
|||
DEBUG("netdev2_tap: sigpend++\n");
|
||||
}
|
||||
else {
|
||||
#ifdef __MACH__
|
||||
kill(_sigio_child_pid, SIGCONT);
|
||||
#endif
|
||||
native_async_read_continue(dev->tap_fd);
|
||||
}
|
||||
|
||||
_native_in_syscall--;
|
||||
|
@ -284,7 +279,9 @@ void netdev2_tap_setup(netdev2_tap_t *dev, const netdev2_tap_params_t *params) {
|
|||
strncpy(dev->tap_name, *(params->tap_name), IFNAMSIZ);
|
||||
}
|
||||
|
||||
static void _tap_isr(void) {
|
||||
static void _tap_isr(int fd) {
|
||||
(void) fd;
|
||||
|
||||
netdev2_t *netdev = (netdev2_t *)&netdev2_tap;
|
||||
|
||||
if (netdev->event_callback) {
|
||||
|
@ -365,22 +362,11 @@ static int _init(netdev2_t *netdev)
|
|||
DEBUG("gnrc_tapnet_init(): dev->addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
dev->addr[0], dev->addr[1], dev->addr[2],
|
||||
dev->addr[3], dev->addr[4], dev->addr[5]);
|
||||
|
||||
/* configure signal handler for fds */
|
||||
register_interrupt(SIGIO, _tap_isr);
|
||||
#ifdef __MACH__
|
||||
/* tuntap signalled IO is not working in OSX,
|
||||
* * check http://sourceforge.net/p/tuntaposx/bugs/17/ */
|
||||
_sigio_child(dev);
|
||||
#else
|
||||
/* configure fds to send signals on io */
|
||||
if (fcntl(dev->tap_fd, F_SETOWN, _native_pid) == -1) {
|
||||
err(EXIT_FAILURE, "gnrc_tapnet_init(): fcntl(F_SETOWN)");
|
||||
}
|
||||
/* set file access mode to non-blocking */
|
||||
if (fcntl(dev->tap_fd, F_SETFL, O_NONBLOCK | O_ASYNC) == -1) {
|
||||
err(EXIT_FAILURE, "gnrc_tabnet_init(): fcntl(F_SETFL)");
|
||||
}
|
||||
#endif /* not OSX */
|
||||
native_async_read_setup();
|
||||
native_async_read_add_handler(dev->tap_fd, _tap_isr);
|
||||
|
||||
#ifdef MODULE_NETSTATS_L2
|
||||
memset(&netdev->stats, 0, sizeof(netstats_t));
|
||||
#endif
|
||||
|
@ -396,40 +382,8 @@ void netdev2_tap_cleanup(netdev2_tap_t *dev)
|
|||
}
|
||||
|
||||
/* cleanup signal handling */
|
||||
unregister_interrupt(SIGIO);
|
||||
#ifdef __MACH__
|
||||
kill(_sigio_child_pid, SIGKILL);
|
||||
#endif
|
||||
native_async_read_cleanup();
|
||||
|
||||
/* close the tap device */
|
||||
real_close(dev->tap_fd);
|
||||
}
|
||||
|
||||
#ifdef __MACH__
|
||||
static void _sigio_child(netdev2_tap_t *dev)
|
||||
{
|
||||
pid_t parent = _native_pid;
|
||||
if ((_sigio_child_pid = real_fork()) == -1) {
|
||||
err(EXIT_FAILURE, "sigio_child: fork");
|
||||
}
|
||||
if (_sigio_child_pid > 0) {
|
||||
/* return in parent process */
|
||||
return;
|
||||
}
|
||||
/* watch tap interface and signal parent process if data is
|
||||
* available */
|
||||
fd_set rfds;
|
||||
while (1) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(dev->tap_fd, &rfds);
|
||||
if (real_select(dev->tap_fd + 1, &rfds, NULL, NULL, NULL) == 1) {
|
||||
kill(parent, SIGIO);
|
||||
}
|
||||
else {
|
||||
kill(parent, SIGKILL);
|
||||
err(EXIT_FAILURE, "osx_sigio_child: select");
|
||||
}
|
||||
pause();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup native_cpu
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief empty GPIO implementation
|
||||
*
|
||||
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*/
|
||||
|
||||
#include "periph/gpio.h"
|
||||
|
||||
int gpio_init(gpio_t pin, gpio_mode_t mode) {
|
||||
(void) pin;
|
||||
(void) mode;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
||||
gpio_cb_t cb, void *arg){
|
||||
(void) pin;
|
||||
(void) mode;
|
||||
(void) flank;
|
||||
(void) cb;
|
||||
(void) arg;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void gpio_irq_enable(gpio_t pin) {
|
||||
(void) pin;
|
||||
}
|
||||
|
||||
void gpio_irq_disable(gpio_t pin) {
|
||||
(void) pin;
|
||||
}
|
||||
|
||||
int gpio_read(gpio_t pin) {
|
||||
(void) pin;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_set(gpio_t pin) {
|
||||
(void) pin;
|
||||
}
|
||||
|
||||
void gpio_clear(gpio_t pin) {
|
||||
(void) pin;
|
||||
}
|
||||
|
||||
void gpio_toggle(gpio_t pin) {
|
||||
(void) pin;
|
||||
}
|
||||
|
||||
void gpio_write(gpio_t pin, int value) {
|
||||
(void) pin;
|
||||
(void) value;
|
||||
}
|
||||
/** @} */
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup native_cpu
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief UART implementation based on /dev/tty devices on host
|
||||
*
|
||||
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "periph/uart.h"
|
||||
#include "native_internal.h"
|
||||
#include "async_read.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief callback function and its argument
|
||||
*/
|
||||
static uart_isr_ctx_t uart_config[UART_NUMOF];
|
||||
|
||||
/**
|
||||
* @brief filenames of /dev/tty
|
||||
*/
|
||||
static char *tty_device_filenames[UART_NUMOF];
|
||||
|
||||
/**
|
||||
* @brief file descriptors of /dev/tty
|
||||
*/
|
||||
static int tty_fds[UART_NUMOF];
|
||||
|
||||
void tty_uart_setup(uart_t uart, const char *filename)
|
||||
{
|
||||
tty_device_filenames[uart] = strndup(filename, PATH_MAX - 1);
|
||||
}
|
||||
|
||||
static void io_signal_handler(int fd)
|
||||
{
|
||||
uart_t uart;
|
||||
|
||||
for (uart = 0; uart < UART_NUMOF; uart++) {
|
||||
if (tty_fds[uart] == fd) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int is_first = 1;
|
||||
|
||||
while (1) {
|
||||
char c;
|
||||
int status = real_read(fd, &c, 1);
|
||||
|
||||
if (status == 1) {
|
||||
if (is_first) {
|
||||
is_first = 0;
|
||||
DEBUG("read char from serial port");
|
||||
}
|
||||
|
||||
DEBUG(" %02x", (unsigned char) c);
|
||||
|
||||
uart_config[uart].rx_cb(uart_config[uart].arg, c);
|
||||
} else {
|
||||
if (status == -1 && errno != EAGAIN) {
|
||||
DEBUG("error: cannot read from serial port\n");
|
||||
|
||||
uart_config[uart].rx_cb = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_first) {
|
||||
DEBUG("\n");
|
||||
}
|
||||
|
||||
native_async_read_continue(fd);
|
||||
}
|
||||
|
||||
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
{
|
||||
if (uart >= UART_NUMOF) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct termios termios;
|
||||
|
||||
memset(&termios, 0, sizeof(termios));
|
||||
|
||||
termios.c_iflag = 0;
|
||||
termios.c_oflag = 0;
|
||||
termios.c_cflag = CS8 | CREAD | CLOCAL;
|
||||
termios.c_lflag = 0;
|
||||
|
||||
speed_t speed;
|
||||
|
||||
switch (baudrate) {
|
||||
case 0: speed = B0; break;
|
||||
case 50: speed = B50; break;
|
||||
case 75: speed = B75; break;
|
||||
case 110: speed = B110; break;
|
||||
case 134: speed = B134; break;
|
||||
case 150: speed = B150; break;
|
||||
case 200: speed = B200; break;
|
||||
case 300: speed = B300; break;
|
||||
case 600: speed = B600; break;
|
||||
case 1200: speed = B1200; break;
|
||||
case 1800: speed = B1800; break;
|
||||
case 2400: speed = B2400; break;
|
||||
case 4800: speed = B4800; break;
|
||||
case 9600: speed = B9600; break;
|
||||
case 19200: speed = B19200; break;
|
||||
case 38400: speed = B38400; break;
|
||||
case 57600: speed = B57600; break;
|
||||
case 115200: speed = B115200; break;
|
||||
case 230400: speed = B230400 ; break;
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
cfsetospeed(&termios, speed);
|
||||
cfsetispeed(&termios, speed);
|
||||
|
||||
tty_fds[uart] = real_open(tty_device_filenames[uart], O_RDWR | O_NONBLOCK);
|
||||
|
||||
if (tty_fds[uart] < 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
tcsetattr(tty_fds[uart], TCSANOW, &termios);
|
||||
|
||||
uart_config[uart].rx_cb = rx_cb;
|
||||
uart_config[uart].arg = arg;
|
||||
|
||||
native_async_read_setup();
|
||||
native_async_read_add_handler(tty_fds[uart], io_signal_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
{
|
||||
DEBUG("writing to serial port ");
|
||||
|
||||
#if ENABLE_DEBUG
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
DEBUG("%02x ", (unsigned char) data[i]);
|
||||
}
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
DEBUG("%c", (char) data[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG("\n");
|
||||
|
||||
_native_write(tty_fds[uart], data, len);
|
||||
}
|
||||
|
||||
void uart_cleanup(void) {
|
||||
native_async_read_cleanup();
|
||||
|
||||
for (uart_t uart = 0; uart < UART_NUMOF; uart++) {
|
||||
if (uart_config[uart].rx_cb != NULL) {
|
||||
real_close(tty_fds[uart]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "native_internal.h"
|
||||
#include "netdev2_tap.h"
|
||||
#include "tty_uart.h"
|
||||
|
||||
void reboot(void)
|
||||
{
|
||||
|
@ -29,6 +30,8 @@ void reboot(void)
|
|||
netdev2_tap_cleanup(&netdev2_tap);
|
||||
#endif
|
||||
|
||||
uart_cleanup();
|
||||
|
||||
if (real_execve(_native_argv[0], _native_argv, NULL) == -1) {
|
||||
err(EXIT_FAILURE, "reboot: execve");
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "board_internal.h"
|
||||
#include "native_internal.h"
|
||||
#include "tty_uart.h"
|
||||
|
||||
int _native_null_in_pipe[2];
|
||||
int _native_null_out_file;
|
||||
|
@ -200,7 +201,7 @@ void usage_exit(void)
|
|||
real_printf(" <tap interface>");
|
||||
#endif
|
||||
|
||||
real_printf(" [-i <id>] [-d] [-e|-E] [-o]\n");
|
||||
real_printf(" [-i <id>] [-d] [-e|-E] [-o] [-c <tty device>]\n");
|
||||
|
||||
real_printf(" help: %s -h\n", _progname);
|
||||
|
||||
|
@ -216,7 +217,8 @@ void usage_exit(void)
|
|||
-E do not redirect stderr (i.e. leave sterr unchanged despite\n\
|
||||
daemon/socket io)\n\
|
||||
-o redirect stdout to file (/tmp/riot.stdout.PID) when not attached\n\
|
||||
to socket\n");
|
||||
to socket\n\
|
||||
-c specify TTY device for UART\n");
|
||||
|
||||
real_printf("\n\
|
||||
The order of command line arguments matters.\n");
|
||||
|
@ -239,6 +241,7 @@ __attribute__((constructor)) static void startup(int argc, char **argv)
|
|||
char *stderrtype = "stdio";
|
||||
char *stdouttype = "stdio";
|
||||
char *stdiotype = "stdio";
|
||||
int uart = 0;
|
||||
|
||||
#if defined(MODULE_NETDEV2_TAP)
|
||||
if (
|
||||
|
@ -297,6 +300,16 @@ __attribute__((constructor)) static void startup(int argc, char **argv)
|
|||
else if (strcmp("-o", arg) == 0) {
|
||||
stdouttype = "file";
|
||||
}
|
||||
else if (strcmp("-c", arg) == 0) {
|
||||
if (argp + 1 < argc) {
|
||||
argp++;
|
||||
}
|
||||
else {
|
||||
usage_exit();
|
||||
}
|
||||
|
||||
tty_uart_setup(uart++, argv[argp]);
|
||||
}
|
||||
else {
|
||||
usage_exit();
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ static int parse_dev(char *arg)
|
|||
printf("Error: The selected UART_DEV(%i) is used for the shell!\n", dev);
|
||||
return -2;
|
||||
}
|
||||
if (dev < 0 || dev >= UART_NUMOF) {
|
||||
if (dev < 0 || (uart_t) dev >= UART_NUMOF) {
|
||||
printf("Error: Invalid UART_DEV device specified (%i).\n", dev);
|
||||
return -1;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ static int parse_dev(char *arg)
|
|||
|
||||
static void rx_cb(void *arg, uint8_t data)
|
||||
{
|
||||
int dev = (int)arg;
|
||||
uart_t dev = (uart_t)arg;
|
||||
|
||||
ringbuffer_add_one(&(ctx[dev].rx_buf), data);
|
||||
if (data == 0) {
|
||||
|
@ -84,7 +84,7 @@ static void *printer(void *arg)
|
|||
|
||||
while (1) {
|
||||
msg_receive(&msg);
|
||||
int dev = (int)msg.content.value;
|
||||
uart_t dev = (uart_t)msg.content.value;
|
||||
char c;
|
||||
|
||||
printf("UART_DEV(%i) RX: ", dev);
|
||||
|
@ -179,7 +179,7 @@ int main(void)
|
|||
printf("UART used for STDIO (the shell): UART_DEV(%i)\n\n", UART_STDIO_DEV);
|
||||
|
||||
/* initialize ringbuffers */
|
||||
for (int i = 0; i < UART_NUMOF; i++) {
|
||||
for (uart_t i = 0; i < UART_NUMOF; i++) {
|
||||
ringbuffer_init(&(ctx[i].rx_buf), ctx[i].rx_mem, UART_BUFSIZE);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue