cancel
Showing results for 
Search instead for 
Did you mean: 

B-WL5M-SUBG1 LoRa HAL Setup and/or TX Failing

zbaltzer
Associate

Hello,

I'm using the B-WL5M-SUB1G, using Visual Studio as my programming environment, attempting to get LoRa TX working without using the middleware.

The code is below. The project serial output is below the code block. Referencing RM0453 Rev 6 (STM32WL5x reference manual), on page 204, there is the "Basic sequence for LoRa... transmit operation", and I believe I'm following all the steps, yet, get a command failure option when putting the radio into TX mode. Here are the steps I'm performing:

  1. Put radio into sleep
  2. Put radio into standby
  3. Get radio status - The return is 0xA2 - suggesting it is in RC13 standby mode
  4. Put the the radio into LoRa mode using RADIO_SET_PACKETTYPE
  5. Get the packet type - here is my first misunderstanding, isn't RADIO_GET_PACKETTYPE supposed to return the status and the packet type? The return is 0x01 0x00, which at face value suggests the status byte is 0x01 and the packet type is FSK Generic? Am I initializing something wrong already?
  6. Set the radio parameters with RADIO_SET_PACKETPARAMS 
  7. Set the sync bytes
  8. Set buffer pointers to 0 with RADIO_SET_BUFFERBASEADDRESS
  9. Verify 0 with ReadRegister (this does seem to work correctly)
  10. Write 32 bytes to the buffer, with WriteBuffer, the data is just a counter from 0 to 31.
  11. Set frequency to 915MHz
  12. Set PAConfig to +14dBm in LP Mode
  13. Set 1.7ms ramp for the transmitter
  14. Set SF to 9, BW to 125kHz, CR to 4/8, and turn off low data rate optimization
  15. Attempt to set the DIO lines - however this is of importance later if I can get TX working
  16. Then finally, set it to TX with timeout disabled

The radio immediately returns with the radio in RC13 standby mode, and a CmdStatus of 0x5, which is "command execution failure"

What am I missing? Are there any true examples anywhere of setting up LoRa sending/receiving while only using the HAL without middleware?

Some extra details:

This is a single core example, only using the M4 core, with sysclk being set to MSI 16MHz, all APB divisors set to 1, and the SUBGHZ prescaler set to 8.

 

 

 

