cancel
Showing results for 
Search instead for 
Did you mean: 

RTS flow control doesn't seem to work

Sietse
Associate III
Posted on February 16, 2017 at 16:13

Dear List,

I am trying to get RTS/CTS flow control working on a discovery-stm32f407 board using cubemx generated software.

But when sending data from the PC to the UART2 the RTS signal never gets high as seen with a scope.

Constequently the data keep coming and soon there is an overrun error in the HAL_UART_ErrorCallback(). I use interrupts.

Sending data at slow enough speed is working perfectly.

I am testing with an usb-to-serial converter, ftdi-chip, between the PC and the board.

That side seems to work: if I make the CTS of the ftdi-chip (which is connected to the RTS of the UART2) high, the PC

immediately stops sending.

I configured RTS/CTS flow control in cubemx and also use interrupts here.

RTS is connected to Pin PD4 via cubemx

The configuration in MX_USART2_UART_Init(void):

huart2.Instance = USART2;

huart2.Init.BaudRate = 913085;

huart2.Init.WordLength = UART_WORDLENGTH_8B;

huart2.Init.StopBits = UART_STOPBITS_1;

huart2.Init.Parity = UART_PARITY_NONE;

huart2.Init.Mode = UART_MODE_TX_RX;

huart2.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;

huart2.Init.OverSampling = UART_OVERSAMPLING_16;

if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); }

The routine that I created to use it is:

__IO ITStatus Uart2RReady=RESET;

// non blocking, but will deliver the buffer in one piece in the end

int uart2_read(char *dst, int size) {

     static char inprogress=0;

      if (size == 0) return 0;

      if (!inprogress) {

          Uart2RReady = RESET;

          if (HAL_UART_Receive_IT(&huart2, (uint8_t *)dst, size) != HAL_OK)

          printf('uart2 read error\r\n'); // error_handler(nummer)

          inprogress = 1;

     }

     if (Uart2RReady == SET) {

          inprogress = 0;

          debug_printf('Received: %d bytes\r\n', size);

          return size;

        } else return 0;

}

The question is why is RTS not set high when data keeps coming at a high enough rate?

 Thanks in advance,

       Sietse

7 REPLIES 7
Posted on February 16, 2017 at 17:13

I think you have to stop servicing the receive data register for it to assert.

Flow control on the STM32's and the rather simplistic USART implementation don't function very well. I've tended to implement a hybrid approach where the underlying buffering manages the throttling of the connection.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on February 18, 2017 at 15:14

Thanks for the reply.

Flow control with RTS works, but only barely. After RTS is asserted the other end has to react immediately.

But this is unreasonably, especially if characters are send end to end. After the stopbit of the second byte the startbit of the third byte can already come.

So a reasonable UART implementation is able to read one (third) character properly to give it a chance to see the RTS and react to it. As far as I can see the STM32 cannot do that. And there is also no mention of the available time in the reference manual.

I now will use a fifo for receiving and control the RTS pin via software.

This, the fifo solution, was actual the one I used in the previous version of our application before I make the step to the HAL-based version.

Thanks again.

AVI-crak
Senior
Posted on February 19, 2017 at 11:18

The signal of RTS works ideally, but very quickly and completely automatically.

Use of DMA with accumulating of data in the FIFO buffer - dumps RTS signal very quickly. Speed of reaction of dumping is higher than registration of a signal in an output pin �?¼�?º.

However incorrect installations for DMA - can give transmission errors. Mistakes will be connected with the incorrect number of data in FIFO.

Use of the manual mode (without DMA) together with RTS/CTS is a special type of masochism. Treatment is impossible (old habits die hard).

Use of 4 communication lines (RTS, RX, CTS, TX) - is ideal in combination with an optical outcome. As a result we have minimum program and overheads for communication, + high accuracy of the data. Other use of 4 communication lines is excessive. For conditions of the minimum hindrances - there are more high-speed interfaces.

