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 daa5b75e65227221e11d7052ac08ed2b3dc55a38 Author: raiden00pl <[email protected]> AuthorDate: Mon Oct 19 11:53:44 2026 +0200 arch/arm/nrf52: ignore a stale IEEE 802.15.4 timer interrupt The timer is stopped from the radio interrupt and from the radio work, for example when the ACK arrives before the ACK wait timeout. nrf52_radioi8_tim_stop() did not clear the compare event, and the timer interrupt handler ran the handler of the current channel whenever it was called. An interrupt raised before the stop reached the default case and asserted; on the nRF5340 net core this stopped a MAC test. Clear the event when stopping, and run the channel handler from the interrupt only if a timer is set and its compare event fired. Assisted-by: Claude Code Signed-off-by: raiden00pl <[email protected]> --- arch/arm/src/nrf52/nrf52_ieee802154_tim.c | 52 +++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_tim.c b/arch/arm/src/nrf52/nrf52_ieee802154_tim.c index a5b6851fed2..71f2c5cf580 100644 --- a/arch/arm/src/nrf52/nrf52_ieee802154_tim.c +++ b/arch/arm/src/nrf52/nrf52_ieee802154_tim.c @@ -71,6 +71,7 @@ static void nrf52_radioi8_tim_reset(struct nrf52_radioi8_dev_s *dev); /* Interrupts logic */ +static void nrf52_radioi8_tim_expire(struct nrf52_radioi8_dev_s *dev); static int nrf52_radioi8_isr_tim(int irq, void *context, void *arg); /**************************************************************************** @@ -154,7 +155,7 @@ static int nrf52_radioi8_tim(struct nrf52_radioi8_dev_s *dev, uint8_t chan, { /* Call handler now */ - nrf52_radioi8_isr_tim(0, NULL, dev); + nrf52_radioi8_tim_expire(dev); } leave_critical_section(flags); @@ -173,7 +174,14 @@ static int nrf52_radioi8_tim(struct nrf52_radioi8_dev_s *dev, uint8_t chan, static void nrf52_radioi8_tim_stop(struct nrf52_radioi8_dev_s *dev) { NRF52_TIM_STOP(dev->tim->tim); - NRF52_TIM_DISABLEINT(dev->tim->tim, dev->tim->tim_now); + + /* Clear the event, it may have already been latched */ + + if (dev->tim->tim_pending) + { + NRF52_TIM_DISABLEINT(dev->tim->tim, dev->tim->tim_now); + NRF52_TIM_ACKINT(dev->tim->tim, dev->tim->tim_now); + } /* Reset state */ @@ -205,22 +213,18 @@ static void nrf52_radioi8_tim_reset(struct nrf52_radioi8_dev_s *dev) } /**************************************************************************** - * Name: nrf52_radioi8_isr_tim + * Name: nrf52_radioi8_tim_expire * * Description: - * Helper tim interrupt handler. + * Handle the expired timer channel. * ****************************************************************************/ -static int nrf52_radioi8_isr_tim(int irq, void *context, void *arg) +static void nrf52_radioi8_tim_expire(struct nrf52_radioi8_dev_s *dev) { - struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; - struct nrf52_radioi8_tim_s *tim = NULL; + struct nrf52_radioi8_tim_s *tim = dev->tim; irqstate_t flags; - DEBUGASSERT(dev != NULL); - tim = dev->tim; - flags = enter_critical_section(); switch (tim->tim_now) @@ -299,7 +303,35 @@ static int nrf52_radioi8_isr_tim(int irq, void *context, void *arg) tim->tim_now = -1; leave_critical_section(flags); +} +/**************************************************************************** + * Name: nrf52_radioi8_isr_tim + * + * Description: + * Helper tim interrupt handler. + * + ****************************************************************************/ + +static int nrf52_radioi8_isr_tim(int irq, void *context, void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + struct nrf52_radioi8_tim_s *tim = NULL; + irqstate_t flags; + + DEBUGASSERT(dev != NULL); + tim = dev->tim; + + flags = enter_critical_section(); + + /* Ignore an interrupt raised before the timer was stopped or set again */ + + if (tim->tim_pending && NRF52_TIM_CHECKINT(tim->tim, tim->tim_now)) + { + nrf52_radioi8_tim_expire(dev); + } + + leave_critical_section(flags); return OK; }
