cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WL33 Receive Interrupt Stops Firing after Low RSSI signals and doesn't recover

EDeYo.1
Associate II

I'm using a STM32WL33 on 2 separate custom PCBs.  I have one of them being a transmitter only, and I have verified that the transmitter consistently transmits when the keyfob button(s) are pressed (using one of the examples on a Nucleo CC2 board to verify) 

I'm having issues with the receiver ceasing to recover after receiving a low-RSSI signal.  As long as the signal strength is reasonable, the HAL_MRSubG_IRQ_Callback executes, and resumes reception without issue.  If it receives a packet that is of questionable RSSI (either too far away with the keyfob or wrapping the keyfob in aluminum foil to keep my step count down :)   ), the HAL_MRSubG_IRQ_Callback doesn't execute at all once the RSSI is back to the original level, and requires a power cycle to recover.  The main loop continues to operate, it's just that the interrupt ceases to fire!  I have observed the same thing on the Nucleo CC2 PCB as well using the Chat example.  A reboot solves the issue there, as well.

Any insight is appreciated!  In the meantime, I'm going to start debugging some register contents and see if somehow the interrupt is getting disabled.

Thanks!

Below are the relevant code snippets:

  /** Configures the radio parameters
  */
  MRSUBG_RadioInitStruct.lFrequencyBase = 433000000;
  MRSUBG_RadioInitStruct.xModulationSelect = MOD_2FSK;
  MRSUBG_RadioInitStruct.lDatarate = 38400;
  MRSUBG_RadioInitStruct.lFreqDev = 20000;
  MRSUBG_RadioInitStruct.lBandwidth = 100000;
  MRSUBG_RadioInitStruct.dsssExp = 0;
  MRSUBG_RadioInitStruct.outputPower = 14;
  MRSUBG_RadioInitStruct.PADrvMode = PA_DRV_TX_HP;
  HAL_MRSubG_Init(&MRSUBG_RadioInitStruct);

  /** Configures the packet parameters
  */
  MRSUBG_PacketSettingsStruct.PreambleLength = 16;
  MRSUBG_PacketSettingsStruct.PostambleLength = 0;
  MRSUBG_PacketSettingsStruct.SyncLength = 31;
  MRSUBG_PacketSettingsStruct.SyncWord = 0x88888888;
  MRSUBG_PacketSettingsStruct.FixVarLength = VARIABLE;
  MRSUBG_PacketSettingsStruct.PreambleSequence = PRE_SEQ_0101;
  MRSUBG_PacketSettingsStruct.PostambleSequence = POST_SEQ_0101;
  MRSUBG_PacketSettingsStruct.CrcMode = PKT_CRC_MODE_8BITS;
  MRSUBG_PacketSettingsStruct.Coding = CODING_NONE;
  MRSUBG_PacketSettingsStruct.DataWhitening = ENABLE;
  MRSUBG_PacketSettingsStruct.LengthWidth = BYTE_LEN_1;
  MRSUBG_PacketSettingsStruct.SyncPresent = ENABLE;
  HAL_MRSubG_PacketBasicInit(&MRSUBG_PacketSettingsStruct);
  /* USER CODE BEGIN MRSUBG_Init 2 */
