cancel
Showing results for 
Search instead for 
Did you mean: 

UART receive until idle line.

BMart
Associate II

Hi! I'm trying to use the following function:

HAL_UARTEx_ReceiveToIdle_IT(&hlpuart1, lpuartRXbuffer, 64);

I've seen a few example codes using it but otherwise google shows nothing when I search for it. I think I should get some callback but I cannot figure what should it be. I tried the following:

void HAL_UARTEx_RxEventCalllback(UART_HandleTypeDef *huart, uint16_t Size)
{
 
}

But there is no response.

I'm new to the STM32 software environment, coming from Arduino and Atmel so any advice where to find such information helps a lot.

1 ACCEPTED SOLUTION

Accepted Solutions
Piranha
Chief II

> Is there any obvious beginner mistake?

Yes, there is - the spelling of the function name... ;)

View solution in original post

7 REPLIES 7
TDK
Guru

HAL_UARTEx_ReceiveToIdle_IT is relatively new compared to the other UART functions which explains the lack of examples.

HAL_UARTEx_RxEventCalllback HAL_UARTEx_RxEventCallback is called when the idle condition happens exactly here in the code:

https://github.com/STMicroelectronics/STM32CubeF4/blob/4aba24d78fef03d797a82b258f37dbc84728bbb5/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c#L2530

If that's not happening, you would need to dig deeper. Ensure the HAL_UART_IRQHandler is getting called. Ensure the idle flag is getting set and the interrupt is enabled. When idle happens, ensure the IRQ handler is called and handled appropriately.

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

Well then I have to dig deeper. I have interrupts enabled and the regular "HAL_UART_RxCpltCallback" works perfectly when I use "HAL_UART_Receive_IT".

I'll paste a few pieces of my code here, maybe it's just my beginner mistake:

In the main, after initializing the peripherals (init generated by the IDE), I use

HAL_UARTEx_ReceiveToIdle_IT(&hlpuart1, lpuartRXbuffer, 64);

Then there is the callback, before the main, in the User Code 0 section:

void HAL_UARTEx_RxEventCalllback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart->Instance == LPUART1)
	{
		HAL_UART_Transmit_IT(&hlpuart1, lpuartRXbuffer, Size);
		HAL_UARTEx_ReceiveToIdle_IT(&hlpuart1, lpuartRXbuffer, 64);
		HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
		//echo = 1;
	}
}

Is there any obvious beginner mistake?

Piranha
Chief II

> Is there any obvious beginner mistake?

Yes, there is - the spelling of the function name... ;)

Thank you! I feel really stupid now. :)

RBT
Associate

Hello

I used the same function and it works. BUT it works only at the moment when I program it when I disconnect stlink and restart the system it doesn't work (No response from callback function)... Does anybody knows what happens here ?

DanKlein
Associate

I've been fighting with STM43F429. I have what I am working on functioning, but it took a lot of work.

I use the idle interrupt to receive data. I got similar code working in late 2020 and using ST Micro's APIs, but have had to revisit ST Micro's UART API in the last few weeks after starting a new project and updating to 1.14.1.

I am using the idle interrupt and the function HAL_UARTEx_ReceiveToIdle_IT(&huart4, pRdBuffer, size) to receive my data.

In void UART4_IRQHandler(void), I replaced...

  if (__HAL_UART_GET_FLAG (&huart4, UART_FLAG_IDLE))
  {
    __HAL_UART_CLEAR_IDLEFLAG (&huart4);
    HAL_UART_RxCpltCallback (&huart4);
  }

with

  if((registerValue & UART_FLAG_IDLE) == UART_FLAG_IDLE)
  {
    huart4.Instance->SR = registerValue & 0xFFFFFFEF;
    HAL_UART_RxCpltCallback(&huart4);
  }

So __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) only clears the PE flag. See line 540 of stm32f4xx_hal_uart.h to confirm for yourself.

In troubleshooting, I found more issues. Here is the excerpt I wrote to share my findings with my coworkers.

....in stm32f4xx_hal_uart.h lines 516 to 540. There is a set of macros that only clear the PE Flag, not the flags they report to clear.

They call the macro __HAL_UART_CLEAR_PEFLAG() It only (seemingly) clears the UART PE pending flag.

So the macro __HAL_UART_CLEAR_FEFLAG ostensibly clears the PE Flag, 
__HAL_UART_CLEAR_NEFLAG ostensibly clears the PE Flag,
__HAL_UART_CLEAR_OREFLAG ostensibly clears the PE Flag, and
__HAL_UART_CLEAR_IDLEFLAG ostensibly clears the PE Flag.

Those macros call another macro __HAL_UART_CLEAR_PEFLAG() which doesn't seem to clear the PE flag.

In the original concept, ST Micro probably intended for HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) to be used for this. Examples of what they probably intended to do are shown immediately below.

HAL_UART_CLEAR_FLAG(__HANDLE__, UART_FLAG_FE)
HAL_UART_CLEAR_FLAG(__HANDLE__, UART_FLAG_NE)
HAL_UART_CLEAR_FLAG(__HANDLE__, UART_FLAG_ORE)
HAL_UART_CLEAR_FLAG(__HANDLE__, UART_FLAG_IDLE)and
HAL_UART_CLEAR_FLAG(__HANDLE__, UART_FLAG_PE)

Someone at ST Micro either made a series of cut-paste errors and/or didn't know what was going on. They seem to have never tested this or maybe they just never envisioned their API being used the way we're using it.

Hopefully this helps someone who is struggling. Hopefully, this helps ST Micro, too.

Pavel A.
Evangelist III

@DanKlein Please start a new thread if you want to discuss another issue.

Rather than "fighting" with the STM32, read the good book. RM0090. The U(S)ART register description. There it says that PE flag can be cleared by a sequence: reading SR then reading or writing DR, *when RXNE is set*.

Flags IDLE, FE, ORE, NF are cleared by the same sequence: reading SR then reading or writing DR - but there's no condition "The software must wait for the RXNE flag to be set". None of these flags can be cleared by writing anything into SR.

__HAL_UART_CLEAR_PEFLAG indeed is implemented as read SR, then read DR. No writing SR.

Macros in stm32f4xx_hal_uart.h have comments that describe which flags they can read or clear.