Skip to main content
Associate II
May 18, 2026
Question

STM32WL33CC1 MRSUBG stop receiving

void HAL_MRSubG_IRQ_Callback(void) {
 uint32_t irq = __HAL_MRSUBG_GET_RFSEQ_IRQ_STATUS();
 if (irq & MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_OK_F) {
 last_rx = HAL_GetTick();
 HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET);
 if (HAL_MRSubG_GetBytesOfTransaction() <=
 ring_buffer_u8_free(&radio_ring_buffer) &&
 radio_packet_fifo_free(&radio_packet_fifo) != 0) {
 for (uint8_t i = 0; i < HAL_MRSubG_GetBytesOfTransaction(); i++) {
 ring_buffer_u8_write(&radio_ring_buffer, radio_rx_buf[i]);
 }
 radio_packet_t radio_packet = {
 .len = HAL_MRSubG_GetBytesOfTransaction(),
 };
 radio_packet_fifo_write(&radio_packet_fifo, radio_packet);
 }
 __HAL_MRSUBG_STROBE_CMD(CMD_RX);
 __HAL_MRSUBG_CLEAR_RFSEQ_IRQ_FLAG(
 MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_OK_F);
 }
 if (irq & MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_TIMEOUT_F) {
 __HAL_MRSUBG_STROBE_CMD(CMD_RX);
 __HAL_MRSUBG_CLEAR_RFSEQ_IRQ_FLAG(
 MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_TIMEOUT_F);
 }
 if (irq % MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_CRC_ERROR_F) {
 __HAL_MRSUBG_STROBE_CMD(CMD_RX);
 __HAL_MRSUBG_CLEAR_RFSEQ_IRQ_FLAG(
 MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_CRC_ERROR_F);
 }
}

This is my interrupt handling code. Everything initially works but after some time the radio just stops receiving the packets. The transmitter is not at fault as resetting the receiver instantly fixes the issue. Checking the radio fsm in the main function shows the state as RX (0x10) and there are no other errors reported anywhere. 

11 replies

ST Technical Moderator
May 18, 2026

Hello Tobias3,

This issue is known. An errata sheet entry is planned. A frequency offset can occur in the receiver when it enters the RX state. This issue can also occur at the transmitter side when entering the TX state. The frequency offset prevents the radio from receiving packets at the expected frequency.

Using RX_TIMEOUT is an acceptable workaround because it allows the radio to exit RX mode and re-enter. Does this recover communication? I assume that it does.

Best regards,
Filippo

 

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
Tobias3Author
Associate II
May 18, 2026

Which microcontrollers are affected by this?

ST Technical Moderator
May 18, 2026

Hi Tobias3,

 

the STM32WL3x family.

 

BR,
Filippo

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
Tobias3Author
Associate II
May 18, 2026

I'm understanding you correctly sending and receiving a packet from any current microcontroller from the STM32WL3x family may randomly fail and there is no workaround other than sending/receiving the packet again?

ST Technical Moderator
May 18, 2026

Hi Tobias3,

no, this one you are talking about is one workaround, I would say the easiest one to implement. 


Another workaround will be explained in the next Errata Sheet document. This is preventing the frequency offset issue at RX/TX entrance so the random issue will not happen anymore.

BR,
Filippo

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
Tobias3Author
Associate II
May 18, 2026

And would you mind sharing that workaround here? Or is there a set release date for when the workaround will be released? We have a finished product and just discovered this and would really like to avoid a redesign using another microcontroller.

CZamb.2
Associate II
October 7, 2026

Hello

 

errata are still at the march release, is there any news about this issue? this is something that stops our products to work, so pretty urgent to be sovled.

EDIT: I’ve seen that the LL_MRSubG_StrobeCommand has changed and that it has some registries writing that looks like a workaround applied, but I’ve already tried to import that lines into my code and they don’t fix the issue.

 

thank you

Cristiano

 

ST Technical Moderator
October 7, 2026

Hello CZamb.2,

the errata sheet for STM32WL3CC is still ongoing, but you can refer to the STM32WL3R errata sheet that has been already published and contains the same entry: STM32WL3RK8 and STM32WL3RKB device errata - Errata sheet


The workaround in the SDK has been validated before the release.

BR,
Filippo

 

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
CZamb.2
Associate II
October 7, 2026

Hello Filippo and thank you for the reply.

 

I’ve checked the errata and the workaround, put it in my code, the problem is not solved. Does the workaround work for all the silicon release or should I check my chip is recent enought?

