From dff0c528ff60ec8d61b017b5c6acb2ceb1e91835 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 25 Jan 2016 00:17:49 +0100 Subject: [PATCH] tests: modify driver_at86rf2xx for pure netdev2 --- tests/driver_at86rf2xx/Makefile | 7 +- tests/driver_at86rf2xx/addr.c | 31 ++++ tests/driver_at86rf2xx/cmd.c | 306 ++++++++++++++++++++++++++++++++ tests/driver_at86rf2xx/common.h | 53 ++++++ tests/driver_at86rf2xx/main.c | 97 ++++++++-- tests/driver_at86rf2xx/recv.c | 117 ++++++++++++ 6 files changed, 593 insertions(+), 18 deletions(-) create mode 100644 tests/driver_at86rf2xx/addr.c create mode 100644 tests/driver_at86rf2xx/cmd.c create mode 100644 tests/driver_at86rf2xx/common.h create mode 100644 tests/driver_at86rf2xx/recv.c diff --git a/tests/driver_at86rf2xx/Makefile b/tests/driver_at86rf2xx/Makefile index 03f6c10e65ab..02dc1afe96f4 100644 --- a/tests/driver_at86rf2xx/Makefile +++ b/tests/driver_at86rf2xx/Makefile @@ -3,12 +3,9 @@ include ../Makefile.tests_common FEATURES_REQUIRED = periph_spi periph_gpio -BOARD_INSUFFICIENT_MEMORY := nucleo-f334 stm32f0discovery weio +DISABLE_MODULE += auto_init -USEMODULE += auto_init_gnrc_netif -USEMODULE += gnrc_netif -USEMODULE += gnrc_nomac -USEMODULE += gnrc_pktdump +USEMODULE += od USEMODULE += shell USEMODULE += shell_commands USEMODULE += ps diff --git a/tests/driver_at86rf2xx/addr.c b/tests/driver_at86rf2xx/addr.c new file mode 100644 index 000000000000..af6b0c22611a --- /dev/null +++ b/tests/driver_at86rf2xx/addr.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 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 + */ + +#include +#include + +#include "common.h" + +void print_addr(uint8_t *addr, size_t addr_len) +{ + for (int i = 0; i < addr_len; i++) { + if (i != 0) { + printf(":"); + } + printf("%02x", (unsigned)addr[i]); + } +} + +/** @} */ diff --git a/tests/driver_at86rf2xx/cmd.c b/tests/driver_at86rf2xx/cmd.c new file mode 100644 index 000000000000..10d44df3f942 --- /dev/null +++ b/tests/driver_at86rf2xx/cmd.c @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2016 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 + */ + +#include +#include +#include +#include + +#include "net/netdev2/ieee802154.h" +#include "net/ieee802154.h" + +#include "common.h" + +#include "od.h" + +#define _MAX_ADDR_LEN (8) + +static int _parse_addr(uint8_t *out, size_t out_len, const char *in); +static int send(int iface, le_uint16_t dst_pan, uint8_t *dst_addr, + size_t dst_len, char *data); + +int ifconfig_list(int idx) +{ + int res; + uint8_t array_val[_MAX_ADDR_LEN]; + netdev2_ieee802154_t *dev = (netdev2_ieee802154_t *)(&devs[idx]); + + int (*get)(netdev2_t *, netopt_t, void *, size_t) = dev->netdev.driver->get; + netopt_enable_t enable_val; + uint16_t u16_val; + + printf("Iface %3d HWaddr: ", idx); + print_addr(dev->short_addr, IEEE802154_SHORT_ADDRESS_LEN); + printf(", Long HWaddr: "); + print_addr(dev->long_addr, IEEE802154_LONG_ADDRESS_LEN); + printf(", PAN: 0x%04x", dev->pan); + + res = get((netdev2_t *)dev, NETOPT_ADDR_LEN, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf("\n Address length: %u", (unsigned)u16_val); + + res = get((netdev2_t *)dev, NETOPT_SRC_LEN, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf(", Source address length: %u", (unsigned)u16_val); + + res = get((netdev2_t *)dev, NETOPT_MAX_PACKET_SIZE, &u16_val, + sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf(", Max.Payload: %u", (unsigned)u16_val); + + res = get((netdev2_t *)dev, NETOPT_IPV6_IID, array_val, sizeof(array_val)); + if (res > 0) { + printf("\n IPv6 IID: "); + print_addr(array_val, res); + } + + printf("\n Channel: %u", dev->chan); + + res = get((netdev2_t *)dev, NETOPT_CHANNEL_PAGE, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf(", Ch.page: %u", (unsigned)u16_val); + + res = get((netdev2_t *)dev, NETOPT_TX_POWER, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf(", TXPower: %d dBm", (int)u16_val); + res = get((netdev2_t *)dev, NETOPT_IS_WIRED, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts(", wireless"); + } + else { + puts(", wired"); + } + + printf(" "); + res = get((netdev2_t *)dev, NETOPT_PRELOADING, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" PRELOAD"); + } + res = get((netdev2_t *)dev, NETOPT_AUTOACK, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" AUTOACK"); + } + res = get((netdev2_t *)dev, NETOPT_RAWMODE, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" RAW"); + } + res = get((netdev2_t *)dev, NETOPT_AUTOCCA, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" AUTOCCA"); + } + res = get((netdev2_t *)dev, NETOPT_CSMA, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" CSMA"); + } + puts(""); + + return 0; +} + +int ifconfig(int argc, char **argv) +{ + (void)argc; + (void)argv; + for (int i = 0; i < AT86RF2XX_NUM; i++) { + ifconfig_list(i); + } + return 0; +} + +static void txtsnd_usage(char *cmd_name) +{ + printf("usage: %s [] \n", cmd_name); +} + +int txtsnd(int argc, char **argv) +{ + char *text; + uint8_t addr[_MAX_ADDR_LEN]; + int iface, idx = 2, res; + le_uint16_t pan = { 0 }; + + switch (argc) { + case 4: + break; + case 5: + res = _parse_addr((uint8_t *)&pan, sizeof(pan), argv[idx++]); + if ((res <= 0) || (res > sizeof(pan))) { + txtsnd_usage(argv[0]); + return 1; + } + pan.u16 = byteorder_swaps(pan.u16); + break; + default: + txtsnd_usage(argv[0]); + return 1; + } + + iface = atoi(argv[1]); + res = _parse_addr(addr, sizeof(addr), argv[idx++]); + if (res <= 0) { + txtsnd_usage(argv[0]); + return 1; + } + text = argv[idx++]; + return send(iface, pan, addr, (size_t)res, text); +} + +static inline int _dehex(char c, int default_) +{ + if ('0' <= c && c <= '9') { + return c - '0'; + } + else if ('A' <= c && c <= 'F') { + return c - 'A' + 10; + } + else if ('a' <= c && c <= 'f') { + return c - 'a' + 10; + } + else { + return default_; + } +} + +static int _parse_addr(uint8_t *out, size_t out_len, const char *in) +{ + const char *end_str = in; + uint8_t *out_end = out; + size_t count = 0; + int assert_cell = 1; + + if (!in || !*in) { + return 0; + } + while (end_str[1]) { + ++end_str; + } + + while (end_str >= in) { + int a = 0, b = _dehex(*end_str--, -1); + if (b < 0) { + if (assert_cell) { + return 0; + } + else { + assert_cell = 1; + continue; + } + } + assert_cell = 0; + + if (end_str >= in) { + a = _dehex(*end_str--, 0); + } + + if (++count > out_len) { + return 0; + } + *out_end++ = (a << 4) | b; + } + if (assert_cell) { + return 0; + } + /* out is reversed */ + + while (out < --out_end) { + uint8_t tmp = *out_end; + *out_end = *out; + *out++ = tmp; + } + + return count; +} + +static int send(int iface, le_uint16_t dst_pan, uint8_t *dst, size_t dst_len, + char *data) +{ + int res; + netdev2_ieee802154_t *dev; + const size_t count = 2; /* mhr + payload */ + struct iovec vector[count]; + uint8_t *src; + size_t src_len; + uint8_t mhr[IEEE802154_MAX_HDR_LEN]; + uint8_t flags; + le_uint16_t src_pan; + + if (((unsigned)iface) > (AT86RF2XX_NUM - 1)) { + printf("txtsnd: %d is not an interface\n", iface); + return 1; + } + + dev = (netdev2_ieee802154_t *)&devs[iface]; + flags = (uint8_t)(dev->flags & NETDEV2_IEEE802154_SEND_MASK); + flags |= IEEE802154_FCF_TYPE_DATA; + vector[1].iov_base = data; + vector[1].iov_len = strlen(data); + src_pan = byteorder_btols(byteorder_htons(dev->pan)); + if (dst_pan.u16 == 0) { + dst_pan = src_pan; + } + if (dev->flags & NETDEV2_IEEE802154_SRC_MODE_LONG) { + src_len = 8; + src = dev->long_addr; + } + else { + src_len = 2; + src = dev->short_addr; + } + /* fill MAC header, seq should be set by device */ + if ((res = ieee802154_set_frame_hdr(mhr, src, src_len, + dst, dst_len, + src_pan, dst_pan, + flags, dev->seq++)) < 0) { + puts("txtsnd: Error preperaring frame"); + return 1; + } + vector[0].iov_base = mhr; + vector[0].iov_len = (size_t)res; + res = dev->netdev.driver->send((netdev2_t *)dev, vector, count); + if (res < 0) { + puts("txtsnd: Error on sending"); + return 1; + } + else { + printf("txtsnd: send %u bytes to ", (unsigned)vector[1].iov_len); + print_addr(dst, dst_len); + printf(" (PAN: "); + print_addr((uint8_t *)&dst_pan, sizeof(dst_pan)); + puts(")"); + } + return 0; +} + +/** @} */ diff --git a/tests/driver_at86rf2xx/common.h b/tests/driver_at86rf2xx/common.h new file mode 100644 index 000000000000..8829b6e54d5b --- /dev/null +++ b/tests/driver_at86rf2xx/common.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 Martine Lenders + * + * 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 tests + * @{ + * + * @file + * @brief Common header for at86rf2xx tests + * + * @author Martine Lenders + */ +#ifndef COMMON_H_ +#define COMMON_H_ + +#include + +#include "at86rf2xx.h" +#include "at86rf2xx_params.h" +#include "net/netdev2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Application-internal functions and variables for at86rf2xx tests + * @internal + * @{ + */ +#define AT86RF2XX_NUM (sizeof(at86rf2xx_params) / sizeof(at86rf2xx_params[0])) + +extern at86rf2xx_t devs[AT86RF2XX_NUM]; + +void recv(netdev2_t *dev); +int ifconfig(int argc, char **argv); +int txtsnd(int argc, char **argv); +void print_addr(uint8_t *addr, size_t addr_len); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_H_ */ +/** @} */ diff --git a/tests/driver_at86rf2xx/main.c b/tests/driver_at86rf2xx/main.c index 1a5f12f9a7f6..1be7bfb5bbc0 100644 --- a/tests/driver_at86rf2xx/main.c +++ b/tests/driver_at86rf2xx/main.c @@ -20,31 +20,102 @@ #include +#include "net/netdev2.h" #include "shell.h" #include "shell_commands.h" -#include "net/gnrc/pktdump.h" -#include "net/gnrc.h" +#include "thread.h" +#include "xtimer.h" -/** - * @brief Maybe you are a golfer?! - */ -int main(void) +#include "common.h" + +#define _STACKSIZE (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF) +#define MSG_TYPE_ISR (0x3456) + +static char stack[_STACKSIZE]; +static kernel_pid_t _recv_pid; + +at86rf2xx_t devs[AT86RF2XX_NUM]; + +static const shell_command_t shell_commands[] = { + { "ifconfig", "Configure netdev2", ifconfig }, + { "txtsnd", "Send IEEE 802.15.4 packet", txtsnd }, + { NULL, NULL, NULL } +}; + +static void _event_cb(netdev2_t *dev, netdev2_event_t event, void *data) { - gnrc_netreg_entry_t dump; + (void) data; + + if (event == NETDEV2_EVENT_ISR) { + msg_t msg; + + msg.type = MSG_TYPE_ISR; + msg.content.ptr = (void *) dev; + + if (msg_send(&msg, _recv_pid) <= 0) { + puts("gnrc_netdev2: possibly lost interrupt."); + } + } + else { + switch (event) { + case NETDEV2_EVENT_RX_COMPLETE: + { + recv(dev); + break; + } + default: + puts("Unexpected event received"); + break; + } + } +} + +void *_recv_thread(void *arg) +{ + while (1) { + msg_t msg; + msg_receive(&msg); + if (msg.type == MSG_TYPE_ISR) { + netdev2_t *dev = (netdev2_t *)msg.content.ptr; + dev->driver->isr(dev); + } + else { + puts("unexpected message type"); + } + } +} + +int main(void) +{ puts("AT86RF2xx device driver test"); + xtimer_init(); + + for (unsigned i = 0; i < AT86RF2XX_NUM; i++) { + const at86rf2xx_params_t *p = &at86rf2xx_params[i]; + netdev2_t *dev = (netdev2_t *)(&devs[i]); + + printf("Initializing AT86RF2xx radio at SPI_%d\n", p->spi); + at86rf2xx_setup(&devs[i], p->spi, p->spi_speed, p->cs_pin, + p->int_pin, p->sleep_pin, p->reset_pin); + dev->event_callback = _event_cb; + dev->driver->init(dev); + } + + _recv_pid = thread_create(stack, sizeof(stack), THREAD_PRIORITY_MAIN - 1, + THREAD_CREATE_STACKTEST, _recv_thread, NULL, + "recv_thread"); - /* register the pktdump thread */ - puts("Register the packet dump thread for GNRC_NETTYPE_UNDEF packets"); - dump.pid = gnrc_pktdump_pid; - dump.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; - gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); + if (_recv_pid <= KERNEL_PID_UNDEF) { + puts("Creation of receiver thread failed"); + return 1; + } /* start the shell */ puts("Initialization successful - starting the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/tests/driver_at86rf2xx/recv.c b/tests/driver_at86rf2xx/recv.c new file mode 100644 index 000000000000..d351eb2574a4 --- /dev/null +++ b/tests/driver_at86rf2xx/recv.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 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 + */ + +#include + +#include "at86rf2xx.h" +#include "od.h" +#include "net/ieee802154.h" +#include "net/netdev2.h" + +#include "common.h" + +#define MAX_LINE (80) + +static uint8_t buffer[AT86RF2XX_MAX_PKT_LENGTH]; + +void recv(netdev2_t *dev) +{ + uint8_t src[IEEE802154_LONG_ADDRESS_LEN], dst[IEEE802154_LONG_ADDRESS_LEN]; + size_t mhr_len, data_len, src_len, dst_len; + netdev2_ieee802154_rx_info_t rx_info; + le_uint16_t src_pan, dst_pan; + + putchar('\n'); + data_len = dev->driver->recv(dev, (char *)buffer, sizeof(buffer), &rx_info); + mhr_len = ieee802154_get_frame_hdr_len(buffer); + if (mhr_len == 0) { + puts("Unexpected MHR for incoming packet"); + return; + } + dst_len = ieee802154_get_dst(buffer, dst, &dst_pan); + src_len = ieee802154_get_src(buffer, src, &src_pan); + switch (buffer[0] & IEEE802154_FCF_TYPE_MASK) { + case IEEE802154_FCF_TYPE_BEACON: + puts("BEACON"); + break; + case IEEE802154_FCF_TYPE_DATA: + puts("DATA"); + break; + case IEEE802154_FCF_TYPE_ACK: + puts("ACK"); + break; + case IEEE802154_FCF_TYPE_MACCMD: + puts("MACCMD"); + break; + default: + puts("UNKNOWN"); + break; + } + printf("Dest. PAN: 0x%04x, Dest. addr.: ", + byteorder_ntohs(byteorder_ltobs(dst_pan))); + print_addr(dst, dst_len); + printf("\nSrc. PAN: 0x%04x, Src. addr.: ", + byteorder_ntohs(byteorder_ltobs(src_pan))); + print_addr(src, src_len); + printf("\nSecurity: "); + if (buffer[0] & IEEE802154_FCF_SECURITY_EN) { + printf("1, "); + } + else { + printf("0, "); + } + printf("Frame pend.: "); + if (buffer[0] & IEEE802154_FCF_FRAME_PEND) { + printf("1, "); + } + else { + printf("0, "); + } + printf("ACK req.: "); + if (buffer[0] & IEEE802154_FCF_ACK_REQ) { + printf("1, "); + } + else { + printf("0, "); + } + printf("PAN comp.: "); + if (buffer[0] & IEEE802154_FCF_ACK_REQ) { + puts("1"); + } + else { + puts("0"); + } + printf("Version: "); + printf("%u, ", (unsigned)((buffer[1] & IEEE802154_FCF_VERS_MASK) >> 4)); + printf("Seq.: %u\n", (unsigned)ieee802154_get_seq(buffer)); + od_hex_dump(buffer + mhr_len, data_len - mhr_len, 0); + printf("txt: "); + for (int i = mhr_len; i < data_len; i++) { + if ((buffer[i] > 0x1F) && (buffer[i] < 0x80)) { + putchar((char)buffer[i]); + } + else { + putchar('?'); + } + if (((((i - mhr_len) + 1) % (MAX_LINE - sizeof("txt: "))) == 1) && + (i - mhr_len) != 0) { + printf("\n "); + } + } + printf("\n"); + printf("RSSI: %u, LQI: %u\n\n", rx_info.rssi, rx_info.lqi); +} + +/** @} */