mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 06:23:53 +01:00
Merge pull request #21418 from Teufelchen1/feat/slipmux_c
drivers/slipmux: Add to RIOT
This commit is contained in:
commit
b2406da63f
@ -12,6 +12,10 @@
|
||||
* @defgroup drivers_slipdev_stdio STDIO via SLIP
|
||||
* @ingroup sys_stdio
|
||||
* @brief Standard input/output backend multiplexed via SLIP
|
||||
* @see [draft-bormann-t2trg-slipmux-03](https://datatracker.ietf.org/doc/html/draft-bormann-t2trg-slipmux-03)
|
||||
*
|
||||
* This extension is part of the [Slipmux draft](https://datatracker.ietf.org/doc/html/draft-bormann-t2trg-slipmux-03).
|
||||
* @warning This module is under development for optimizations and module names might change!
|
||||
*
|
||||
* This will multiplex STDIO via the Serial Line Internet Protocol.
|
||||
* The shell can be accessed via the `sliptty` tool.
|
||||
@ -23,11 +27,32 @@
|
||||
* @see drivers_slipdev
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_slipdev_configuration CoAP via SLIP
|
||||
* @ingroup drivers_slipdev
|
||||
* @brief Exchange CoAP requests and responses via SLIP
|
||||
* @see [draft-bormann-t2trg-slipmux-03](https://datatracker.ietf.org/doc/html/draft-bormann-t2trg-slipmux-03)
|
||||
*
|
||||
* This extension is part of the [Slipmux draft](https://datatracker.ietf.org/doc/html/draft-bormann-t2trg-slipmux-03).
|
||||
* @warning This module is under development for optimizations and module names might change!
|
||||
*
|
||||
* This will multiplex CoAP messages via the Serial Line Internet Protocol.
|
||||
* It spawns an extra thread as a CoAP server. The incoming requests are handled with `nanocoap`
|
||||
* according to any `NANOCOAP_RESOURCE`s present in the binary. See @ref net_nanocoap for more.
|
||||
*
|
||||
* To enable this implementation, select
|
||||
*
|
||||
* USEMODULE += slipdev_config
|
||||
*
|
||||
* @see drivers_slipdev
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_slipdev SLIP network device
|
||||
* @ingroup drivers_netdev
|
||||
* @brief SLIP network device over @ref drivers_periph_uart
|
||||
* @see [RFC 1055](https://github.com/RIOT-OS/RIOT/pull/6487)
|
||||
* @see [RFC 1055](https://datatracker.ietf.org/doc/html/rfc1055)
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
@ -42,6 +67,7 @@
|
||||
#include "net/netdev.h"
|
||||
#include "periph/uart.h"
|
||||
#include "chunked_ringbuffer.h"
|
||||
#include "sched.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -93,6 +119,14 @@ enum {
|
||||
* @brief Device writes received data to stdin, next byte is escaped
|
||||
*/
|
||||
SLIPDEV_STATE_STDIN_ESC,
|
||||
/**
|
||||
* @brief Device writes received data as CoAP message
|
||||
*/
|
||||
SLIPDEV_STATE_CONFIG,
|
||||
/**
|
||||
* @brief Device writes received data as CoAP message, next byte is escaped
|
||||
*/
|
||||
SLIPDEV_STATE_CONFIG_ESC,
|
||||
/**
|
||||
* @brief Device is in standby, will wake up when sending data
|
||||
*/
|
||||
@ -120,13 +154,19 @@ typedef struct {
|
||||
typedef struct {
|
||||
netdev_t netdev; /**< parent class */
|
||||
slipdev_params_t config; /**< configuration parameters */
|
||||
chunk_ringbuf_t rb; /**< Ringbuffer to store received frames. */
|
||||
chunk_ringbuf_t rb; /**< Ringbuffer to store received networking frames.*/
|
||||
/* Written to from interrupts (with irq_disable */
|
||||
/* to prevent any simultaneous writes), */
|
||||
/* consumed exclusively in the network stack's */
|
||||
/* loop at _isr. */
|
||||
|
||||
uint8_t rxmem[CONFIG_SLIPDEV_BUFSIZE]; /**< memory used by RX buffer */
|
||||
|
||||
#if IS_USED(MODULE_SLIPDEV_CONFIG)
|
||||
chunk_ringbuf_t rb_config; /**< Ringbuffer stores received configuration frames */
|
||||
uint8_t rxmem_config[CONFIG_SLIPDEV_BUFSIZE]; /**< memory used by RX buffer */
|
||||
kernel_pid_t coap_server_pid; /**< The PID of the CoAP server */
|
||||
#endif
|
||||
/**
|
||||
* @brief Device state
|
||||
* @see [Device state definitions](@ref drivers_slipdev_states)
|
||||
|
||||
@ -7,3 +7,10 @@ FEATURES_REQUIRED += periph_uart
|
||||
ifneq (,$(filter slipdev_stdio,$(USEMODULE)))
|
||||
USEMODULE += isrpipe
|
||||
endif
|
||||
ifneq (,$(filter slipdev_config,$(USEMODULE)))
|
||||
USEMODULE += checksum
|
||||
USEMODULE += sock_udp
|
||||
USEMODULE += gnrc_ipv6
|
||||
USEMODULE += nanocoap_sock
|
||||
USEMODULE += nanocoap_resources
|
||||
endif
|
||||
|
||||
@ -43,9 +43,16 @@ extern "C" {
|
||||
/**
|
||||
* @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)
|
||||
* [SLIPMUX](https://tools.ietf.org/html/draft-bormann-t2trg-slipmux-03#section-4)
|
||||
*/
|
||||
#define SLIPDEV_STDIO_START (0x0aU)
|
||||
|
||||
/**
|
||||
* @brief Marker byte for beginning of configuration/CoAP
|
||||
* @see taken from configuration from
|
||||
* [SLIPMUX](https://tools.ietf.org/html/draft-bormann-t2trg-slipmux-03#section-5)
|
||||
*/
|
||||
#define SLIPDEV_CONFIG_START (0xa9U)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
* @file
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
|
||||
* @author Bennet Hattesen <bennet.hattesen@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -31,20 +32,37 @@
|
||||
|
||||
#include "isrpipe.h"
|
||||
#include "mutex.h"
|
||||
#if IS_USED(MODULE_SLIPDEV_CONFIG)
|
||||
#include "checksum/crc16_ccitt.h"
|
||||
#include "net/nanocoap.h"
|
||||
#endif
|
||||
#include "stdio_uart.h"
|
||||
|
||||
#if (IS_USED(MODULE_SLIPDEV_STDIO) || IS_USED(MODULE_SLIPDEV_CONFIG))
|
||||
/* For synchronization with stdio/config threads */
|
||||
mutex_t slipdev_mutex = MUTEX_INIT;
|
||||
#endif
|
||||
|
||||
#if IS_USED(MODULE_SLIPDEV_CONFIG)
|
||||
/* The special init is the result of normal fcs init combined with slipmux config start (0xa9) */
|
||||
#define SPECIAL_INIT_FCS (0x374cU)
|
||||
#define COAP_STACKSIZE (1024)
|
||||
|
||||
static char coap_stack[COAP_STACKSIZE];
|
||||
#endif /* IS_USED(MODULE_SLIPDEV_CONFIG) */
|
||||
|
||||
static int _check_state(slipdev_t *dev);
|
||||
|
||||
static inline void slipdev_lock(void)
|
||||
{
|
||||
if (IS_USED(MODULE_SLIPDEV_STDIO)) {
|
||||
if (IS_USED(MODULE_SLIPDEV_STDIO) || IS_USED(MODULE_SLIPDEV_CONFIG)) {
|
||||
mutex_lock(&slipdev_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void slipdev_unlock(void)
|
||||
{
|
||||
if (IS_USED(MODULE_SLIPDEV_STDIO)) {
|
||||
if (IS_USED(MODULE_SLIPDEV_STDIO) || IS_USED(MODULE_SLIPDEV_CONFIG)) {
|
||||
mutex_unlock(&slipdev_mutex);
|
||||
}
|
||||
}
|
||||
@ -54,7 +72,6 @@ static void _slip_rx_cb(void *arg, uint8_t byte)
|
||||
slipdev_t *dev = arg;
|
||||
|
||||
switch (dev->state) {
|
||||
#if IS_USED(MODULE_SLIPDEV_STDIO)
|
||||
case SLIPDEV_STATE_STDIN:
|
||||
switch (byte) {
|
||||
case SLIPDEV_ESC:
|
||||
@ -64,7 +81,11 @@ static void _slip_rx_cb(void *arg, uint8_t byte)
|
||||
dev->state = SLIPDEV_STATE_NONE;
|
||||
break;
|
||||
default:
|
||||
isrpipe_write_one(&stdin_isrpipe, byte);
|
||||
#if IS_USED(MODULE_SLIPDEV_STDIO)
|
||||
if (dev->config.uart == STDIO_UART_DEV) {
|
||||
isrpipe_write_one(&stdin_isrpipe, byte);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return;
|
||||
@ -78,24 +99,81 @@ static void _slip_rx_cb(void *arg, uint8_t byte)
|
||||
break;
|
||||
}
|
||||
dev->state = SLIPDEV_STATE_STDIN;
|
||||
isrpipe_write_one(&stdin_isrpipe, byte);
|
||||
return;
|
||||
#if IS_USED(MODULE_SLIPDEV_STDIO)
|
||||
if (dev->config.uart == STDIO_UART_DEV) {
|
||||
isrpipe_write_one(&stdin_isrpipe, byte);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
case SLIPDEV_STATE_CONFIG:
|
||||
switch (byte) {
|
||||
case SLIPDEV_ESC:
|
||||
dev->state = SLIPDEV_STATE_CONFIG_ESC;
|
||||
break;
|
||||
case SLIPDEV_END:
|
||||
dev->state = SLIPDEV_STATE_NONE;
|
||||
#if IS_USED(MODULE_SLIPDEV_CONFIG)
|
||||
crb_end_chunk(&dev->rb_config, true);
|
||||
thread_flags_set(thread_get(dev->coap_server_pid), 1);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
#if IS_USED(MODULE_SLIPDEV_CONFIG)
|
||||
/* discard frame if byte can't be added */
|
||||
if (!crb_add_byte(&dev->rb_config, byte)) {
|
||||
DEBUG("slipdev: rx buffer full, drop frame\n");
|
||||
crb_end_chunk(&dev->rb_config, false);
|
||||
dev->state = SLIPDEV_STATE_NONE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return;
|
||||
case SLIPDEV_STATE_CONFIG_ESC:
|
||||
switch (byte) {
|
||||
case SLIPDEV_END_ESC:
|
||||
byte = SLIPDEV_END;
|
||||
break;
|
||||
case SLIPDEV_ESC_ESC:
|
||||
byte = SLIPDEV_ESC;
|
||||
break;
|
||||
}
|
||||
#if IS_USED(MODULE_SLIPDEV_CONFIG)
|
||||
/* discard frame if byte can't be added */
|
||||
if (!crb_add_byte(&dev->rb_config, byte)) {
|
||||
DEBUG("slipdev: rx buffer full, drop frame\n");
|
||||
crb_end_chunk(&dev->rb_config, false);
|
||||
dev->state = SLIPDEV_STATE_NONE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
dev->state = SLIPDEV_STATE_CONFIG;
|
||||
return;
|
||||
case SLIPDEV_STATE_NONE:
|
||||
/* is diagnostic frame? */
|
||||
if (IS_USED(MODULE_SLIPDEV_STDIO) &&
|
||||
(byte == SLIPDEV_STDIO_START) &&
|
||||
(dev->config.uart == STDIO_UART_DEV)) {
|
||||
if (byte == SLIPDEV_STDIO_START) {
|
||||
dev->state = SLIPDEV_STATE_STDIN;
|
||||
return;
|
||||
}
|
||||
|
||||
if (byte == SLIPDEV_CONFIG_START) {
|
||||
#if IS_USED(MODULE_SLIPDEV_CONFIG)
|
||||
/* try to create new frame */
|
||||
if (!crb_start_chunk(&dev->rb_config)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
dev->state = SLIPDEV_STATE_CONFIG;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ignore empty frame */
|
||||
if (byte == SLIPDEV_END) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* try to create new frame */
|
||||
/* try to create new ip frame */
|
||||
if (!crb_start_chunk(&dev->rb)) {
|
||||
return;
|
||||
}
|
||||
@ -198,8 +276,8 @@ void slipdev_write_bytes(uart_t uart, const uint8_t *data, size_t len)
|
||||
|
||||
static int _check_state(slipdev_t *dev)
|
||||
{
|
||||
/* power states not supported when multiplexing stdio */
|
||||
if (IS_USED(MODULE_SLIPDEV_STDIO)) {
|
||||
/* power states not supported when multiplexing stdio / configuration */
|
||||
if (IS_USED(MODULE_SLIPDEV_STDIO) || IS_USED(MODULE_SLIPDEV_CONFIG)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -272,7 +350,7 @@ static void _isr(netdev_t *netdev)
|
||||
}
|
||||
}
|
||||
|
||||
#if !IS_USED(MODULE_SLIPDEV_STDIO)
|
||||
#if !(IS_USED(MODULE_SLIPDEV_STDIO) || IS_USED(MODULE_SLIPDEV_CONFIG))
|
||||
static int _set_state(slipdev_t *dev, netopt_state_t state)
|
||||
{
|
||||
if (IS_USED(MODULE_SLIPDEV_STDIO)) {
|
||||
@ -309,7 +387,7 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *value, size_t max_le
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
#endif /* !MODULE_SLIPDEV_STDIO */
|
||||
#endif /* !(MODULE_SLIPDEV_STDIO || MODULE_SLIPDEV_CONFIG) */
|
||||
|
||||
static int _get(netdev_t *netdev, netopt_t opt, void *value, size_t max_len)
|
||||
{
|
||||
@ -348,15 +426,69 @@ static const netdev_driver_t slip_driver = {
|
||||
.isr = _isr,
|
||||
.get = _get,
|
||||
.confirm_send = _confirm_send,
|
||||
#if IS_USED(MODULE_SLIPDEV_STDIO)
|
||||
#if (IS_USED(MODULE_SLIPDEV_STDIO) || IS_USED(MODULE_SLIPDEV_CONFIG))
|
||||
.set = netdev_set_notsup,
|
||||
#else
|
||||
.set = _set,
|
||||
#endif
|
||||
};
|
||||
|
||||
#if IS_USED(MODULE_SLIPDEV_CONFIG)
|
||||
static void *_coap_server_thread(void *arg)
|
||||
{
|
||||
static uint8_t buf[512];
|
||||
slipdev_t *dev = arg;
|
||||
while (1) {
|
||||
thread_flags_wait_any(1);
|
||||
size_t len;
|
||||
while (crb_get_chunk_size(&dev->rb_config, &len)) {
|
||||
crb_consume_chunk(&dev->rb_config, buf, len);
|
||||
|
||||
/* Is the crc correct via residue(=0xF0B8) test */
|
||||
if (crc16_ccitt_fcs_update(SPECIAL_INIT_FCS, buf, len) != 0xF0B8) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* cut off the FCS checksum at the end */
|
||||
size_t pktlen = len - 2;
|
||||
|
||||
coap_pkt_t pkt;
|
||||
sock_udp_ep_t remote;
|
||||
coap_request_ctx_t ctx = {
|
||||
.remote = &remote,
|
||||
};
|
||||
if (coap_parse(&pkt, buf, pktlen) < 0) {
|
||||
break;
|
||||
}
|
||||
unsigned int res = 0;
|
||||
if ((res = coap_handle_req(&pkt, buf, sizeof(buf), &ctx)) <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t fcs_sum = crc16_ccitt_fcs_finish(SPECIAL_INIT_FCS, buf, res);
|
||||
|
||||
slipdev_lock();
|
||||
slipdev_write_byte(dev->config.uart, SLIPDEV_CONFIG_START);
|
||||
slipdev_write_bytes(dev->config.uart, buf, res);
|
||||
slipdev_write_bytes(dev->config.uart, (uint8_t *) &fcs_sum, 2);
|
||||
slipdev_write_byte(dev->config.uart, SLIPDEV_END);
|
||||
slipdev_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* MODULE_SLIPDEV_CONFIG */
|
||||
|
||||
void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params, uint8_t index)
|
||||
{
|
||||
#if IS_USED(MODULE_SLIPDEV_CONFIG)
|
||||
crb_init(&dev->rb_config, dev->rxmem_config, sizeof(dev->rxmem_config));
|
||||
|
||||
dev->coap_server_pid = thread_create(coap_stack, sizeof(coap_stack), THREAD_PRIORITY_MAIN - 1,
|
||||
THREAD_CREATE_STACKTEST, _coap_server_thread,
|
||||
(void *)dev, "Slipmux CoAP server");
|
||||
#endif
|
||||
/* set device descriptor fields */
|
||||
dev->config = *params;
|
||||
dev->state = 0;
|
||||
|
||||
@ -24,8 +24,6 @@
|
||||
#include "stdio_base.h"
|
||||
#include "stdio_uart.h"
|
||||
|
||||
mutex_t slipdev_mutex = MUTEX_INIT;
|
||||
|
||||
static void _isrpipe_write(void *arg, uint8_t data)
|
||||
{
|
||||
isrpipe_write_one(arg, (char)data);
|
||||
@ -34,9 +32,11 @@ static void _isrpipe_write(void *arg, uint8_t data)
|
||||
static void _init(void)
|
||||
{
|
||||
/* intentionally overwritten in netdev init so we have stdio before
|
||||
* the network device is initialized is initialized */
|
||||
* the network device is initialized */
|
||||
uart_init(slipdev_params[0].uart, slipdev_params[0].baudrate,
|
||||
_isrpipe_write, &stdin_isrpipe);
|
||||
|
||||
slipdev_write_byte(slipdev_params[0].uart, SLIPDEV_END);
|
||||
}
|
||||
|
||||
static ssize_t _write(const void *buffer, size_t len)
|
||||
|
||||
@ -464,6 +464,7 @@ PSEUDOMODULES += shield_llcc68
|
||||
PSEUDOMODULES += shield_sx1262
|
||||
PSEUDOMODULES += shield_w5100
|
||||
PSEUDOMODULES += slipdev_stdio
|
||||
PSEUDOMODULES += slipdev_config
|
||||
PSEUDOMODULES += slipdev_l2addr
|
||||
PSEUDOMODULES += sock
|
||||
PSEUDOMODULES += sock_async
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "embUnit/embUnit.h"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user