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

Merge pull request #16826 from jia200x/pr/submac/test/remove_netdev

tests/ieee802154_submac: remove netdev dependency
This commit is contained in:
José Alamos 2021-09-29 15:05:43 +02:00 committed by GitHub
commit 280c756c7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 261 additions and 203 deletions

View File

@ -189,6 +189,7 @@ endif
ifneq (,$(filter ieee802154_submac,$(USEMODULE)))
USEMODULE += xtimer
USEMODULE += random
endif
ifneq (,$(filter l2util,$(USEMODULE)))

View File

@ -18,11 +18,18 @@ BOARD_WHITELIST := \
#
USEMODULE += od
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += ps
USEMODULE += event_thread_highest
USEMODULE += netdev_ieee802154_submac
USEMODULE += event_thread
USEMODULE += netdev_default
USEMODULE += luid
USEMODULE += l2util
USEMODULE += eui_provider
USEMODULE += ieee802154
USEMODULE += ieee802154_submac
USEMODULE += ztimer_usec
CFLAGS += -DEVENT_THREAD_HIGHEST_STACKSIZE=1024
CFLAGS += -DEVENT_THREAD_MEDIUM_STACKSIZE=1024
include $(RIOTBASE)/Makefile.include
include $(RIOTMAKE)/default-radio-settings.inc.mk

View File

