0

Recently I started working on the GNSS with STM32, I am very new to STM32 eco-system. I have a IRNSS click from MikroE which has L89H and I am trying to integrate L89H with STM32WL55JC1 controller.

I have implemented the UART receive NMEA messages from the L89H. I have connected TX, RX, 3,3v, GND pins to STM32's RX, TX, 3.3v, and ground. But when I execute the code no NMEA messages are displayed on the serial monitor. I don't know where I am going wring and I would appreciate to have help for me in this situation.

When i plugged the device, I can see the PPS LED is blinking which means I device is receiving the satellite signal.

From the documentation it is mentioned that the default baud rate is 9600. So I am using the default baud rate.

I connect the same IRNSS click to the Clicker 2 STM32 controller, and when I uploaded the example GNSS FW I can see the NMEA messages received by the controller. But the same board is not working when I connected to STM32WL55JC1.

I am using the following code to read and print the NMEA messages in the CUBE IDE:

#include "main.h"
#include "malloc.h"
#include "string.h"
 
 
UART_HandleTypeDef huart1;
 
uint8_t* RX_BUFFER = NULL;
 
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
 
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
 
  while (1)
  {
 
      RX_BUFFER = (uint8_t*)malloc(400 * sizeof(uint8_t));
      HAL_UART_Receive(&huart1,(uint8_t *)RX_BUFFER,350,500);
      HAL_Delay(1000);
      int size = sizeof(RX_BUFFER);
      HAL_UART_Transmit(&huart1,(uint8_t *)RX_BUFFER,size,500);
      HAL_Delay(1000);
  }
 
}
 
 
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
 
  HAL_PWR_EnableBkUpAccess();
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
 
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 24;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
 
  /** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
                              |RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
                              |RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}
 
/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{
 
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
 
 
}
 
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  HAL_GPIO_WritePin(Wake_up_GPIO_Port, Wake_up_Pin, GPIO_PIN_RESET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(Reset_GPIO_Port, Reset_Pin, GPIO_PIN_RESET);
 
  /*Configure GPIO pin : Wake_up_Pin */
  GPIO_InitStruct.Pin = Wake_up_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(Wake_up_GPIO_Port, &GPIO_InitStruct);
 
  /*Configure GPIO pin : Reset_Pin */
  GPIO_InitStruct.Pin = Reset_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(Reset_GPIO_Port, &GPIO_InitStruct);
 
 
}
 
void Error_Handler(void)
{
  __disable_irq();
  while (1)
  {
  }
}
 
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Please let me know if you need any additional information.

Best regards, Pavan Ravuru

1 Answers1

0

Caveat: I'm not too familiar with the STM32 HAL

Some issues ...

  1. You do malloc on each loop iteration. You are leaking memory. Move the malloc above the while
  2. sizeof(RXBUFFER) is incorrect. It is the size of a pointer and not the length of what that pointer points to. So, this is 4 or 8 bytes and not the 400 that you expect.
  3. You're not handling an RX timeout.
  4. 400 bytes [at 9600 baud] is 0.4 seconds worth of data. This produces a relatively large latency that may cause the UART's internal FIFO to overrun. Better to use a much smaller value.
  5. If the UART is receiving GNSS/GPS data, why are you echoing it back to the device? My suspicion is that if the device accepts data [at all], it is to configure it. So, echoing back the GPS data just sends gibberish to the device?
  6. Why are you doing HAL_Delay at all?
  7. No need for so many uint8_t * casts.

Most guides I've looked at recommend using interrupts or DMA (e.g. HAL_UART_Receive_IT or HAL_UART_Receive_DMA.

I found the source code for HAL_UART_Receive: https://www.disca.upv.es/aperles/arm_cortex_m3/llibre/st/STM32F439xx_User_Manual/stm32f4xx__hal__uart_8c_source.html

From it, if you get a timeout, [I think] you can use huart->RxXferCount to determine the actual amount of data transferred.

This is [a bit of a hack] in lieu of using the interrupt or DMA versions.

You may want to implement ring buffers or "sliding" indexes into separate RX and TX buffers.

Again ... Why are you sending the GPS data back to the device? This makes no sense to me. Do you need/have another UART or other device? Is this just sample code and you want to process the GPS data instead?


Here is some refactored code. It is just a guess.

UART_HandleTypeDef huart1;

uint8_t *rx_buffer = NULL;

// NOTE/BUG: this might produce better latency with a much smaller value
#define BUFMAX      400

int
main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();

    rx_buffer = malloc(BUFMAX)
    // check for malloc failure ...

    int actual_rxlen;
    HAL_StatusTypeDef code;

    // expected amount to read
    // NOTES:
    // (1) we may want a smaller amount to reduce latency on the
    //     HAL_UART_Receive call
    int expected_rxlen = BUFMAX;

    while (1) {
        code = HAL_UART_Receive(&huart1, rx_buffer, expected_rxlen, 500);

        // normal transfer
        if (code == HAL_OK)
            actual_rxlen = expected_rxlen;

        // timeout ...
        else
            actual_rxlen = expected_rxlen - huart1.RxXferCount;

// NOTE/BUG: why use huart1 here???
// NOTE/BUG: this has the same timeout potential/issue as the receive above
        if (actual_rxlen > 0)
            HAL_UART_Transmit(&huart1, rx_buffer, actual_rxlen, 500);
    }
}
Craig Estey
  • 30,627
  • 4
  • 24
  • 48