cancel
Showing results for 
Search instead for 
Did you mean: 

Alternate blocking and interrupt UART reception

Yaxit
Associate II

Hello, everyone.

I'm working on a project based on an STM32L4 MCU. My project needs to receive some commands asynchronously, to start and stop processing and tune internal parameters. I also need to be able to stream large chunks of data in and out.

I'm using UART5 for this purpose. To handle the asynchronous commands I enabled the interrupt in CubeMX and I user HAL_UART_Receive_IT(). I then use HAL_UART_RxCpltCallback() to execute the commands (this involves interacting with GPIO and SPI) and then call HAL_UART_Receive_IT() again.

This part works pretty well.

In order to receive the large chunks of data, I'm trying to use HAL_UART_Receive() in a blocking mode. Using this approach, however, I am only able to receive the first byte, and the rest is lost. This happens also if I do not ever call HAL_UART_Receive_IT() before.

Do I need to change some configuration before using the blocking mode?

Here my UART configuration.

static void MX_UART5_Init(void)
{
 
  /* USER CODE BEGIN UART5_Init 0 */
 
  /* USER CODE END UART5_Init 0 */
 
  /* USER CODE BEGIN UART5_Init 1 */
 
  /* USER CODE END UART5_Init 1 */
  huart5.Instance = UART5;
  huart5.Init.BaudRate = 2000000;
  huart5.Init.WordLength = UART_WORDLENGTH_8B;
  huart5.Init.StopBits = UART_STOPBITS_1;
  huart5.Init.Parity = UART_PARITY_NONE;
  huart5.Init.Mode = UART_MODE_TX_RX;
  huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart5.Init.OverSampling = UART_OVERSAMPLING_16;
  huart5.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart5.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart5) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN UART5_Init 2 */
 
  /* USER CODE END UART5_Init 2 */
 
}

5 REPLIES 5
TDK
Guru

HAL_UART_Receive should be able to receive more than 1 character at a time.

2000000 is a very fast UART speed. Try reducing it to 115200.

Monitor return values from HAL function to determine if/why they are failing. It's possible your timeout is too small.

What is sending the data to the STM32? Ensure it can actually operate at 2000000 baud.

If you feel a post has answered your question, please click "Accept as Solution".
Yaxit
Associate II

Thank you for answering.

Indeed the function returns HAL_TIMEOUT after one second (the timeout I set)

I have the same problem at 115200 baud (just verified). I don't think it's a speed issue because I can transmit data from the MCU to the laptop at 2000000 and receive it correctly.

It seems the function simply fetches the first byte and then sits waiting, maybe for an ISR to do something. Here I'm simply trying to read 10 bytes.

uint8_t buffer[10];
hal_status = HAL_UART_Receive(&huart5, buffer, 10, UART_TIMEOUT);

It has to receive all the bytes or timeout.

Perhaps need to look deeper in to why that's not happening.

It shouldn't use the interrupt here, but if something else is servicing the interrupt and RXNE flagging that could be a problem.

Also dwelling in the debugger looking at a peripheral view of the UART registers will also be invasive.

Perhaps look for framing or noise errors?

Large blocks can be accumulated via the interrupt methods also, most STM32 interrupt for every byte received, where as call-backs will only occur when buffer targets are hit.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

It's waiting for more data that never comes in. It doesn't call any ISRs. Increase UART_TIMEOUT value and/or verify that more data is actually arriving.

If you feel a post has answered your question, please click "Accept as Solution".
Yaxit
Associate II

No matter the timeout I set, only the first byte is received. I also tried to send data multiple times while the function is running (with a long timeout), but only the very first byte is received.

Regarding the noise, I believe this is not an issue, because I can get the data if I use HAL_UART_Receive_IT() and the callback. That works fine. I could use async UART for everything probably, but I would need to rethink a big part of my project, I'm trying to avoid that for now.

I mentioned interrupts as the HAL_UART_Receive_IT() runs an ISR for every byte received (as far as I understood), even though I know they should not matter in this case. But I'm confused by the first byte getting received every time.