UART Driver Hardware Flow Control and the "rx idle loop"

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
apmorton
Posts: 36
Joined: Fri Sep 29, 2017 10:26 am
Been thanked: 16 times

UART Driver Hardware Flow Control and the "rx idle loop"

Postby apmorton » Tue Apr 03, 2018 8:13 am

Hello,

Currently the UART driver is not usable with hardware flow control due to the rx idle loop, which makes the "rxchar_cb" callback possible.

Suppose you are attempting to receive a packetized protocol. You want to be able to receive a complete packet, and then allow some upper protocol layer to process the packet before receiving the next packet. For overall system performance, you don't want to do this processing in the "rxend_cb" callback.

You can either dedicate a single buffer, or have a queue of buffers available, but in either case you need a way to stall the receiving of the next packet until you have a buffer available.

Unfortunately, because the rx idle loop configures a circular dma transaction, there is no way to prevent reception for some period of time.
Perhaps an option to check if USART_CR3_RTSE is enabled in uart_enter_rx_idle_loop before configuring the dma transaction?

Something like this perhaps?

hal_uart.h

Code: Select all

// this allows disabling the idle loop entirely for all UART's if possible
#if !defined(UART_USE_RX_IDLE_LOOP) || defined(__DOXYGEN__)
#define UART_USE_RX_IDLE_LOOP           TRUE
#endif


hal_uart_lld.h

Code: Select all

// this allows leaving idle loop in tact, but disabling it on a per driver basis with some runtime overhead
#if !defined(STM32_UART_RTS_IDLE_LOOP_DETECTION) || defined(__DOXYGEN__)
#define STM32_UART_RTS_IDLE_LOOP_DETECTION    FALSE
#endif


hal_uart_lld.c

Code: Select all

static void uart_enter_rx_idle_loop(UARTDriver *uartp) {
#if UART_USE_RX_IDLE_LOOP
#if STM32_UART_RTS_IDLE_LOOP_DETECTION
  if ((uartp->usart->CR3 & USART_CR3_RTSE) != 0) return;
#endif  // STM32_UART_RTS_IDLE_LOOP_DETECTION

  uint32_t mode;
 
  /* RX DMA channel preparation, if the char callback is defined then the
     TCIE interrupt is enabled too.*/
  if (uartp->config->rxchar_cb == NULL)
    mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC;
  else
    mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE;
  dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf);
  dmaStreamSetTransactionSize(uartp->dmarx, 1);
  dmaStreamSetMode(uartp->dmarx, uartp->dmamode | mode);
  dmaStreamEnable(uartp->dmarx);
#endif  // UART_USE_RX_IDLE_LOOP
}

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: UART Driver Hardware Flow Control and the "rx idle loop"

Postby Giovanni » Tue Apr 03, 2018 10:25 am

Hi,

The driver is designed around never stopping received data, you get a callback for each received byte even while a receive operation is not in progress.

Why don't you do the CTS handling in the receive callback? if you have no buffers then block CTS and ignore eventual incoming data callbacks.

Giovanni

apmorton
Posts: 36
Joined: Fri Sep 29, 2017 10:26 am
Been thanked: 16 times

Re: UART Driver Hardware Flow Control and the "rx idle loop"

Postby apmorton » Tue Apr 03, 2018 12:57 pm

After doing more research on the STM32 built-in implementation of RTS, it seems the general consensus is that its almost useless.
Because the hardware is not capable of receiving at least one more character after de-asserting RTS, it seems common for overruns to happen at high baud rates.

Implementing something like what you mention is likely the best idea.
Control RTS via GPIO.
- de-assert it in rxend/rxchar based when free buffer space goes below a threshold.
- re-assert it in whatever routine processes the buffer, when space goes above a threshold.

This allows the transmitting end some slack in its response time to RTS.
The hardware implementation of CTS works fine with the UART driver in ChibiOS, so nothing special needs to be done there.

Thanks,
Austin


Return to “Development and Feedback”

Who is online

Users browsing this forum: No registered users and 15 guests