From 49ea7a3d6137536123c71f7abead7c1340859541 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Thu, 4 Jun 2015 11:50:03 +0200 Subject: [PATCH] sys: factor stdio uart functions out of newlib's syscalls --- Makefile.dep | 4 ++ sys/include/uart_stdio.h | 66 +++++++++++++++++++++++++++ sys/newlib/syscalls.c | 63 +++----------------------- sys/uart_stdio/Makefile | 1 + sys/uart_stdio/uart_stdio.c | 89 +++++++++++++++++++++++++++++++++++++ 5 files changed, 165 insertions(+), 58 deletions(-) create mode 100644 sys/include/uart_stdio.h create mode 100644 sys/uart_stdio/Makefile create mode 100644 sys/uart_stdio/uart_stdio.c diff --git a/Makefile.dep b/Makefile.dep index 49d2a0164448..a1ce715435c4 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -325,3 +325,7 @@ ifneq (,$(filter cpp11-compat,$(USEMODULE))) USEMODULE += timex FEATURES_REQUIRED += cpp endif + +ifneq (,$(filter newlib,$(USEMODULE))) + USEMODULE += uart_stdio +endif diff --git a/sys/include/uart_stdio.h b/sys/include/uart_stdio.h new file mode 100644 index 000000000000..f8d48bd52ada --- /dev/null +++ b/sys/include/uart_stdio.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * 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. + */ + +/** + * @defgroup sys_uart_stdio UART stdio + * @ingroup sys + * + * @brief stdio init/read/write functions for UARTs + * + * @{ + * @file + * + * @author Kaspar Schleiser + */ +#ifndef UART_STDIO_H +#define UART_STDIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief initialize the module + */ +void uart_stdio_init(void); + +/** + * @brief read @p len bytes from stdio uart into @p buffer + * + * @param[out] buffer buffer to read into + * @param[in] len nr of bytes to read + * + * @return nr of bytes read + * @return <0 on error + */ +int uart_stdio_read(char* buffer, int len); + +/** + * @brief write @p len bytes from @p buffer into uart + * + * @param[in] buffer buffer to read from + * @param[in] len nr of bytes to write + * + * @return nr of bytes written + * @return <0 on error + */ +int uart_stdio_write(const char* buffer, int len); + +/** + * @brief internal callback for periph/uart drivers + * + * @param[in] arg (unused) + * @param[in] data character that has been received + */ +void uart_stdio_rx_cb(void *arg, char data); + +#ifdef __cplusplus +} +#endif +/** @} */ +#endif /* UART_STDIO_H */ diff --git a/sys/newlib/syscalls.c b/sys/newlib/syscalls.c index da0b3fd5056f..0f6a0d36f8d5 100644 --- a/sys/newlib/syscalls.c +++ b/sys/newlib/syscalls.c @@ -34,14 +34,9 @@ #include "board.h" #include "thread.h" #include "kernel.h" -#include "mutex.h" -#include "ringbuffer.h" #include "irq.h" -#include "periph/uart.h" -#ifdef MODULE_UART0 -#include "board_uart0.h" -#endif +#include "uart_stdio.h" /** * @brief manage the heap @@ -50,42 +45,12 @@ extern char _sheap; /* start of the heap */ extern char _eheap; /* end of the heap */ caddr_t heap_top = (caddr_t)&_sheap + 4; -#ifndef MODULE_UART0 -/** - * @brief use mutex for waiting on incoming UART chars - */ -static mutex_t uart_rx_mutex = MUTEX_INIT; -static char rx_buf_mem[STDIO_RX_BUFSIZE]; -static ringbuffer_t rx_buf; -#endif - -/** - * @brief Receive a new character from the UART and put it into the receive buffer - */ -void rx_cb(void *arg, char data) -{ - (void)arg; -#ifndef MODULE_UART0 - ringbuffer_add_one(&rx_buf, data); - mutex_unlock(&uart_rx_mutex); -#else - if (uart0_handler_pid) { - uart0_handle_incoming(data); - uart0_notify_thread(); - } -#endif -} - /** * @brief Initialize NewLib, called by __libc_init_array() from the startup script */ void _init(void) { -#ifndef MODULE_UART0 - mutex_lock(&uart_rx_mutex); - ringbuffer_init(&rx_buf, rx_buf_mem, STDIO_RX_BUFSIZE); -#endif - uart_init(STDIO, STDIO_BAUDRATE, rx_cb, 0, 0); + uart_stdio_init(); } /** @@ -107,7 +72,7 @@ void _fini(void) void _exit(int n) { printf("#! exit %i: resetting\n", n); - NVIC_SystemReset(); + reboot(n); while(1); } @@ -204,19 +169,7 @@ int _read_r(struct _reent *r, int fd, void *buffer, unsigned int count) { (void)r; (void)fd; -#ifndef MODULE_UART0 - int res; - mutex_lock(&uart_rx_mutex); - unsigned state = disableIRQ(); - count = count < rx_buf.avail ? count : rx_buf.avail; - res = ringbuffer_get(&rx_buf, (char*)buffer, count); - restoreIRQ(state); - return res; -#else - char *res = (char*)buffer; - res[0] = (char)uart0_readc(); - return 1; -#endif + return uart_stdio_read(buffer, count); } /** @@ -238,13 +191,7 @@ int _write_r(struct _reent *r, int fd, const void *data, unsigned int count) { (void) r; (void) fd; - unsigned int i = 0; - - while (i < count) { - uart_write_blocking(STDIO, ((char*)data)[i++]); - } - - return (int)i; + return uart_stdio_write(data, count); } /** diff --git a/sys/uart_stdio/Makefile b/sys/uart_stdio/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/sys/uart_stdio/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/uart_stdio/uart_stdio.c b/sys/uart_stdio/uart_stdio.c new file mode 100644 index 000000000000..9cb4c1712d82 --- /dev/null +++ b/sys/uart_stdio/uart_stdio.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013 INRIA + * 2015 Kaspar Schleiser + * + * 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 sys + * @{ + * + * @file + * @brief UART stdio implementation + * + * This file implements a UART callback and read/write functions. + * + * @author Oliver Hahm + * @author Ludwig Ortmann + * @author Kaspar Schleiser + * + * @} + */ + +#include + +#include "cpu_conf.h" +#include "ringbuffer.h" +#include "thread.h" +#include "mutex.h" +#include "irq.h" + +#include "periph/uart.h" + +#include "board.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" + +#ifndef STDIO_RX_BUFSIZE +#define STDIO_RX_BUFSIZE (64) +#endif + +/** + * @brief use mutex for waiting on incoming UART chars + */ +static mutex_t _rx_mutex = MUTEX_INIT; +static char _rx_buf_mem[STDIO_RX_BUFSIZE]; +static ringbuffer_t _rx_buf; + +/** + * @brief Receive a new character from the UART and put it into the receive buffer + */ +void uart_stdio_rx_cb(void *arg, char data) +{ + (void)arg; + ringbuffer_add_one(&_rx_buf, data); + mutex_unlock(&_rx_mutex); +} + +void uart_stdio_init(void) +{ + mutex_lock(&_rx_mutex); + ringbuffer_init(&_rx_buf, _rx_buf_mem, STDIO_RX_BUFSIZE); + uart_init(STDIO, STDIO_BAUDRATE, uart_stdio_rx_cb, 0, 0); +} + +int uart_stdio_read(char* buffer, int count) +{ + int res; + mutex_lock(&_rx_mutex); + unsigned state = disableIRQ(); + count = (count < _rx_buf.avail) ? count : _rx_buf.avail; + res = ringbuffer_get(&_rx_buf, (char*)buffer, count); + restoreIRQ(state); + return res; +} + +int uart_stdio_write(const char* buffer, int len) +{ + unsigned int i = len; + + while (i--) { + uart_write_blocking(STDIO, *buffer++); + } + + return len; +}