1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/native/periph/uart.c

210 lines
4.8 KiB
C

/*
* 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 cpu_native
* @ingroup drivers_periph_uart
* @{
*
* @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, void *arg)
{
uart_t uart;
(void) arg;
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 UART_NODEV;
}
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;
case 460800 : speed = B460800; break;
case 500000 : speed = B500000; break;
case 576000 : speed = B576000; break;
case 921600 : speed = B921600; break;
case 1000000: speed = B1000000; break;
case 1152000: speed = B1152000; break;
case 1500000: speed = B1500000; break;
case 2000000: speed = B2000000; break;
case 2500000: speed = B2500000; break;
case 3000000: speed = B3000000; break;
case 3500000: speed = B3500000; break;
case 4000000: speed = B4000000; break;
default:
return UART_NOBAUD;
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 UART_INTERR;
}
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], NULL, io_signal_handler);
return UART_OK;
}
void uart_write(uart_t uart, const uint8_t *data, size_t len)
{
DEBUG("writing to serial port ");
if (IS_ACTIVE(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]);
}
}
DEBUG("\n");
if (tty_fds[uart] >= 0) {
_native_write(tty_fds[uart], data, len);
}
}
void uart_poweron(uart_t uart)
{
(void)uart;
/* not implemented (yet) */
}
void uart_poweroff(uart_t uart)
{
if (tty_fds[uart] >= 0) {
native_async_read_remove_handler(tty_fds[uart]);
real_close(tty_fds[uart]);
tty_fds[uart] = -1;
}
}