You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In the current RIOT version, the address match interrupt is only activated in the _init function in the driver for the AT86RF215 radio module. This interrupt is required so that the callback of the MAC layer is called with RX_STARTED.
drivers/at86rf215/at86rf215_netdev.c 105
static int _init(netdev_t *netdev)
{
...
/* reset device to default values and put it into RX state */
at86rf215_reset_and_cfg(dev);
...
}
The problem with this is, that when the radio wakes up from sleep mode, the configuration is lost. This means that the BBC_IRQM register is completely set to 0 after the module wakes up, resulting in no interrupts being generated. To overcome this, all necessary interrupts are reset in the reset function after wake-up. However, the BB_IRQ_RXAM interrupt is missing.
drivers/at86rf215/at86rf215_getset.c 310
static void _wake_from_sleep(at86rf215_t *dev)
{
...
/* config is lost after SLEEP */
at86rf215_reset(dev);
...
}
In earlier RIOT versions this was not a problem because the address match interrupt could be reactivated with a set function using a net option. This functionality has been removed in the current version, so it is necessary to activate the BB_IRQ_RXAM interrupt in the reset function.
Steps to reproduce the issue
You need at least two microcontrollers (for exmaple a nucleo-f411re) with an at86rf215 connected to it. Now write a script that does the following things: For both nodes the script should put the at86rf215 radio module to sleep and wakes it up directly after. This step is important to reproduce the issue! After that, one of the nodes should periodically send a message to the other node.
The application should look like this:
Makefile
APPLICATION = at86rf215-issue
BOARD ?= nucleo-f411re
RIOTBASE ?= $(CURDIR)/../..
USEMODULE += netdev_default
USEMODULE += auto_init_gnrc_netif
USEMODULE += ztimer
# Include the radio
USEMODULE += at86rf215
USEMODULE += at86rf215_24ghz
# Configure the radio
SPI ?= SPI_DEV(0)
PIN_CS ?= GPIO_PIN(PORT_B, 6)
PIN_IRQ ?= GPIO_PIN(PORT_A, 9)
PIN_RST ?= GPIO_PIN(PORT_C, 7)
ifneq (, $(SPI))
CFLAGS += '-DAT86RF215_PARAM_SPI=$(SPI)'
endif
ifneq (, $(PIN_CS))
CFLAGS += '-DAT86RF215_PARAM_CS=$(PIN_CS)'
endif
ifneq (, $(PIN_IRQ))
CFLAGS += '-DAT86RF215_PARAM_INT=$(PIN_IRQ)'
endif
ifneq (, $(PIN_RST))
CFLAGS += '-DAT86RF215_PARAM_RESET=$(PIN_RST)'
endif
include $(RIOTBASE)/Makefile.include
# Set a custom channel if needed
include $(RIOTMAKE)/default-radio-settings.inc.mk
main.c
#include <stdio.h>
#include <string.h>
#include "board.h"
#include "net/gnrc.h"
#include "net/gnrc/netif.h"
#ifdef tx_node
typedef struct
{
uint8_t arr[106]; // Dummy data
} message_t;
static int l2_send(netif_t *iface, char *str_addr, uint8_t *data, size_t len)
{
/* Only short addr */
size_t addr_len = 2;
gnrc_pktsnip_t *pkt, *hdr;
gnrc_netif_hdr_t *nethdr;
uint8_t flags = 0x00;
uint8_t addr[addr_len];
l2util_addr_from_str(str_addr, addr);
/* Put packet together */
pkt = gnrc_pktbuf_add(NULL, data, len, GNRC_NETTYPE_UNDEF);
if (pkt == NULL)
{
printf("error: packet buffer full\n");
return 1;
}
hdr = gnrc_netif_hdr_build(NULL, 0, addr, addr_len);
if (hdr == NULL)
{
printf("error: packet buffer full\n");
gnrc_pktbuf_release(pkt);
return 1;
}
pkt = gnrc_pkt_prepend(pkt, hdr);
nethdr = (gnrc_netif_hdr_t *)hdr->data;
nethdr->flags = flags;
/* Send */
if (gnrc_netif_send(container_of(iface, gnrc_netif_t, netif), pkt) < 1)
{
printf("error: unable to send\n");
gnrc_pktbuf_release(pkt);
return 1;
}
return 0;
}
#endif
void turn_off_netif(netif_t *netif)
{
int res = -1;
while (res != NETOPT_STATE_SLEEP)
{
netopt_state_t state = NETOPT_STATE_SLEEP;
res = netif_set_opt(netif, NETOPT_STATE, 0, (void *) &state, sizeof(state));
}
}
void turn_on_netif(netif_t *netif)
{
netopt_state_t state = NETOPT_STATE_IDLE;
netif_set_opt(netif, NETOPT_STATE, 0, (void *) &state, sizeof(state));
}
int main(void)
{
netif_t *netif = netif_iter(NULL);
turn_off_netif(netif);
// wait some time
ztimer_sleep(ZTIMER_MSEC, 10);
turn_on_netif(netif);
#ifdef tx_node
// One of the node should send
while(1)
{
message_t msg;
l2_send(netif, "FF:FF", (uint8_t *) &msg, sizeof(msg));
ztimer_sleep(ZTIMER_MSEC, 1000);
}
#endif
return 0;
}
To monitor the behavior use a logic analyzer and add this:
case NETDEV_EVENT_RX_STARTED:
gpio_set(RX_PIN);
ztimer_sleep(ZTIMER_MSEC, 1);
gpio_clear(RX_PIN);
break;
to
sys/net/gnrc/netif/gnrc_netif.c
before the NETDEV_EVENT_RX_COMPLETE case.
Expected results
Thats how it should look like; The RXAM interrupt occurs, if the valid PHR has been received and after the PSDU has been received, the RXFE interrupt occurs.
Actual results
The reason why both interrupts are called one after the other is that the RXAM interrupt does not occur, but the bit is set. When the RXFE interrupt occurs, the RXAM bit is still set.
Description
In the current RIOT version, the address match interrupt is only activated in the _init function in the driver for the AT86RF215 radio module. This interrupt is required so that the callback of the MAC layer is called with RX_STARTED.
The problem with this is, that when the radio wakes up from sleep mode, the configuration is lost. This means that the BBC_IRQM register is completely set to 0 after the module wakes up, resulting in no interrupts being generated. To overcome this, all necessary interrupts are reset in the reset function after wake-up. However, the BB_IRQ_RXAM interrupt is missing.
In earlier RIOT versions this was not a problem because the address match interrupt could be reactivated with a set function using a net option. This functionality has been removed in the current version, so it is necessary to activate the BB_IRQ_RXAM interrupt in the reset function.
Steps to reproduce the issue
You need at least two microcontrollers (for exmaple a nucleo-f411re) with an at86rf215 connected to it. Now write a script that does the following things: For both nodes the script should put the at86rf215 radio module to sleep and wakes it up directly after. This step is important to reproduce the issue! After that, one of the nodes should periodically send a message to the other node.
The application should look like this:
To monitor the behavior use a logic analyzer and add this:
to the following code part:
before line 398. Add this:
to
after line 2085 and add this:
to
before the NETDEV_EVENT_RX_COMPLETE case.
Expected results
Thats how it should look like; The RXAM interrupt occurs, if the valid PHR has been received and after the PSDU has been received, the RXFE interrupt occurs.
Actual results
The reason why both interrupts are called one after the other is that the RXAM interrupt does not occur, but the bit is set. When the RXFE interrupt occurs, the RXAM bit is still set.
Versions
Operating system: Ubuntu 20.04.6 LTS (Focal Fossa)
Build environment:
The text was updated successfully, but these errors were encountered: