slipdev_stdio: provide stdio multiplexing over SLIP

This commit is contained in:
Martine Lenders 2018-11-25 18:21:36 +01:00 committed by Martine Lenders
parent 8e827055f0
commit ff425576a0
No known key found for this signature in database
GPG Key ID: CCD317364F63286F
8 changed files with 188 additions and 4 deletions

View File

@ -436,7 +436,7 @@ ifneq (,$(filter newlib,$(USEMODULE)))
ifeq (,$(filter newlib_syscalls_%,$(USEMODULE))) ifeq (,$(filter newlib_syscalls_%,$(USEMODULE)))
USEMODULE += newlib_syscalls_default USEMODULE += newlib_syscalls_default
endif endif
ifeq (,$(filter stdio_cdc_acm stdio_native stdio_null stdio_rtt,$(USEMODULE))) ifeq (,$(filter stdio_cdc_acm stdio_native stdio_null stdio_rtt slipdev_stdio,$(USEMODULE)))
USEMODULE += stdio_uart USEMODULE += stdio_uart
endif endif
endif endif
@ -483,7 +483,7 @@ ifneq (,$(filter stdio_uart,$(USEMODULE)))
FEATURES_REQUIRED += periph_uart FEATURES_REQUIRED += periph_uart
endif endif
ifneq (,$(filter stdio_cdc_acm stdio_null stdio_uart,$(USEMODULE))) ifneq (,$(filter stdio_cdc_acm stdio_null stdio_uart slipdev_stdio,$(USEMODULE)))
# stdio_rtt cannot be used when another STDIO is loaded # stdio_rtt cannot be used when another STDIO is loaded
DISABLE_MODULE += stdio_rtt DISABLE_MODULE += stdio_rtt
endif endif

View File

