This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 67b7fb00c560a51acb1ce8368769544ded1422be Author: raiden00pl <[email protected]> AuthorDate: Mon Oct 19 11:28:38 2026 +0200 arch/arm/nrf52: do not start a transmission during the ACK TX The ACK of a received frame is sent from the interrupt handler. A CSMA transaction polled from the MAC, or a no CSMA transaction that waited for the CSMA transaction, could be set up and triggered while that ACK was on air: norm_setup() overwrote the radio state and a zero backoff restarted the radio. The sender then received an empty frame with a CRC error instead of the ACK and retransmitted, and the replies to fragmented 6LoWPAN datagrams were lost in 15 to 28% of the cases. Start such a transaction when the ACK TX is done, as txdelayed() does. Assisted-by: Claude Code Signed-off-by: raiden00pl <[email protected]> --- arch/arm/src/nrf52/nrf52_ieee802154_priv.h | 1 + arch/arm/src/nrf52/nrf52_ieee802154_radio.c | 49 +++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_priv.h b/arch/arm/src/nrf52/nrf52_ieee802154_priv.h index b61fc59760f..9aadc2598a9 100644 --- a/arch/arm/src/nrf52/nrf52_ieee802154_priv.h +++ b/arch/arm/src/nrf52/nrf52_ieee802154_priv.h @@ -97,6 +97,7 @@ struct nrf52_radioi8_state_s bool txdelayed_busy; /* No CSMA transfer */ bool txdelayed_pending; /* No CSMA transfer waits for CSMA */ + bool csma_pending; /* CSMA transfer waits for ACK TX */ uint32_t txdelayed_delay; /* Delay of the pending no CSMA transfer */ #ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_radio.c b/arch/arm/src/nrf52/nrf52_ieee802154_radio.c index 183ee1d0df5..7412065b4a8 100644 --- a/arch/arm/src/nrf52/nrf52_ieee802154_radio.c +++ b/arch/arm/src/nrf52/nrf52_ieee802154_radio.c @@ -1290,13 +1290,25 @@ static void nrf52_radioi8_rxrestore(struct nrf52_radioi8_dev_s *dev) static void nrf52_radioi8_txpending(struct nrf52_radioi8_dev_s *dev) { + irqstate_t flags; + /* Start the no CSMA transaction that waited for the CSMA transaction */ if (dev->state.txdelayed_pending) { + flags = enter_critical_section(); + dev->state.txdelayed_pending = false; dev->state.txdelayed_busy = true; + /* An ACK TX in progress starts it when done */ + + if (dev->radio->state.state == NRF52_RADIO_STATE_ACKTX) + { + leave_critical_section(flags); + return; + } + nrf52_radioi8_norm_setup(dev, dev->state.txdelayed_desc->frame, false); @@ -1309,12 +1321,15 @@ static void nrf52_radioi8_txpending(struct nrf52_radioi8_dev_s *dev) dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_TXDELAY, dev->state.txdelayed_delay); } + + leave_critical_section(flags); } } void nrf52_radioi8_dopoll_csma(void *arg) { struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + irqstate_t flags; int len = 0; /* Get exclusive access to the driver */ @@ -1325,8 +1340,8 @@ void nrf52_radioi8_dopoll_csma(void *arg) /* If this a CSMA transaction and we have room in the CSMA */ - if (!dev->radio->state.csma_busy && !dev->state.txdelayed_busy && - !dev->state.txdelayed_pending) + if (!dev->radio->state.csma_busy && !dev->state.csma_pending && + !dev->state.txdelayed_busy && !dev->state.txdelayed_pending) { wlinfo("Polling for frame\n"); len = dev->radiocb->poll(dev->radiocb, false, &dev->state.csma_desc); @@ -1335,11 +1350,24 @@ void nrf52_radioi8_dopoll_csma(void *arg) { wlinfo("Frame received. Frame length: %d\n", len); - /* Setup the CSMA transaction */ + flags = enter_critical_section(); + + /* An ACK TX in progress starts the transaction when done */ + + if (dev->radio->state.state == NRF52_RADIO_STATE_ACKTX) + { + dev->state.csma_pending = true; + } + else + { + /* Setup the CSMA transaction */ + + dev->radio->ops->norm_setup(dev, dev->state.csma_desc->frame, + true); + dev->radio->ops->norm_trigger(dev); + } - dev->radio->ops->norm_setup(dev, dev->state.csma_desc->frame, - true); - dev->radio->ops->norm_trigger(dev); + leave_critical_section(flags); } } @@ -2078,6 +2106,15 @@ static void nrf52_radioi8_state_acktx(struct nrf52_radioi8_dev_s *dev) } } + /* Start the CSMA transaction that waited for the ACK TX */ + + else if (dev->state.csma_pending) + { + dev->state.csma_pending = false; + nrf52_radioi8_norm_setup(dev, dev->state.csma_desc->frame, true); + nrf52_radioi8_norm_trigger(dev); + } + /* Restore RX */ else if (dev->radio->state.rxrestore)
