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:
commit
280c756c7a
@ -189,6 +189,7 @@ endif
|
||||
|
||||
ifneq (,$(filter ieee802154_submac,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += random
|
||||
endif
|
||||
|
||||
ifneq (,$(filter l2util,$(USEMODULE)))
|
||||
|
@ -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
|
||||
|
@ -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, ®);
|
||||
|
||||
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, ®);
|
||||
|
||||
int res = ieee802154_submac_init(&submac, &short_addr, &long_addr);
|
||||
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user