@ -601,6 +601,12 @@ ifneq (,$(filter slipdev,$(USEMODULE)))
FEATURES_REQUIRED += periph_uart FEATURES_REQUIRED += periph_uart
endif endif
ifneq (,$(filter slipdev_stdio,$(USEMODULE)))
USEMODULE += isrpipe
USEMODULE += slipdev
FEATURES_REQUIRED += periph_uart
endif
ifneq (,$(filter soft_spi,$(USEMODULE))) ifneq (,$(filter soft_spi,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio FEATURES_REQUIRED += periph_gpio
USEMODULE += xtimer USEMODULE += xtimer

View File

@ -44,6 +44,27 @@ extern "C" {
#define SLIPDEV_BUFSIZE (2048U) #define SLIPDEV_BUFSIZE (2048U)
#endif #endif
/**
* @name Device state definitions
* @anchor drivers_slipdev_states
* @{
*/
enum {
/**
* @brief Device is in no mode (currently did not receiving any data frame)
*/
SLIPDEV_STATE_NONE = 0,
/**
* @brief Device writes handles data as network device
*/
SLIPDEV_STATE_NET,
/**
* @brief Device writes received data to stdin
*/
SLIPDEV_STATE_STDIN,
};
/** @} */
/** /**
* @brief Configuration parameters for a slipdev * @brief Configuration parameters for a slipdev
*/ */
@ -62,6 +83,11 @@ typedef struct {
slipdev_params_t config; /**< configuration parameters */ slipdev_params_t config; /**< configuration parameters */
tsrb_t inbuf; /**< RX buffer */ tsrb_t inbuf; /**< RX buffer */
uint8_t rxmem[SLIPDEV_BUFSIZE]; /**< memory used by RX buffer */ uint8_t rxmem[SLIPDEV_BUFSIZE]; /**< memory used by RX buffer */
/**
* @brief Device state
* @see [Device state definitions](@ref drivers_slipdev_states)
*/
uint8_t state;
} slipdev_t; } slipdev_t;
/** /**

View File

@ -1 +1,7 @@
# exclude submodule sources from *.c wildcard source selection
SRC := $(filter-out stdio.c,$(wildcard *.c))
# enable submodules
SUBMODULES := 1
include $(RIOTBASE)/Makefile.base include $(RIOTBASE)/Makefile.base

View File

@ -22,7 +22,9 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "isrpipe.h"
#include "periph/uart.h" #include "periph/uart.h"
#include "mutex.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -37,8 +39,26 @@ extern "C" {
#define SLIPDEV_ESC (0xdbU) #define SLIPDEV_ESC (0xdbU)
#define SLIPDEV_END_ESC (0xdcU) #define SLIPDEV_END_ESC (0xdcU)
#define SLIPDEV_ESC_ESC (0xddU) #define SLIPDEV_ESC_ESC (0xddU)
/**
* @brief Marker byte for beginning of stdio
* @see taken from diagnostic transfer from
* [SLIPMUX](https://tools.ietf.org/html/draft-bormann-t2trg-slipmux-02#section-4)
*/
#define SLIPDEV_STDIO_START (0x0aU)
/** @} */ /** @} */
/**
* @brief ISR pipe to hand read bytes to stdin
*/
extern isrpipe_t slipdev_stdio_isrpipe;
/**
* @brief Mutex to synchronize write operations to the UART between stdio
* sub-module and normal SLIP.
*/
extern mutex_t slipdev_mutex;
/** /**
* @brief Writes one byte to UART * @brief Writes one byte to UART
* *

View File

@ -21,16 +21,54 @@
#include "slipdev.h" #include "slipdev.h"
#include "slipdev_internal.h" #include "slipdev_internal.h"
/* XXX: BE CAREFUL ABOUT USING OUTPUT WITH MODULE_SLIPDEV_STDIO IN SENDING
* FUNCTIONALITY! MIGHT CAUSE DEADLOCK!!!1!! */
#define ENABLE_DEBUG (0) #define ENABLE_DEBUG (0)
#include "debug.h" #include "debug.h"
#include "isrpipe.h"
#include "mutex.h"
#include "stdio_uart.h"
static inline void slipdev_lock(void)
{
if (IS_USED(MODULE_SLIPDEV_STDIO)) {
mutex_lock(&slipdev_mutex);
}
}
static inline void slipdev_unlock(void)
{
if (IS_USED(MODULE_SLIPDEV_STDIO)) {
mutex_unlock(&slipdev_mutex);
}
}
static void _slip_rx_cb(void *arg, uint8_t byte) static void _slip_rx_cb(void *arg, uint8_t byte)
{ {
slipdev_t *dev = arg; slipdev_t *dev = arg;
if (IS_USED(MODULE_SLIPDEV_STDIO)) {
if (dev->state == SLIPDEV_STATE_STDIN) {
isrpipe_write_one(&slipdev_stdio_isrpipe, byte);
goto check_end;
}
else if ((byte == SLIPDEV_STDIO_START) &&
(dev->config.uart == STDIO_UART_DEV) &&
(dev->state == SLIPDEV_STATE_NONE)) {
dev->state = SLIPDEV_STATE_STDIN;
return;
}
}
dev->state = SLIPDEV_STATE_NET;
tsrb_add_one(&dev->inbuf, byte); tsrb_add_one(&dev->inbuf, byte);
if ((byte == SLIPDEV_END) && (dev->netdev.event_callback != NULL)) { check_end:
dev->netdev.event_callback((netdev_t *)dev, NETDEV_EVENT_ISR); if (byte == SLIPDEV_END) {
if ((dev->state == SLIPDEV_STATE_NET) &&
(dev->netdev.event_callback != NULL)) {
dev->netdev.event_callback((netdev_t *)dev, NETDEV_EVENT_ISR);
}
dev->state = SLIPDEV_STATE_NONE;
} }
} }
@ -112,12 +150,14 @@ static int _send(netdev_t *netdev, const iolist_t *iolist)
int bytes = 0; int bytes = 0;
DEBUG("slipdev: sending iolist\n"); DEBUG("slipdev: sending iolist\n");
slipdev_lock();
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
uint8_t *data = iol->iol_base; uint8_t *data = iol->iol_base;
slipdev_write_bytes(dev->config.uart, data, iol->iol_len); slipdev_write_bytes(dev->config.uart, data, iol->iol_len);
bytes += iol->iol_len; bytes += iol->iol_len;
} }
slipdev_write_byte(dev->config.uart, SLIPDEV_END); slipdev_write_byte(dev->config.uart, SLIPDEV_END);
slipdev_unlock();
return bytes; return bytes;
} }
@ -209,6 +249,7 @@ void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params)
{ {
/* set device descriptor fields */ /* set device descriptor fields */
dev->config = *params; dev->config = *params;
dev->state = 0;
dev->netdev.driver = &slip_driver; dev->netdev.driver = &slip_driver;
} }

