Showing results for 
Search instead for 
Did you mean: 

STM32WL55 SUBGHZ Interrupt enable/disable and race conditions in SubGHz_Phy/HAL

Associate III


I'm having trouble understanding the radio IRQs on STM32WL55. According to the reference manual NVIC section, there is one interrupt line for two interrupt sources (which are ORed together) for the radio:

  1. The 3 IRQs from the Semtech module ORed together, which can be configured using Cfg_DioIrq, via EXTI44
  2. The RFBUSY signal from the radio module via EXTI45

According to the EXTI section, the EXTI44 line is a "Direct" one and the "EXTI45" one is a "Configurable" one. This means the EXTI45 can be enabled/disabled via the EXTI_CnIMR2 and cleared via the EXTI_PR2 register. The EXTI44 signal however can not be masked or cleared via the EXTI's registers, correct?

Additionally, both EXTI44 and EXTI45 can be used to wake-up the CPUs from standby. This can be enabled via the EWRFIRQ/EWRBUSY bits in PWR_CR3 and PWR_C2CR3 registers. However, this wakeup does not cause an interrupt to be called, only a power-on of the CPU, correct? If the CPUs never enter standby mode, the EWRFIRQ/EWRBUSY bits have no effect, correct?

This however contradicts the following comment from the HAL:


#define LL_PWR_RADIO_BUSY_TRIGGER_WU_IT    (PWR_CR3_EWRFBUSY) /*!< Radio busy trigger action: wake-up from low-power mode Standby and interruption sent to the selected CPU. */


When commenting out the following line




In stm32wlxx_hal_subghz.c , the interrupt still happens, indicating the comment is wrong.

This means that the 3 radio IRQs can only be masked in the NVICs registers and via Cfg_DioIrq, correct?

There is also the SUBGHZSPI interrupt, but this is completely independent from this issue. So the complete SubGHZ interrupt structure looks like:

SubGHZ Interrupts.png


I am asking this because I have trouble addressing a race condition within the SubGHz_Phy middleware / HAL which happens in the following scenario:

  1. Start a RF process (Transmit, Receive, CAD)
  2. Start an independent timer via UTIL_TIMER_Start
  3. In the timer callback (which is indirectly called from the main loop, not an interrupt), perform some RF operation, e.g. Radio.Rssi or Radio.Standby.
  4. In rare cases, during the SPI transfer, the RF module signals an interrupt via one of the 3 IRQ lines.
  5. The HAL_SUBGHZ_IRQHandler function attempts to determine the cause of the interrupt via Get_IrqStatus.
  6. Since the SPI peripheral is already in use, HAL_SUBGHZ_ExecGetCmd fails and returns HAL_BUSY.
  7. HAL_SUBGHZ_IRQHandler ignores this error and returns without doing anything.
  8. As the interrupt source was not cleared using Clr_IrqStatus, the interrupt just happens again and again in an endless loop, which causes the application to freeze.

A possible solution would be to disable the radio interrupt in the timer interrupt before attempting to send an SPI command. Doing this via Cfg_DioIrq does not work, as the transfer can still be interrupted by the radio IRQ and cause the endless loop as described.

This means the radio IRQ must be disabled using NVIC_DisableIRQ (SUBGHZ_Radio_IRQn) before doing any RF operation in the timer callback, correct?