What we are doing is a fairly simple test:

 

  • one board (proprietary) is just sending simple packet with 8bytes preamble, 4 bytes SW, datarate 30kbit, fdev 10khz
  • other 5 boards are just starting an RX with 10s timeout with this implementation:
    void RadioPerformRX(uint32_t timeoutAT) {
    if (MR_SUBG_GLOB_STATUS->RADIO_FSM_INFO == STATE_IDLE) {
    MR_SUBG_GLOB_DYNAMIC->RX_TIMER = MR_SUBG_GLOB_DYNAMIC_RX_TIMER_RX_SQI_TIMEOUT_MASK | (timeoutAT); // Set the RX_TIMEOUT with tick = 1,95uSec
    MODIFY_REG_FIELD(MR_SUBG_RADIO->AGC2_CTRL, MR_SUBG_RADIO_AGC2_CTRL_AGC_MEAS_TIME, 3); // Speedup the AGC measure time
    WRITE_REG(MR_SUBG_GLOB_STATIC->DATABUFFER0_PTR, (uint32_t )&rxBuf[activeDataBuffer]);/* Set the pointer to the data buffer */
    WRITE_REG(MR_SUBG_GLOB_STATIC->DATABUFFER1_PTR, (uint32_t )&rxBuf[activeDataBuffer]);/* Set the pointer to the data buffer */
    MODIFY_REG_FIELD(MR_SUBG_GLOB_DYNAMIC->PCKTLEN_CONFIG, MR_SUBG_GLOB_DYNAMIC_PCKTLEN_CONFIG_PCKTLEN, MAX_RX_PACKET_SIZE); //Max length of the packet to get auto RX-Stop

    // STM WORKAROUND
    volatile uint32_t __mrsubg_delay;
    uint32_t xCommandCode = CMD_RX;
    uint32_t command_reg_backup = READ_REG(MR_SUBG_GLOB_DYNAMIC->COMMAND);
    WRITE_REG(MR_SUBG_GLOB_DYNAMIC->COMMAND, (command_reg_backup & MR_SUBG_GLOB_DYNAMIC_COMMAND_BACK2LOCKON) | MR_SUBG_GLOB_DYNAMIC_COMMAND_BACK2ACTIVE | CMD_NOP);
    WRITE_REG(MRSUBG_RADIO_SYNTH0_ANA_ENG_REG, 0x87U);
    WRITE_REG(MR_SUBG_GLOB_DYNAMIC->COMMAND, (command_reg_backup & ~MR_SUBG_GLOB_DYNAMIC_COMMAND_COMMAND_ID) | xCommandCode);
    for (__mrsubg_delay = 0U; __mrsubg_delay < 3U; __mrsubg_delay++) {
    __NOP();
    }
    WRITE_REG(MRSUBG_RADIO_SYNTH0_ANA_ENG_REG, 0x07U);
    // END


    // PREEVIOUS LINE
    // MODIFY_REG_FIELD(MR_SUBG_GLOB_DYNAMIC->COMMAND, MR_SUBG_GLOB_DYNAMIC_COMMAND_COMMAND_ID, CMD_RX);
    do {
    } while (MR_SUBG_GLOB_STATUS->RADIO_FSM_INFO != STATE_RX);
    }
    }

the function is called inside a while(1) that just restarts the RX when a packet or a TO wakes up from a __WFE();

what we see: the system works correctly for thousands of communications, then it stops for 10 secs, then it starts again and so on and so on. This behaviour is totally compatible to what is indicated in the errata with the PLL problem, but for some reason the workaround does not solve it.

The problem does not appear with the same frequency in all the boards..does this tell you something?

thank you
Carlo

ST Technical Moderator
October 7, 2026

Hi CZamb.2,

can you clarify what you mean with: “it stops for 10 secs, then it starts again and so on and so on.”

The issue described in the errata results in a wrong center frequency, so, unless there is a RX TIMEOUT set, the radio stays in RX state indefinitely, so it never restarts. While, if your radio misses one or a few packets but after a while is receiving again, it is not the PLL issue.

BR,
Filippo

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
CZamb.2
Associate II
October 9, 2026

Hello Filippo

the 5 receiver boards are in RX with a timeout of 10s. As I wrote, the RadioPerformRX(10000000) is called inside a while(1) so it is issued every time a com is received or a TO is reached:

 

while(1) {
RadioPerformRX(10000000);
_WFI();
PRINT_IRQ_FLAGS;
PRINT_PACKET;
CLEAR_IRQ_FLAGS;
}

The TX board is sending a packet every 40ms, and we correctly see the debug outputs going for thousands of communications. Then, suddently, the receiver stops working and it does not receive any packet for 10s, until a TO is reached and an RX is restared. This erally looks like the bug that work around is supposed to solve.

 

in the errata is written that the correct sequence is:

  • reset CMOS
  • strobe command
  • wait 3xNOPs
  • release CMOS reset

but in the SDK we found:

  • reset CMOS
  • strobe command
  • wait a for cycle from 0 to 2 with a NOP inside
  • release CMOS

the for actually waits much more than tre three NOPs declared. That seems to suggest that the workaround just wants a time delay between tje strobe and the release of reset, but this time actually depends on CPU clock. 

I’ve modified ST workaround and possibly found a solution, doing tests on it right now, but the work around as it is, even if validated, is actually not working in our case.

 

Regards

Carlo