void protocol_init(void)
{
	  HAL_MRSubG_PktBasicSetPayloadLength(sizeof(rx_packet_t));
	  __HAL_MRSUBG_SET_RFSEQ_IRQ_ENABLE(MR_SUBG_GLOB_DYNAMIC_RFSEQ_IRQ_ENABLE_RX_OK_E | MR_SUBG_GLOB_DYNAMIC_RFSEQ_IRQ_ENABLE_TX_DONE_E);
	  HAL_NVIC_EnableIRQ(MR_SUBG_IRQn);

	  __HAL_MRSUBG_SET_DATABUFFER0_POINTER((uint32_t)&rx_packet_isr);
	  __HAL_MRSUBG_STROBE_CMD(CMD_RX);
}
void HAL_MRSubG_IRQ_Callback(void){
  uint32_t irq;
  uint8_t *ptr = (uint8_t *)&rx_packet_isr;

  irq = __HAL_MRSUBG_GET_RFSEQ_IRQ_STATUS();

  if (irq & MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_OK_F) {

    /* Clear the IRQ flag */
    __HAL_MRSUBG_CLEAR_RFSEQ_IRQ_FLAG(MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_OK_F);

    uint16_t rxBytes = __HAL_MRSUBG_GET_DATABUFFER_COUNT();


    if(ptr[rxBytes-1] == (uint8_t)HAL_CRC_Calculate(&hcrc, (uint32_t *)&rx_packet_isr, rxBytes-1))
    {
		 printf("RX:\t");
		 for(uint8_t i = 0; i<rxBytes; i++)
		 {
			 printf("%02X ",ptr[i]);
		 }
		 printf("\r\n");

    }
	__HAL_MRSUBG_SET_DATABUFFER0_POINTER((uint32_t)&rx_packet_isr);
	__HAL_MRSUBG_STROBE_CMD(CMD_RX);
  }

	if (irq & MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_TX_DONE_F ) {

	    /* Clear the IRQ flag */
	    __HAL_MRSUBG_CLEAR_RFSEQ_IRQ_FLAG(MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_TX_DONE_F);

	    /* set the tx_done_flag to manage the event in the main() */
	    tx_done_flag = TRUE;
	  }
}

 

3 REPLIES 3
EDeYo.1
Associate II

I can confirm that strobing with the RX command __HAL_MRSUBG_STROBE_CMD(CMD_RX) after a lockup allows the receiver to receive properly.  Reading the MR_SUBG_GLOB_DYNAMIC->COMMAND register immediately prior to resending the CMD_RX strobe still indicates that the device is in receive mode (0x2) in the failed state.  Are there any examples which show how to use the RX timeout function and initialization procedures - assuming this would resolve my issue?

Thanks!

 

 

Trying to isolate the issue and post relevant info as I go.

When the radio fails, I have found that the RADIO_FSM_STATE is back in IDLE instead of RX.  Issuing the RX strobe gets it back to RX and allows further reception.  What would cause the FSM state to drop back to IDLE and what's the best way to prevent this or the best way to handle it properly?

 

void HAL_MRSubG_IRQ_Callback(void){
  uint32_t irq;


  irq = __HAL_MRSUBG_GET_RFSEQ_IRQ_STATUS();

  if (irq & MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_OK_F) {
    /* Clear the IRQ flag */
    __HAL_MRSUBG_CLEAR_RFSEQ_IRQ_FLAG(MR_SUBG_GLOB_STATUS_RFSEQ_IRQ_STATUS_RX_OK_F);
    set_led(green,flash_times,1,100);

    uint16_t rxBytes = __HAL_MRSUBG_GET_DATABUFFER_COUNT();

	__HAL_MRSUBG_SET_DATABUFFER0_POINTER((uint32_t)&rx_data);
	__HAL_MRSUBG_STROBE_CMD(CMD_RX);
  }
}

 while (1)
  {
	  led_handler();
	  if(ms_counter > 5000)
	  {
		  status = MR_SUBG_GLOB_STATUS->RADIO_FSM_INFO;
		  __HAL_MRSUBG_STROBE_CMD(CMD_RX);
		  HAL_Delay(10);
		  printf("OLD:0x%08lX, NEW:0x%08lX\r\n",status, MR_SUBG_GLOB_STATUS->RADIO_FSM_INFO);

		  set_led(blue,flash_times,1,100);
		  ms_counter = 0;


	  }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

 

EDeYo.1
Associate II

Problem solved - if the CRC is enabled in the MRSUBG peripheral setup, a packet with a failed CRC will revert the FSM to IDLE mode and the MRSUBG callback won't be executed for further received packets until the RX_CMD strobe is issued. 

In the MRSUBG Chat example, the CRC is enabled in the peripheral, but the CRC interrupt isn't enabled and the flag is left unchecked in the callback.  In this case, a packet CRC error will leave the peripheral in IDLE mode, unable to receive any more packets until a transmission occurs from the 'locked' device (which strobes the RX_CMD).