//Used for printf
int _write(int file, char *data, int len)
{
    UNUSED(file);
    HAL_UART_Transmit(&huart2, (uint8_t*)data, len, HAL_MAX_DELAY);
    return len;
}

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C2_Init();
  MX_SPI2_Init();
  MX_USART2_UART_Init();
  MX_ADC_Init();
  MX_AES_Init();
  MX_CRC_Init();
  //MX_RNG_Init();
  MX_RTC_Init();
  MX_SUBGHZ_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  
  #define RADIO_MODE_BITFIELD          0x70
  #define RADIO_STATUS_BITFIELD        0x0E
  while (1)
  {
    HAL_Delay(500);
    printf("Toggle 1\r\n");
    HAL_GPIO_TogglePin(GPIOB, LED1_Pin);
    
    HAL_Delay(500);
    printf("Toggle 2\r\n");
    HAL_GPIO_TogglePin(GPIOB, LED2_Pin);
    
    HAL_Delay(500);
    printf("Toggle 3\r\n");
    HAL_GPIO_TogglePin(GPIOB, LED3_Pin);

    uint8_t radioParam, radioResult;
    uint8_t radioCmd[8] = {0};
    uint8_t dataToSend[100] = {0};
    for(int i = 0; i<100; i++){
      dataToSend[i] = i;
    }

    radioParam = 0; 
    if(HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_SLEEP, &radioParam, 1) != HAL_OK){
      printf("Sleep Failed\r\n");
    }

    radioParam = 0; //RC13 used
    if(HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_STANDBY, &radioParam, 1) != HAL_OK){
      printf("Standby Failed\r\n");
    }

    if(HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1) != HAL_OK){
      printf("Get Status Failed\r\n");
    }
    printf("Status is: 0x%02x\r\n", radioResult);

    radioParam = 1; //lora mode
    HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_PACKETTYPE, &radioParam, 1);

    //verify lora mode
    HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_PACKETTYPE, radioCmd, 2);

    printf("Should be 1 for lora mode: 0x%02x 0x%02x\r\n", radioCmd[0], radioCmd[1]);

    radioCmd[0] = 0x00;
    radioCmd[1] = 0x0C; //preamble = 12
    radioCmd[2] = 0; //explicit header
    radioCmd[3] = 0; //payload length, 0 for explicit header?
    radioCmd[4] = 0; //Disable CRC
    radioCmd[5] = 0; //Disable IQ inversion
    HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_PACKETPARAMS, radioCmd, 6);

    //Set syn word to "W"
    HAL_SUBGHZ_WriteRegister(&hsubghz, 0x740, 0);
    HAL_SUBGHZ_WriteRegister(&hsubghz, 0x741, 0x57);

    //Verify sync word
    HAL_SUBGHZ_ReadRegister(&hsubghz, 0x740, radioCmd);
    printf("Sync word MSB: 0x%02x\r\n", radioCmd[0]);

    HAL_SUBGHZ_ReadRegister(&hsubghz, 0x741, radioCmd);
    printf("Sync word MSB: 0x%02x\r\n", radioCmd[0]);

    radioCmd[0] = 0;
    radioCmd[1] = 0;
    HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_BUFFERBASEADDRESS, radioCmd, 2);

    //Should be fulfilled in reg 0x802 and 0x803 (tx and rx respective)
    HAL_SUBGHZ_ReadRegister(&hsubghz, 0x802, radioCmd);
    printf("TX Pointer: 0x%02x\r\n", radioCmd[0]);

    HAL_SUBGHZ_ReadRegister(&hsubghz, 0x803, radioCmd);
    printf("RX Pointer: 0x%02x\r\n", radioCmd[0]);

    //Write data
    HAL_SUBGHZ_WriteBuffer(&hsubghz, 0, dataToSend, 32);

    //Set Frequency to 915MHz
    uint32_t rf915 = 0x39300000;
    radioCmd[0] = (rf915 >> 24) & 0xFF;
    radioCmd[1] = (rf915 >> 16) & 0xFF;
    radioCmd[2] = (rf915 >> 8) & 0xFF;
    radioCmd[3] = (rf915) & 0xFF;
    HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_RFFREQUENCY, radioCmd, 4);
    
    //To Transmit at +14dBm in LP Mode
    //PaDutyCycle = 0x4
    //HpMax = 0x0
    //PASel = 1
    //Power = 0xE
    radioCmd[0] = 0x4;
    radioCmd[1] = 0x0;
    radioCmd[2] = 0x1;
    radioCmd[3] = 0x1;
    HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_PACONFIG, radioCmd, 4);

    radioCmd[0] = 0xE;
    radioCmd[1] = 0x06; //1.7ms ramp
    HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_TXPARAMS, radioCmd, 2);

    radioCmd[0] = 0x9; //SF
    radioCmd[1] = 0x4; //BW
    radioCmd[2] = 0x4; //CR = 4/8
    radioCmd[3] = 0x0; //low data optimize off
    HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_MODULATIONPARAMS, radioCmd, 4);

    //Enable bit 0 on line 0(txdone) and bit 9 on line 1(tx timeout)
    radioCmd[0] = 0;
    radioCmd[1] = 0x1;
    radioCmd[2] = 0x2;
    radioCmd[3] = 0;
    for(int i = 4; i<8; i++){
      radioCmd[i] = 0;
    }
    HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_CFG_DIOIRQ, radioCmd, 8);

    if(HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1) != HAL_OK){
      printf("Get Status Failed\r\n");
    }

    HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1);
    uint8_t result = (radioResult & RADIO_MODE_BITFIELD) >> 4; 
    uint8_t status = (radioResult & RADIO_STATUS_BITFIELD) >> 1;
    printf("Status is: 0x%02x 0x%02x\r\n", result, status);

    for(int i = 0; i<8; i++){
      radioCmd[i] = 0;
    }
    //Disable timeout, transmit
    HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_TX, radioCmd, 3);
    uint32_t startTime = HAL_GetTick();

    HAL_Delay(100);
    HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1);
    
    printf("%lums have elapsed, status: 0x%02x\r\n", HAL_GetTick() - startTime, radioResult);
    if((radioResult & (1 << 6)) & (radioResult & (1 << 4)) ){
      printf("Probably in TX Mode\r\n");
    }
    if((radioResult & (1 << 5)) ){
      printf("Probably in Standby Mode\r\n");
    }
    if(radioResult == 0xAA){
      printf("error...\r\n");
      HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1);
      uint8_t result = (radioResult & RADIO_MODE_BITFIELD) >> 4; 
      uint8_t status = (radioResult & RADIO_STATUS_BITFIELD) >> 1;
      printf("Status is: 0x%02x 0x%02x\r\n", result, status);

      for(int i = 0; i<8; i++){
        radioCmd[i] = 0;
      }
      HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_ERROR, radioCmd, 4);
      printf("Error is: 0x%02x 0x%02x 0x%02x 0x%02x\r\n", radioCmd[0], radioCmd[1], radioCmd[2], radioCmd[3]);
      while(1);
    }

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 

 

And the output:

Toggle 1
Toggle 2
Toggle 3
Status is: 0xa2
Should be 1 for lora mode: 0x01 0x00
Sync word MSB: 0x00
Sync word MSB: 0x57
TX Pointer: 0x00
RX Pointer: 0x00
Status is: 0x02 0x01
101ms have elapsed, status: 0xaa
Probably in Standby Mode
error...
Status is: 0x02 0x05
Error is: 0x00 0x20 0x0a 0x00

 

1 REPLY 1
STTwo-32
ST Employee

Hello @zbaltzer 

The only example available for transmission based only on the hal without midleware is the SUBGHZ_Tx_Mode so you can use it as a reference. There is also this tutorial that is not tested on my side but it may be really helpful.

Best Regards.

STTwo-32

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.