Skip to content

Commit

Permalink
native: add UART driver based on /dev/tty
Browse files Browse the repository at this point in the history
uart0 functionality is removed by RIOT-OS#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.
  • Loading branch information
Yonezawa-T2 committed Feb 2, 2016
1 parent e6f3349 commit 5b38c87
Show file tree
Hide file tree
Showing 11 changed files with 581 additions and 62 deletions.
2 changes: 2 additions & 0 deletions boards/native/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_random
FEATURES_PROVIDED += periph_rtc
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_uart
FEATURES_PROVIDED += periph_gpio

# Various other features (if any)
FEATURES_PROVIDED += config
Expand Down
160 changes: 160 additions & 0 deletions cpu/native/async_read.c
Original file line number Diff line number Diff line change
@@ -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 suspend(), the process stops
// forever, so using sigwait instead.

int sig;

sigemptyset(&sigmask);
sigaddset(&sigmask, SIGCONT);
sigwait(&sigmask, &sig);
}
}
#endif
/** @} */
74 changes: 74 additions & 0 deletions cpu/native/include/async_read.h
Original file line number Diff line number Diff line change
@@ -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
/** @} */
9 changes: 9 additions & 0 deletions cpu/native/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@

/** @} */

/**
* @brief UART configuration
* @{
*/
#ifndef UART_NUMOF
#define UART_NUMOF (1U)
#endif
/** @} */

#ifdef __cplusplus
}
#endif
Expand Down
46 changes: 46 additions & 0 deletions cpu/native/include/tty_uart.h
Original file line number Diff line number Diff line change
@@ -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
/** @} */
2 changes: 2 additions & 0 deletions cpu/native/native_cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
extern netdev2_tap_t netdev2_tap;
#endif

#include "tty_uart.h"

#include "native_internal.h"

#define ENABLE_DEBUG (0)
Expand Down
Loading

0 comments on commit 5b38c87

Please sign in to comment.