diff --git a/sys/include/net/gnrc/lwmac/lwmac.h b/sys/include/net/gnrc/lwmac/lwmac.h index 1a5583db60..eaf1af5803 100644 --- a/sys/include/net/gnrc/lwmac/lwmac.h +++ b/sys/include/net/gnrc/lwmac/lwmac.h @@ -316,6 +316,19 @@ extern "C" { #endif /** @} */ +/** +* @brief Maximum preamble attempts before re-initialize radio in LWMAC. +* +* After a long period of run time, a radio may be in wrong condition which needs to be +* re-calibrated. This is indicated by having a series of continuous preamble failure (no WA) +* in LWMAC. In case we have @ref CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD number of preamble +* failure, then we re-initialize the radio, trying to re-calibrate the radio for bringing it +* back to normal condition. +*/ +#ifndef CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD +#define CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD (10U) +#endif + /** * @brief Creates an IEEE 802.15.4 LWMAC network interface * diff --git a/sys/include/net/gnrc/mac/types.h b/sys/include/net/gnrc/mac/types.h index 433d85b197..6f13ba7b19 100644 --- a/sys/include/net/gnrc/mac/types.h +++ b/sys/include/net/gnrc/mac/types.h @@ -197,6 +197,7 @@ typedef struct { uint8_t bcast_seqnr; /**< Sequence number for broadcast data to filter at receiver */ uint8_t tx_burst_count; /**< Count how many consecutive packets have been transmitted */ uint8_t tx_retry_count; /**< Count how many Tx-retrials have been executed before packet drop */ + uint8_t preamble_fail_counts; /**< Preamble trial failure count. */ #endif #ifdef MODULE_GNRC_GOMACH diff --git a/sys/net/gnrc/link_layer/lwmac/Kconfig b/sys/net/gnrc/link_layer/lwmac/Kconfig index e7cd14eccb..466bcec88a 100644 --- a/sys/net/gnrc/link_layer/lwmac/Kconfig +++ b/sys/net/gnrc/link_layer/lwmac/Kconfig @@ -138,5 +138,16 @@ config GNRC_LWMAC_TIMEOUT_COUNT help Configure 'CONFIG_GNRC_LWMAC_TIMEOUT_COUNT', the default value for the maximum number of parallel timeouts in LWMAC. +config GNRC_LWMAC_RADIO_REINIT_THRESHOLD + int "Maximum preamble attempts before re-initialize radio" + default 10 + help + Configure 'CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD', the maximum preamble + attempts before re-initialize radio. After a long period of run time, a radio + may be in wrong condition which needs to be re-calibrated. This is indicated + by having a series of continuous preamble failure (no WA) in LWMAC. In case + we have @ref GNRC_LWMAC_RADIO_REINI_THRESHOLD number of preamble failure, + then we re-initialize the radio, trying to re-calibrate the radio for bringing + it back to normal condition. endif # KCONFIG_MODULE_GNRC_LWMAC diff --git a/sys/net/gnrc/link_layer/lwmac/lwmac.c b/sys/net/gnrc/link_layer/lwmac/lwmac.c index 26b13bd503..e8a63aac55 100644 --- a/sys/net/gnrc/link_layer/lwmac/lwmac.c +++ b/sys/net/gnrc/link_layer/lwmac/lwmac.c @@ -83,6 +83,38 @@ int gnrc_netif_lwmac_create(gnrc_netif_t *netif, char *stack, int stacksize, &lwmac_ops); } +static void lwmac_reinit_radio(gnrc_netif_t *netif) +{ + /* Initialize low-level driver. */ + netif->dev->driver->init(netif->dev); + + /* Set MAC address length. */ + uint16_t src_len = netif->l2addr_len; + netif->dev->driver->set(netif->dev, NETOPT_SRC_LEN, &src_len, sizeof(src_len)); + + /* Set the MAC address of the device. */ + if (netif->l2addr_len == IEEE802154_LONG_ADDRESS_LEN) { + netif->dev->driver->set(netif->dev, + NETOPT_ADDRESS_LONG, + netif->l2addr, + sizeof(netif->l2addr)); + } + else { + netif->dev->driver->set(netif->dev, + NETOPT_ADDR_LEN, + netif->l2addr, + sizeof(netif->l2addr)); + } + + /* Enable RX-start and TX-started and TX-END interrupts. */ + netopt_enable_t enable = NETOPT_ENABLE; + netif->dev->driver->set(netif->dev, NETOPT_RX_START_IRQ, &enable, sizeof(enable)); + netif->dev->driver->set(netif->dev, NETOPT_RX_END_IRQ, &enable, sizeof(enable)); + netif->dev->driver->set(netif->dev, NETOPT_TX_START_IRQ, &enable, sizeof(enable)); + netif->dev->driver->set(netif->dev, NETOPT_TX_END_IRQ, &enable, sizeof(enable)); + +} + static gnrc_pktsnip_t *_make_netif_hdr(uint8_t *mhr) { gnrc_pktsnip_t *snip; @@ -328,6 +360,7 @@ void lwmac_set_state(gnrc_netif_t *netif, gnrc_lwmac_state_t newstate) case GNRC_LWMAC_START: { rtt_handler(GNRC_LWMAC_EVENT_RTT_START, netif); lwmac_set_state(netif, GNRC_LWMAC_LISTENING); + netif->mac.tx.preamble_fail_counts = 0; break; } case GNRC_LWMAC_STOP: { @@ -576,6 +609,13 @@ static void _tx_management(gnrc_netif_t *netif) gnrc_lwmac_set_tx_continue(netif, false); gnrc_lwmac_set_quit_tx(netif, true); /* TX packet will be dropped, no automatic resending here. */ + + /* Re-initialize the radio when needed. */ + if (netif->mac.tx.preamble_fail_counts >= CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD) { + netif->mac.tx.preamble_fail_counts = 0; + LOG_INFO("[LWMAC] Re-initialize radio."); + lwmac_reinit_radio(netif); + } /* Intentionally falls through */ case GNRC_LWMAC_TX_STATE_SUCCESSFUL: diff --git a/sys/net/gnrc/link_layer/lwmac/tx_state_machine.c b/sys/net/gnrc/link_layer/lwmac/tx_state_machine.c index 32d61b0169..1209f92301 100644 --- a/sys/net/gnrc/link_layer/lwmac/tx_state_machine.c +++ b/sys/net/gnrc/link_layer/lwmac/tx_state_machine.c @@ -685,6 +685,7 @@ static bool _lwmac_tx_update(gnrc_netif_t *netif) LOG_WARNING("WARNING: [LWMAC-tx] No response from destination\n"); netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; reschedule = true; + netif->mac.tx.preamble_fail_counts++; break; } @@ -735,6 +736,7 @@ static bool _lwmac_tx_update(gnrc_netif_t *netif) if (tx_info & GNRC_LWMAC_TX_SUCCESS) { netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SEND_DATA; reschedule = true; + netif->mac.tx.preamble_fail_counts = 0; break; } else {