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

tests/driver_at86rf2xx: rewrite without GNRC

This commit is contained in:
MrKevinWeiss 2022-03-21 14:31:13 +01:00
parent 3095afafd2
commit 9d3a546e1d
No known key found for this signature in database
GPG Key ID: 4B69974722CBEEAE
9 changed files with 112 additions and 631 deletions

View File

@ -1,11 +1,9 @@
INCLUDES += -I$(APPDIR)
BOARD ?= samr21-xpro
include ../Makefile.tests_common
DISABLE_MODULE += auto_init_at86rf2xx
USEMODULE += od
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += ps
USEMODULE += test_utils_netdev_ieee802154_minimal
# define the driver to be used for selected boards
ifneq (,$(filter samr21-xpro,$(BOARD)))
@ -24,4 +22,6 @@ DRIVER ?= at86rf231
# include the selected driver
USEMODULE += $(DRIVER)
CFLAGS += -DEVENT_THREAD_STACKSIZE_DEFAULT=1024
include $(RIOTBASE)/Makefile.include

View File

@ -3,9 +3,8 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-f031k6 \
atmega328p \
nucleo-l011k4 \
samd10-xmini \
stm32f030f4-demo \

View File

@ -1,16 +1,16 @@
# About
This is a manual test application for the AT86RF2xx radio driver
This is a manual test application for the AT86RF2xx radio driver.
For running this test, you need to connect/configure the following pins of your
radio device:
- SPI MISO
- SPI MOSI
- SPI CLK
- CS (ship select)
- CS (chip select)
- RESET
- SLEEP
- INT (external interrupt)
# Usage
For testing the radio driver you can use the netif and txtsnd shell commands
For testing the radio driver you can use the ifconfig and txtsnd shell commands
that are included in this application.

View File

@ -1,31 +0,0 @@
/*
* 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 <mlenders@inf.fu-berlin.de>
*/
#include <stdio.h>
#include <stdint.h>
#include "common.h"
void print_addr(uint8_t *addr, size_t addr_len)
{
for (size_t i = 0; i < addr_len; i++) {
if (i != 0) {
printf(":");
}
printf("%02x", (unsigned)addr[i]);
}
}
/** @} */

View File

@ -1,335 +0,0 @@
/*
* 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 <mlenders@inf.fu-berlin.de>
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "at86rf2xx_internal.h"
#include "common.h"
#include "net/ieee802154.h"
#include "net/netdev/ieee802154.h"
#include "od.h"
#include "test_utils/expect.h"
#define _MAX_ADDR_LEN (8)
#define MAC_VECTOR_SIZE (2) /* mhr + payload */
static size_t _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;
netdev_ieee802154_t *dev = &devs[idx].netdev;
int (*get)(netdev_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(&dev->netdev, 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(&dev->netdev, 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(&dev->netdev, NETOPT_MAX_PDU_SIZE, &u16_val,
sizeof(u16_val));
if (res < 0) {
puts("(err)");
return 1;
}
printf(", Max.Payload: %u", (unsigned)u16_val);
printf("\n Channel: %u", dev->chan);
res = get(&dev->netdev, NETOPT_CHANNEL_PAGE, &u16_val, sizeof(u16_val));
if (res < 0) {
puts("(err)");
return 1;
}
printf(", Ch.page: %u", (unsigned)u16_val);
res = get(&dev->netdev, NETOPT_TX_POWER, &u16_val, sizeof(u16_val));
if (res < 0) {
puts("(err)");
return 1;
}
printf(", TXPower: %d dBm", (int)u16_val);
res = get(&dev->netdev, NETOPT_IS_WIRED, &u16_val, sizeof(u16_val));
if (res < 0) {
puts(", wireless");
}
else {
puts(", wired");
}
printf(" ");
res = get(&dev->netdev, NETOPT_PRELOADING, &enable_val,
sizeof(netopt_enable_t));
if ((res > 0) && (enable_val == NETOPT_ENABLE)) {
printf(" PRELOAD");
}
res = get(&dev->netdev, NETOPT_AUTOACK, &enable_val,
sizeof(netopt_enable_t));
if ((res > 0) && (enable_val == NETOPT_ENABLE)) {
printf(" AUTOACK");
}
res = get(&dev->netdev, NETOPT_RAWMODE, &enable_val,
sizeof(netopt_enable_t));
if ((res > 0) && (enable_val == NETOPT_ENABLE)) {
printf(" RAW");
}
res = get(&dev->netdev, NETOPT_AUTOCCA, &enable_val,
sizeof(netopt_enable_t));
if ((res > 0) && (enable_val == NETOPT_ENABLE)) {
printf(" AUTOCCA");
}
res = get(&dev->netdev, 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 (unsigned int i = 0; i < AT86RF2XX_NUM; i++) {
ifconfig_list(i);
}
return 0;
}
static void txtsnd_usage(char *cmd_name)
{
printf("usage: %s <iface> [<pan>] <addr> <text>\n", cmd_name);
}
int txtsnd(int argc, char **argv)
{
char *text;
uint8_t addr[_MAX_ADDR_LEN];
int iface, idx = 2;
size_t 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, 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 size_t _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;
netdev_ieee802154_t *dev;
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;
}
iolist_t iol_data = {
.iol_base = data,
.iol_len = strlen(data)
};
dev = &devs[iface].netdev;
flags = (uint8_t)(dev->flags & NETDEV_IEEE802154_SEND_MASK);
flags |= IEEE802154_FCF_TYPE_DATA;
src_pan = byteorder_btols(byteorder_htons(dev->pan));
if (dst_pan.u16 == 0) {
dst_pan = src_pan;
}
if (dev->flags & NETDEV_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;
}
iolist_t iol_hdr = {
.iol_next = &iol_data,
.iol_base = mhr,
.iol_len = (size_t)res
};
res = dev->netdev.driver->send(&dev->netdev, &iol_hdr);
if (res < 0) {
puts("txtsnd: Error on sending");
return 1;
}
else {
printf("txtsnd: send %u bytes to ", (unsigned)iol_data.iol_len);
print_addr(dst, dst_len);
printf(" (PAN: ");
print_addr((uint8_t *)&dst_pan, sizeof(dst_pan));
puts(")");
}
return 0;
}
#if AT86RF2XX_RANDOM_NUMBER_GENERATOR
void random_net_api(uint8_t idx, uint32_t *value)
{
netdev_ieee802154_t *dev = &devs[idx].netdev;
int retval = dev->netdev.driver->get(&dev->netdev, NETOPT_RANDOM,
value, sizeof(uint32_t));
if (retval < 0) {
printf("get(NETOPT_RANDOM) failed: %s\n", strerror(-retval));
}
else {
expect(retval == sizeof(*value));
}
}
int random_by_at86rf2xx(int argc, char **argv)
{
(void)argc;
(void)argv;
for (unsigned int i = 0; i < AT86RF2XX_NUM; i++) {
uint32_t test = 0;
at86rf2xx_get_random(&devs[i], (uint8_t *)&test, sizeof(test));
printf("Random number for device %u via native API: %" PRIx32 "\n", i, test);
test = 0;
random_net_api(i, &test);
printf("Random number for device %u via netopt: %" PRIx32 "\n", i, test);
}
return 0;
}
#endif
/** @} */

View File

@ -1,57 +0,0 @@
/*
* Copyright (C) 2016 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* 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 <mlenders@inf.fu-berlin.de>
*/
#ifndef COMMON_H
#define COMMON_H
#include <stdint.h>
#include "at86rf2xx.h"
#include "at86rf2xx_params.h"
#include "net/netdev.h"
#include "kernel_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Application-internal functions and variables for at86rf2xx tests
* @internal
* @{
*/
#define AT86RF2XX_NUM ARRAY_SIZE(at86rf2xx_params)
extern at86rf2xx_t devs[AT86RF2XX_NUM];
void recv(netdev_t *dev);
int ifconfig(int argc, char **argv);
int txtsnd(int argc, char **argv);
#if AT86RF2XX_RANDOM_NUMBER_GENERATOR
int random_by_at86rf2xx(int argc, char **argv);
#endif
void print_addr(uint8_t *addr, size_t addr_len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* COMMON_H */
/** @} */

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2022 HAW Hamburg
*
* 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 Device-specific test header file AT86RF2XX IEEE 802.15.4 device driver
*
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
*/
#ifndef INIT_DEV_H
#define INIT_DEV_H
#include "at86rf2xx_params.h"
#include "kernel_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AT86RF2XX_NUM ARRAY_SIZE(at86rf2xx_params)
#define NETDEV_IEEE802154_MINIMAL_NUMOF AT86RF2XX_NUM
#ifdef __cplusplus
}
#endif
#endif /* INIT_DEV_H */
/** @} */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Freie Universität Berlin
* Copyright (C) 2022 HAW Hamburg
*
* 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
@ -11,110 +11,92 @@
* @{
*
* @file
* @brief Test application for AT86RF2xx network device driver
* @brief Test application for AT86RF2XX IEEE 802.15.4 device driver
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
*
* @}
*/
#include <stdio.h>
#include "net/netdev.h"
#include "at86rf2xx.h"
#include "at86rf2xx_params.h"
#include "at86rf2xx_internal.h"
#include "init_dev.h"
#include "net/ieee802154.h"
#include "net/netdev/ieee802154.h"
#include "shell.h"
#include "thread.h"
#include "xtimer.h"
#include "test_utils/netdev_ieee802154_minimal.h"
#include "test_utils/expect.h"
#include "common.h"
static at86rf2xx_t at86rf2xx[AT86RF2XX_NUM];
#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 netdev", ifconfig },
{ "txtsnd", "Send IEEE 802.15.4 packet", txtsnd },
#if AT86RF2XX_RANDOM_NUMBER_GENERATOR
{ "random", "Get a value from Random Number Generator", random_by_at86rf2xx },
#endif
{ NULL, NULL, NULL }
};
static void _event_cb(netdev_t *dev, netdev_event_t event)
void random_net_api(uint8_t idx, uint32_t *value)
{
if (event == NETDEV_EVENT_ISR) {
msg_t msg;
msg.type = MSG_TYPE_ISR;
msg.content.ptr = dev;
if (msg_send(&msg, _recv_pid) <= 0) {
puts("gnrc_netdev: possibly lost interrupt.");
}
netdev_ieee802154_t *dev = &at86rf2xx[idx].netdev;
dev->netdev.driver->get(&dev->netdev, NETOPT_RANDOM, value, sizeof(uint32_t));
int retval = dev->netdev.driver->get(&dev->netdev, NETOPT_RANDOM,
value, sizeof(uint32_t));
if (retval < 0) {
printf("get(NETOPT_RANDOM) failed: %s\n", strerror(-retval));
}
else {
switch (event) {
case NETDEV_EVENT_RX_COMPLETE:
{
recv(dev);
break;
}
default:
puts("Unexpected event received");
break;
}
expect(retval == sizeof(*value));
}
}
void *_recv_thread(void *arg)
int random_by_at86rf2xx(int argc, char **argv)
{
(void)arg;
while (1) {
msg_t msg;
msg_receive(&msg);
if (msg.type == MSG_TYPE_ISR) {
netdev_t *dev = msg.content.ptr;
dev->driver->isr(dev);
}
else {
puts("unexpected message type");
(void)argc;
(void)argv;
for (unsigned int i = 0; i < AT86RF2XX_NUM; i++) {
uint32_t test = 0;
at86rf2xx_get_random(&at86rf2xx[i], (uint8_t *)&test, sizeof(test));
printf("Random number for device %u via native API: %" PRIx32 "\n", i, test);
test = 0;
random_net_api(i, &test);
printf("Random number for device %u via netopt: %" PRIx32 "\n", i, test);
}
return 0;
}
static const shell_command_t shell_commands[] = {
{ "random", "Get a value from Random Number Generator", random_by_at86rf2xx },
{ NULL, NULL, NULL }
};
#endif
int netdev_ieee802154_minimal_init_devs(netdev_event_cb_t cb) {
puts("Initializing AT86RF2XX devices");
for (unsigned i = 0; i < AT86RF2XX_NUM; i++) {
printf("%d out of %d\n", i + 1, AT86RF2XX_NUM);
/* setup the specific driver */
at86rf2xx_setup(&at86rf2xx[i], &at86rf2xx_params[i], i);
/* set the application-provided callback */
at86rf2xx[i].netdev.netdev.event_callback = cb;
/* initialize the device driver */
int res = at86rf2xx[i].netdev.netdev.driver->init(&at86rf2xx[i].netdev.netdev);
if (res != 0) {
return -1;
}
}
return 0;
}
int main(void)
{
puts("AT86RF2xx device driver test");
unsigned dev_success = 0;
for (unsigned i = 0; i < AT86RF2XX_NUM; i++) {
const at86rf2xx_params_t *p = &at86rf2xx_params[i];
netdev_t *dev = &devs[i].netdev.netdev;
puts("Test application for AT86RF2XX IEEE 802.15.4 device driver");
printf("Initializing AT86RF2xx radio at SPI_%d\n", p->spi);
at86rf2xx_setup(&devs[i], p, i);
dev->event_callback = _event_cb;
if (dev->driver->init(dev) < 0) {
continue;
}
dev_success++;
}
if (!dev_success) {
puts("No device could be initialized");
return 1;
}
_recv_pid = thread_create(stack, sizeof(stack), THREAD_PRIORITY_MAIN - 1,
THREAD_CREATE_STACKTEST, _recv_thread, NULL,
"recv_thread");
if (_recv_pid <= KERNEL_PID_UNDEF) {
puts("Creation of receiver thread failed");
int res = netdev_ieee802154_minimal_init();
if (res) {
puts("Error initializing devices");
return 1;
}
@ -122,7 +104,11 @@ int main(void)
puts("Initialization successful - starting the shell now");
char line_buf[SHELL_DEFAULT_BUFSIZE];
#if AT86RF2XX_RANDOM_NUMBER_GENERATOR
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
#else
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
#endif
return 0;
}

View File

@ -1,117 +0,0 @@
/*
* 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 <mlenders@inf.fu-berlin.de>
*/
#include <stdio.h>
#include "at86rf2xx.h"
#include "od.h"
#include "net/ieee802154.h"
#include "net/netdev.h"
#include "common.h"
#define MAX_LINE (80)
static uint8_t buffer[AT86RF2XX_MAX_PKT_LENGTH];
void recv(netdev_t *dev)
{
uint8_t src[IEEE802154_LONG_ADDRESS_LEN], dst[IEEE802154_LONG_ADDRESS_LEN];
size_t mhr_len, data_len, src_len, dst_len;
netdev_ieee802154_rx_info_t rx_info;
le_uint16_t src_pan, dst_pan;
putchar('\n');
data_len = dev->driver->recv(dev, 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_ltohs(dst_pan));
print_addr(dst, dst_len);
printf("\nSrc. PAN: 0x%04x, Src. addr.: ",
byteorder_ltohs(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_PAN_COMP) {
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 (size_t 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: %i, LQI: %u\n\n", rx_info.rssi, rx_info.lqi);
}
/** @} */