84
drivers/slipdev/stdio.c Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2018 Freie Universität Berlin
*
* 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.
*/
/**
* @{
*
* @file
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#include "board.h"
#include "isrpipe.h"
#include "periph/uart.h"
#include "slipdev.h"
#include "slipdev_internal.h"
#include "slipdev_params.h"
#include "stdio_base.h"
#include "stdio_uart.h"
static uint8_t _rx_buf_mem[STDIO_UART_RX_BUFSIZE];
isrpipe_t slipdev_stdio_isrpipe = ISRPIPE_INIT(_rx_buf_mem);
mutex_t slipdev_mutex = MUTEX_INIT;
static void _isrpipe_write(void *arg, uint8_t data)
{
isrpipe_write_one(arg, (char)data);
}
void stdio_init(void)
{
/* intentionally overwritten in netdev init so we have stdio before
* the network device is initialized is initialized */
uart_init(slipdev_params[0].uart, slipdev_params[0].baudrate,
(uart_rx_cb_t)_isrpipe_write, &slipdev_stdio_isrpipe);
}
ssize_t stdio_read(void *buffer, size_t len)
{
uint8_t *ptr = buffer;
bool escaped = false;
uint8_t byte;
do {
int read = isrpipe_read(&slipdev_stdio_isrpipe, &byte, 1);
int tmp;
if (read == 0) {
continue;
}
else if (len == 0) {
return -ENOBUFS;
}
tmp = slipdev_unstuff_readbyte(ptr, byte, &escaped);
ptr += tmp;
if ((unsigned)(ptr - (uint8_t *)buffer) > len) {
while (byte != SLIPDEV_END) {
/* clear out unreceived packet */
isrpipe_read(&slipdev_stdio_isrpipe, &byte, 1);
}
return -ENOBUFS;
}
} while (byte != SLIPDEV_END);
return ptr - (uint8_t *)buffer;
}
ssize_t stdio_write(const void *buffer, size_t len)
{
mutex_lock(&slipdev_mutex);
slipdev_write_byte(slipdev_params[0].uart, SLIPDEV_STDIO_START);
slipdev_write_bytes(slipdev_params[0].uart, buffer, len);
slipdev_write_byte(slipdev_params[0].uart, SLIPDEV_END);
mutex_unlock(&slipdev_mutex);
return len;
}
/** @} */

View File

@ -82,6 +82,7 @@ PSEUDOMODULES += saul_nrf_temperature
PSEUDOMODULES += scanf_float PSEUDOMODULES += scanf_float
PSEUDOMODULES += sched_cb PSEUDOMODULES += sched_cb
PSEUDOMODULES += semtech_loramac_rx PSEUDOMODULES += semtech_loramac_rx
PSEUDOMODULES += slipdev_stdio
PSEUDOMODULES += sock PSEUDOMODULES += sock
PSEUDOMODULES += sock_async PSEUDOMODULES += sock_async
PSEUDOMODULES += sock_dtls PSEUDOMODULES += sock_dtls