You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2026/10/19 21:49:15 UTC
(nuttx) 15/17: arch/arm/nrf52: do not start a transmission during the ACK TX
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 <ra...@railab.me>
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 <ra...@railab.me>
---
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)