diff --git a/drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c b/drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c index baa1efd509..d5692a5f57 100644 --- a/drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c +++ b/drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c @@ -151,6 +151,9 @@ void ieee802154_submac_ack_timer_cancel(ieee802154_submac_t *submac) submac); xtimer_remove(&netdev_submac->ack_timer); + /* Prevent a race condition between the RX_DONE event and the ACK timeout */ + netdev_submac->isr_flags &= ~NETDEV_SUBMAC_FLAGS_ACK_TIMEOUT; + } static int _send(netdev_t *netdev, const iolist_t *pkt) diff --git a/sys/include/net/ieee802154/submac.h b/sys/include/net/ieee802154/submac.h index 49e26e2dc7..5a1baa1925 100644 --- a/sys/include/net/ieee802154/submac.h +++ b/sys/include/net/ieee802154/submac.h @@ -544,7 +544,9 @@ ieee802154_fsm_state_t ieee802154_submac_process_ev(ieee802154_submac_t *submac, * * This function must be called when the ACK timeout timer fires. * - * @note this function should not be called inside ISR context. + * @note this function should not be called inside ISR context and MUST NOT + * be invoked if @ref ieee802154_submac_ack_timer_cancel was already + * called. * * @param[in] submac pointer to the SubMAC descriptor */ diff --git a/tests/ieee802154_submac/main.c b/tests/ieee802154_submac/main.c index 0e25a04279..0de03bd8dd 100644 --- a/tests/ieee802154_submac/main.c +++ b/tests/ieee802154_submac/main.c @@ -139,6 +139,10 @@ void ieee802154_submac_ack_timer_cancel(ieee802154_submac_t *submac) { (void)submac; ztimer_remove(ZTIMER_USEC, &ack_timer); + /* Avoid race conditions between RX_DONE and ACK_TIMEOUT */ + if (ev_ack_timeout.list_node.next) { + event_cancel(EVENT_PRIO_HIGHEST, &ev_ack_timeout); + } } static void _ack_timeout(void *arg)