@ -32,58 +32,171 @@
#include "net/ieee802154/submac.h"
#include "net/ieee802154.h"
#include "net/netdev/ieee802154_submac.h"
#include "net/l2util.h"
#include "ztimer.h"
#include "common.h"
#define MAX_LINE (80)
/* Only the first radio is supported so far */
#define RADIO_DEFAULT_ID (0U)
ieee802154_submac_t submac; /**< IEEE 802.15.4 SubMAC descriptor */
mutex_t lock; /**< lock used to synchronize SubMAC operation */
ztimer_t ack_timer; /**< required for the ACK timer */
eui64_t long_addr; /**< SubMAC extended address */
network_uint16_t short_addr; /**< SubMAC short address */
netdev_ieee802154_submac_t netdev_submac;
mutex_t lock;
static void _ev_tx_done_handler(event_t *event); /**< TX Done event handler */
static void _ev_rx_done_handler(event_t *event); /**< RX Done event handler */
static void _ev_crc_error_handler(event_t *event); /**< CRC Error event handler */
static void _ev_bh_request_handler(event_t *event); /**< BH Request event handler */
static void _ev_ack_timeout_handler(event_t *event); /**< ACK Timeout event handler */
static void _ev_set_rx_handler(event_t *event); /**< Set RX event handler */
struct send_ctx {
event_t ev;
iolist_t pkt;
static event_t ev_tx_done = { .handler = _ev_tx_done_handler }; /**< TX Done descriptor */
static event_t ev_rx_done = { .handler = _ev_rx_done_handler }; /**< RX Done descriptor */
static event_t ev_crc_error = { .handler = _ev_crc_error_handler }; /**< CRC Error descriptor */
static event_t ev_bh_request = { .handler = _ev_bh_request_handler }; /**< BH Request descriptor */
static event_t ev_ack_timeout = { .handler = _ev_ack_timeout_handler }; /**< ACK TO descriptor */
static event_t ev_set_rx = { .handler = _ev_set_rx_handler }; /**< Set RX descriptor */
uint8_t buffer[IEEE802154_FRAME_LEN_MAX]; /* buffer to store IEEE 802.15.4 frames */
uint8_t seq; /* sequence number of IEEE 802.15.4 frame */
struct _reg_container {
int count; /* device index */
};
static void _send_handler(event_t *ev)
{
struct send_ctx *ctx = (struct send_ctx*) ev;
netdev_t *dev = &netdev_submac.dev.netdev;
static void submac_rx_done(ieee802154_submac_t *submac);
static void submac_tx_done(ieee802154_submac_t *submac, int status,
ieee802154_tx_info_t *info);
dev->driver->send(dev, &ctx->pkt);
}
static const ieee802154_submac_cb_t _cb = {
.rx_done = submac_rx_done,
.tx_done = submac_tx_done,
};
void _ack_timeout(void *arg);
static const uint8_t payload[] =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ornare" \
"lacinia mi elementum interdum ligula.";
uint8_t buffer[IEEE802154_FRAME_LEN_MAX];
uint8_t seq;
static int print_addr(int argc, char **argv);
static int txtsnd(int argc, char **argv);
static const shell_command_t shell_commands[] = {
{ "print_addr", "Print IEEE802.15.4 addresses", print_addr },
{ "txtsnd", "Send IEEE 802.15.4 packet", txtsnd },
{ NULL, NULL, NULL }
};
static int print_addr(int argc, char **argv)
{
(void)argc;
(void)argv;
uint8_t *_p = (uint8_t *)&netdev_submac.submac.ext_addr;
/****** SubMAC South Bond API Implementation ******/
for (int i = 0; i < 8; i++) {
printf("%02x", *_p++);
}
printf("\n");
return 0;
}
extern const netdev_driver_t netdev_submac_driver;
static void _netdev_isr_handler(event_t *event)
static void _ev_tx_done_handler(event_t *event)
{
(void)event;
netdev_t *netdev = &netdev_submac.dev.netdev;
netdev->driver->isr(netdev);
mutex_lock(&lock);
ieee802154_submac_tx_done_cb(&submac);
mutex_unlock(&lock);
}
static void _ev_rx_done_handler(event_t *event)
{
(void)event;
mutex_lock(&lock);
ieee802154_submac_rx_done_cb(&submac);
mutex_unlock(&lock);
}
static void _ev_crc_error_handler(event_t *event)
{
(void)event;
mutex_lock(&lock);
ieee802154_submac_crc_error_cb(&submac);
mutex_unlock(&lock);
}
static void _ev_bh_request_handler(event_t *event)
{
(void)event;
mutex_lock(&lock);
ieee802154_submac_bh_process(&submac);
mutex_unlock(&lock);
}
static void _ev_ack_timeout_handler(event_t *event)
{
(void)event;
mutex_lock(&lock);
ieee802154_submac_ack_timeout_fired(&submac);
mutex_unlock(&lock);
}
void ieee802154_submac_ack_timer_set(ieee802154_submac_t *submac, uint16_t us)
{
(void)submac;
ztimer_set(ZTIMER_USEC, &ack_timer, us);
}
void ieee802154_submac_ack_timer_cancel(ieee802154_submac_t *submac)
{
(void)submac;
ztimer_remove(ZTIMER_USEC, &ack_timer);
}
static void _ack_timeout(void *arg)
{
(void)arg;
event_post(EVENT_PRIO_HIGHEST, &ev_ack_timeout);
}
static void _hal_radio_cb(ieee802154_dev_t *dev, ieee802154_trx_ev_t status)
{
(void)dev;
switch (status) {
case IEEE802154_RADIO_CONFIRM_TX_DONE:
event_post(EVENT_PRIO_HIGHEST, &ev_tx_done);
break;
case IEEE802154_RADIO_INDICATION_RX_DONE:
event_post(EVENT_PRIO_HIGHEST, &ev_rx_done);
break;
case IEEE802154_RADIO_INDICATION_CRC_ERROR:
event_post(EVENT_PRIO_HIGHEST, &ev_crc_error);
break;
default:
break;
}
}
void ieee802154_submac_bh_request(ieee802154_submac_t *submac)
{
(void)submac;
event_post(EVENT_PRIO_HIGHEST, &ev_bh_request);
}
static ieee802154_dev_t *_reg_callback(ieee802154_dev_type_t type, void *opaque)
{
struct _reg_container *reg = opaque;
printf("Trying to register ");
switch (type) {
case IEEE802154_DEV_TYPE_CC2538_RF:
printf("cc2538_rf");
break;
case IEEE802154_DEV_TYPE_NRF802154:
printf("nrf52840");
break;
}
puts(".");
if (reg->count > 0) {
puts("For the moment this test only supports one radio");
return NULL;
}
puts("Success");
return &submac.dev;
}
/****** Helpers ******/
void _print_addr(uint8_t *addr, size_t addr_len)
{
for (size_t i = 0; i < addr_len; i++) {
@ -93,18 +206,66 @@ void _print_addr(uint8_t *addr, size_t addr_len)
printf("%02x", (unsigned)addr[i]);
}
}
static event_t _netdev_ev = { .handler = _netdev_isr_handler };
void recv(netdev_t *dev)
/****** Upper layer implementation ******/
#define IEEE802154_LONG_ADDRESS_LEN_STR_MAX \
(sizeof("00:00:00:00:00:00:00:00"))
static int print_addr(int argc, char **argv)
{
(void)argc;
(void)argv;
char addr_str[IEEE802154_LONG_ADDRESS_LEN_STR_MAX];
printf("%s\n", l2util_addr_to_str(
long_addr.uint8, IEEE802154_LONG_ADDRESS_LEN, addr_str));
return 0;
}
static void _ev_set_rx_handler(event_t *event)
{
(void)event;
mutex_lock(&lock);
ieee802154_set_rx(&submac);
mutex_unlock(&lock);
}
static void submac_tx_done(ieee802154_submac_t *submac, int status,
ieee802154_tx_info_t *info)
{
(void)info;
(void)submac;
switch (status) {
case TX_STATUS_SUCCESS:
puts("Tx complete");
break;
case TX_STATUS_FRAME_PENDING:
puts("Tx complete with pending data");
break;
case TX_STATUS_MEDIUM_BUSY:
puts("Medium Busy");
break;
case TX_STATUS_NO_ACK:
puts("No ACK");
break;
default:
break;
}
/* Schedule the state change. Calling this function directly in the callback
* will return error */
event_post(EVENT_PRIO_HIGHEST, &ev_set_rx);
}
static void submac_rx_done(ieee802154_submac_t *submac)
{
uint8_t src[IEEE802154_LONG_ADDRESS_LEN], dst[IEEE802154_LONG_ADDRESS_LEN];
int data_len;
size_t mhr_len, src_len, dst_len;
netdev_ieee802154_rx_info_t rx_info;
le_uint16_t src_pan, dst_pan;
ieee802154_rx_info_t rx_info;
putchar('\n');
data_len = dev->driver->recv(dev, buffer, sizeof(buffer), &rx_info);
data_len = ieee802154_read_frame(submac, buffer, sizeof(buffer), &rx_info);
if (data_len < 0) {
puts("Couldn't read frame");
return;
@ -186,83 +347,11 @@ void recv(netdev_t *dev)
}
printf("\n");
printf("RSSI: %i, LQI: %u\n\n", rx_info.rssi, rx_info.lqi);
/* Schedule the state change. Calling this function directly in the callback
* will return error */
event_post(EVENT_PRIO_HIGHEST, &ev_set_rx);
}
static void _event_cb(netdev_t *dev, netdev_event_t event)
{
(void)dev;
if (event == NETDEV_EVENT_ISR) {
event_post(EVENT_PRIO_HIGHEST, &_netdev_ev);
}
else {
switch (event) {
case NETDEV_EVENT_RX_COMPLETE:
{
recv(dev);
return;
}
case NETDEV_EVENT_TX_COMPLETE:
puts("Tx complete");
break;
case NETDEV_EVENT_TX_COMPLETE_DATA_PENDING:
puts("Tx complete with pending data");
break;
case NETDEV_EVENT_TX_MEDIUM_BUSY:
puts("Medium Busy");
break;
case NETDEV_EVENT_TX_NOACK:
puts("No ACK");
break;
default:
assert(false);
}
mutex_unlock(&lock);
}
}
struct _reg_container {
int count;
};
static ieee802154_dev_t *_reg_callback(ieee802154_dev_type_t type, void *opaque)
{
struct _reg_container *reg = opaque;
printf("Trying to register ");
switch(type) {
case IEEE802154_DEV_TYPE_CC2538_RF:
printf("cc2538_rf");
break;
case IEEE802154_DEV_TYPE_NRF802154:
printf("nrf52840");
break;
}
puts(".");
if (reg->count > 0) {
puts("For the moment this test only supports one radio");
return NULL;
}
puts("Success");
return &netdev_submac.submac.dev;
}
static int _init(void)
{
netdev_t *dev = &netdev_submac.dev.netdev;
mutex_init(&lock);
mutex_lock(&lock);
dev->event_callback = _event_cb;
struct _reg_container reg = {0};
netdev_ieee802154_submac_init(&netdev_submac);
ieee802154_hal_test_init_devs(_reg_callback, &reg);
dev->driver->init(dev);
return 0;
}
uint8_t payload[] =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ornare lacinia mi elementum interdum ligula.";
static int send(uint8_t *dst, size_t dst_len,
size_t len)
@ -270,20 +359,20 @@ static int send(uint8_t *dst, size_t dst_len,
uint8_t flags;
uint8_t mhr[IEEE802154_MAX_HDR_LEN];
int mhr_len;
struct send_ctx ctx = {0};
le_uint16_t src_pan, dst_pan;
iolist_t iol_data = {
.iol_base = payload,
.iol_base = (void *)payload,
.iol_len = len,
.iol_next = NULL,
};
flags = IEEE802154_FCF_TYPE_DATA | 0x20;
src_pan = byteorder_btols(byteorder_htons(0x23));
dst_pan = byteorder_btols(byteorder_htons(0x23));
uint8_t src_len = 8;
void *src = &netdev_submac.submac.ext_addr;
flags = IEEE802154_FCF_TYPE_DATA | IEEE802154_FCF_ACK_REQ;
src_pan = byteorder_btols(byteorder_htons(CONFIG_IEEE802154_DEFAULT_PANID));
dst_pan = byteorder_btols(byteorder_htons(CONFIG_IEEE802154_DEFAULT_PANID));
uint8_t src_len = IEEE802154_LONG_ADDRESS_LEN;
void *src = &submac.ext_addr;
/* fill MAC header, seq should be set by device */
if ((mhr_len = ieee802154_set_frame_hdr(mhr, src, src_len,
@ -294,85 +383,23 @@ static int send(uint8_t *dst, size_t dst_len,
return 1;
}
ctx.ev.handler = _send_handler;
ctx.pkt.iol_next = &iol_data;
ctx.pkt.iol_base = mhr;
ctx.pkt.iol_len = mhr_len;
iolist_t pkt;
pkt.iol_next = &iol_data;
pkt.iol_base = mhr;
pkt.iol_len = mhr_len;
event_post(EVENT_PRIO_HIGHEST, &ctx.ev);
mutex_lock(&lock);
int res = ieee802154_send(&submac, &pkt);
mutex_unlock(&lock);
if (res < 0) {
puts("Error: Frame couldn't be sent");
}
return 0;
}
static inline int _dehex(char c, int default_)
static int txtsnd(int argc, char **argv)
{
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;
}
int txtsnd(int argc, char **argv)
{
uint8_t addr[8];
uint8_t addr[IEEE802154_LONG_ADDRESS_LEN];
size_t len;
size_t res;
@ -381,7 +408,7 @@ int txtsnd(int argc, char **argv)
return 1;
}
res = _parse_addr(addr, sizeof(addr), argv[1]);
res = l2util_addr_from_str(argv[1], addr);
if (res == 0) {
puts("Usage: txtsnd <long_addr> <len>");
return 1;
@ -390,11 +417,34 @@ int txtsnd(int argc, char **argv)
return send(addr, res, len);
}
static const shell_command_t shell_commands[] = {
{ "print_addr", "Print IEEE802.15.4 addresses", print_addr },
{ "txtsnd", "Send IEEE 802.15.4 packet", txtsnd },
{ NULL, NULL, NULL }
};
static int _init(void)
{
mutex_init(&lock);
submac.cb = &_cb;
/* Set the Event Notification */
submac.dev.cb = _hal_radio_cb;
ack_timer.callback = _ack_timeout;
ack_timer.arg = NULL;
luid_base(&long_addr, sizeof(long_addr));
eui64_set_local(&long_addr);
eui64_clear_group(&long_addr);
eui_short_from_eui64(&long_addr, &short_addr);
struct _reg_container reg = { 0 };
ieee802154_hal_test_init_devs(_reg_callback, &reg);
int res = ieee802154_submac_init(&submac, &short_addr, &long_addr);
if (res < 0) {
return res;
}
return 0;
}
int main(void)
{