Posted on February 19, 2017 at 15:09

Sorry, but I think not. Communication works perfectly (using DMA or in my case using interrupts) when sending and receiving packets of , say, 100 bytes. You then can see, on a scope, the spikes of the RTS signal. But there now is no actual use of flow control since data is always read fast enough.

Communication works perfectly if the packets written and read (on the STM) are of the same size.

But suppose I send 2 packets of 100 bytes from the PC to the STM32. On the STM32 I do 2 reads of 100 bytes using the HAL routines for DMA or INT.

What happens is that the first 100 bytes are read perfectly and the first read is done. But before the second read is started the first bytes of the second packet arrive. Note that the baudrate is quite high, say 900000 baud.

The first byte is read, and when the second bytes has arrived the RTS signal is asserted. But now it will not be de-asserted because the second read is not started yet.

From now on the PC should not send any data more to the STM32, but it takes some time for the PC to react to the RTS.

Looking at the scope I think the time available for this is less then the time of the stop bit because directly after this stopbit the next startbit can come, so something like 100 nsec.

So in theory the PC , or in my case a serial to USB convert (FTDI) or a Bluetooth chip, could react fast enough, but in practice they do not. So the third character arrives and gives an overrun. End of story.

In an earlier life I used UART´s, but when they raised RTS the UART was still able to receive one character. As mentioned above, that is a reasonable requirement.

So when using high baudrates, RTS flow control cannot properly be used with current hardware.

But that´s no problem for me, because I can use the fifo solution: then the ¨end of the read' will never arrive, so the above situation does not occur. I used this construct for more than a year in an older version when the HAL library did not exist yet. But for several reasons I wanted to upgrade to using this HAL library and hoped that I could use the HAL functions as given. I now have to use my own (old) interrupt routine.

The fifo gives me more that enough time to cope with the above scenario, but if I still need flow control I can program the RTS pin using it as a GPIO on the basis of the state of the fifo.

Thanks for the response, Sietse

AVI-crak
Senior
Posted on February 19, 2017 at 17:10

RTS is set hardware!!! itself, automatically, when DMA stopped filling the buffer and caused interruption. UART won't register new data, before normal restarting of DMA.

If the transmitting end managed to send a part of data of one byte - that in case of installation of RTS arises an exception on the transmitting end. After RTS falling transmission of this byte begins in the start mode, all bits in sequence. Too completely automatically.

To control RTS/CTS programmatically through HAL or that it is even worse through GPIO: it how to buy the train ticket and will go on foot.

Posted on October 20, 2017 at 18:04

Hi 

Sietse,

I'm also using FTDI USB/UART bridge face to STM32L4 USART peripheral in DMA mode and I observed FTDI does not 'perfectly' respect flow control. Using logic analyzer I noticed FTDI is sending one more character though STM32 indicates it cannot accept more data 

(

STM32 RTS/FTDI CTS is 1) because of higher priority processing. This behavior is confirmed in

http://www.ftdichip.com/Support/FAQs.htm ♯ HwGen2

 :

'If CTS ♯ is logic 1 it is indicating the external device cannot accept more data. the FTxxx will stop transmitting within 0~3 characters, depending on what is in the buffer.

This potential 3 character overrun does occasionally present problems.'

In my case OVERRUN error occured and one byte is lost.

Do you have a solution to prevent any byte to be lost?

Thanks

,

Guillaume

Posted on October 20, 2017 at 18:17

You'd need a sufficiently deep buffer so you can throttle the transfer in the DMA TC/HT interrupt if your secondary buffer can't take anymore data. ie create a small primary FIFO buffer using circular DMA to deal with flow control at the interface, and a larger secondary FIFO to deal with you transfer protocol.

The ST U(S)ART implementation is pretty lame as such peripherals go, pity someone didn't pay for the 16550 work-alike IP that's been prevalent in SoC designs for several decades.

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