Skip to main content
Visitor II
March 30, 2023
Solved

HAL_UARTEx_ReceiveToIdle_DMA() => No reaction on IDLE event

  • March 30, 2023
  • 8 replies
  • 9238 views

I'm trying to make use of the HAL_UARTEx_ReceiveToIdle_DMA() functionality.

So far no reaction on an IDLE event. The corresponding HAL_UARTEx_RxEventCallback

gets called when a certain amount of bytes has been received, but not on an IDLE event.

The development board I use: NUCLEO-L031K6

The UART of interest:USART2

So here's my setup:

0693W00000bhDtDQAU.jpg0693W00000bhDtIQAU.jpg0693W00000bhDtNQAU.jpg0693W00000bhDtSQAU.jpg0693W00000bhDtcQAE.jpgI added the following code:

...

/* USER CODE BEGIN PFP */

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size);

/* USER CODE END PFP */

...

/* USER CODE BEGIN 2 */

HAL_UARTEx_ReceiveToIdle_DMA(&huart2, rx_buf_usart2, rx_buf_size);

__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

/* USER CODE END 2 */

...

/* USER CODE BEGIN 4 */

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size)

{

if (huart->Instance == USART2)

{

HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);

HAL_UARTEx_ReceiveToIdle_DMA(&huart2, rx_buf_usart2, rx_buf_size);

__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

}

}

/* USER CODE BEGIN 4 */

...

rx_buf_size is set to 16. And exactly after 16 bytes the RxEventCallback gets executed.

What am I missing?

As you can see in my setup, the USART2 global interrupt ist set.

Could somebody point me in the right direction to look for the problem?

Thanks.

    This topic has been closed for replies.
    Best answer by Karl Yamashita

    That's right i forgot that you get the 16 bytes.

    I'd check the HAL status when you call HAL_UARTEx_ReceiveToIdle_DMA. More than likely it returns as HAL_ERROR. So based from the notes i highlighted it reverted to HAL_UART_RECEPTION_STANDARD. That would be the only explanation why you're not getting interrupts on idle.

    Check the HALdriver stm32l0xx_hal_uart_ex.c and put a breakpoint on line 775 and see during debug if it breaks.

    0693W00000bhGTSQA2.png

    8 replies

    Graduate II
    March 30, 2023

    Here is a clue, you call __HAL_DMA_DISABLE_IT to disable the DMA interrupt, after you call HAL_UARTEx_ReceiveToIdle_DMA to enable the interrupt.

    Visitor II
    March 31, 2023

    Hi Karl,

    thank you for your post. The line

    __HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

    should only disable the interrupt generated after half of the expected data has been received.

    According to certain threads and forum messages this interrupt and the subsequently calling of

    HAL_UART_RxHalfCpltCallback() are not necessary.

    Anyhow, I'll try to comment this line and come back with the result.

    Graduate II
    March 31, 2023

    Well if you design a ring buffer then you don't need to worry about trying to parse the first part of data when HAL_UART_RxHalfCpltCallback interrupts while the second part of the data is being saved in the data array.

    See this post where i can accept up to 64 bytes and i have a queue to hold up to 4 RX messages. The Tx routine has the same concept so a message will never get lost because HAL was busy transmitting a previous message. https://community.st.com/s/question/0D53W00002CeLaOSAV/cannot-receive-full-string-on-uart-receive-st32h745-disco-board

    Visitor II
    March 31, 2023

    In the end I will use a ring buffer, cause that is from my point of view the most convenient way to handle received data.

    Ok back to the previous approach: I commented the line

    __HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

    out, but no change. No call to HAL_UARTEx_RxEventCallback after an IDLE situation.

    Is there anything else what I could try?

    Graduate II
    March 31, 2023

    I assume you're using the VCP? Did you check with an oscilloscope to see if the PC is sending data and you see data activity on PA15? Baud rates match?

    Visitor II
    March 31, 2023
    Yes, I am using the VCP. And I connected an oscilloscope with decoding functionality to monitor PA15.
    The terminal software to send data via serial line is PUTTY. And as I already mentioned, I know that
    data has been received, cause after exactly 16 Bytes the callback function gets executed due to
    the RxCplt event.
    Graduate II
    March 31, 2023

    That's right i forgot that you get the 16 bytes.

    I'd check the HAL status when you call HAL_UARTEx_ReceiveToIdle_DMA. More than likely it returns as HAL_ERROR. So based from the notes i highlighted it reverted to HAL_UART_RECEPTION_STANDARD. That would be the only explanation why you're not getting interrupts on idle.

    Check the HALdriver stm32l0xx_hal_uart_ex.c and put a breakpoint on line 775 and see during debug if it breaks.

    0693W00000bhGTSQA2.png

    Visitor II
    March 31, 2023

    Hi Karl,

    it was not exactly the reason but the right direction. In fact I missed to check the

    Status of the HAL between two conscutive called DMA functions.

    Thanks

    Graduate II
    March 31, 2023

    That is good to hear and that I was able to help get you in the right direction.

    Graduate II
    March 31, 2023

    If the DMA (half)complete callbacks are working, but the IDLE does not, it means the UART interrupt for some reason doesn't work. Stop clicking and check the actual CubeMX generated bloatware.

    Visitor II
    April 21, 2023

    Hi MClau.1,

    well it would probably help in your situation if you would show us some portions of the code that you use to handle DMA transfers.

    In general the ReceiveToIdle call activates three kind of interrupts:

    IDLE => Reacts on IDLE events and the IDLE duration to react on depends on your configuration

    HC => Reacts on DMA transfers when half of the data to receive or to send has been handled

    TC => Reacts on DMA transfers when the entire amount of data to receive or to send has been handled

    If the DMA request has been set to normal mode, then subsequently performed DMA transfers have

    to be reinitiated by calling the ReceiveToIdle function again in case of an IDLE ot TC event.

    And I think it is good practice to call HAL_DMA_GetState for the DMA channel of interest before

    calling ReceiveToIdle. This way you ensure that all related DMA processes are done.