cancel
Showing results for 
Search instead for 
Did you mean: 

How I can resume receiving data from flow controlled UART?

Naos Y
Associate II

I'd like to know how I can resume receiving data from flow controlled 

UART.

I use HAL, and I set USART2 into "flow control" with Cube MX code like as

huart2.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;

(115200 bps, data bit 8, stop bit 1, none parity, etc. )

I start data receiving as follows,

HAL_UART_Receive_DMA(&huart2, &g_recv_char, 1);

and the 1 byte receiving is chained as follows.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) {

  (......any processes......)

  HAL_UART_Receive_DMA(&huart2, &g_recv_char, 1);

}

It works for a while (10 - 30min), but after it the data receiving is stopped. When I read RDR register with debugger, the value is changed and it is explicit correct data sent from external device.

But "HAL_UART_RxCpltCallback" func is not called.

When I manually execute "HAL_UART_Receive_DMA(&huart2, &g_recv_char, 1);" (with debugger operation), continuous data receiving is resumed.

So I guess the external device is stopped data sending, by my MCU's RTS pin.

How can I know my RTS pin status ?

Or how I can know that chained receiving process is stopped?

I use STM32L496RGT6, TM32CubeMX V5.4.0, and IAR Embedde Workbench for ARM V8.4.0 with Windows 10 PC.

Sorry for the basic question.

Thank you in advance.

1 ACCEPTED SOLUTION

Accepted Solutions
Bob S
Principal

How long does "(.... any processes...)" take?

I suspect your issue is not "resuming after flow control", but rather that every once in a while you are taking too long to re-enable the receive function. Calling HAL_UART_Receive_DMA() for every byte of data is grossly inefficient and allows for the possibility that the UART may receive the next byte before you re-enable the DMA - causing exactly the case you describe above. The UART receives the next byte while your program is off "any processing", the RX DATA register is full so the chip de-asserts RTS, which stops the other end from transmitting. Your code then enables RX with DMA but never reads the RX DATA register so RTS remains de-asserted, so no more data arrives.

If you are going to use DMA - allocate some large buffer and enable DMA in circular mode to write into that buffer. You can then poll the DMA registers to see if you have received any data. Search this forum for UART and DMA and you should find some examples.

View solution in original post

2 REPLIES 2
Bob S
Principal

How long does "(.... any processes...)" take?

I suspect your issue is not "resuming after flow control", but rather that every once in a while you are taking too long to re-enable the receive function. Calling HAL_UART_Receive_DMA() for every byte of data is grossly inefficient and allows for the possibility that the UART may receive the next byte before you re-enable the DMA - causing exactly the case you describe above. The UART receives the next byte while your program is off "any processing", the RX DATA register is full so the chip de-asserts RTS, which stops the other end from transmitting. Your code then enables RX with DMA but never reads the RX DATA register so RTS remains de-asserted, so no more data arrives.

If you are going to use DMA - allocate some large buffer and enable DMA in circular mode to write into that buffer. You can then poll the DMA registers to see if you have received any data. Search this forum for UART and DMA and you should find some examples.

Thank you for your kindness advice.

I could find "double buffered" examples which seem to be useful.

On the other hand, I realized DMA was not necessarily necessary in this case.

I'll try some codes which does not prevent receiving.