UART Hardware Flow Control - Confirming Nominal Operation - Page 1
Forum section: electronics / beginners

author: davegravy
author_rank: Regular Contributor
timestamp: March 09, 2024, 12:58:04 am
content: I've never used flow control before and I'm scratching my head a bit interfacing with this Sparkfun LTE shield:https://www.sparkfun.com/products/14997Schematic here:https://cdn.sparkfun.com/assets/d/7/b/c/3/lte_cat_m1_shield_schematic_v11.pdfAfter cutting JP4 that shorts the shield's RTS to ground, I connected my SBC's RTS to the shield's CTS and vice versa. But I wasn't getting any successful communication (I tested UART without flow control fine beforehand so I knew the RX and TX connections were correct).I connected the 4 pins to a logic analyzer and saw some CTS/RTS activity but it didn't make a lot of sense to me based on my understanding of how it should work. Only the SBC was sending data, no replies from the shield.After pulling my hair out for a bit I reversed the CTS/RTS connection and voila it started working. Confused, I checked the LA again and the SBC's CTS is constantly low (active). Triggering on rising/falling SBC CTS there is never any LA capture. I see the Shield's CTS being switched occasionally but never the SBC's.Is this normal? Does it just mean throughput is too low to achieve a full buffer on the SBC's side? Baud rate is 115200How can I be sure this is working normally?

author: Nominal Animal
author_rank: Super Contributor
timestamp: March 09, 2024, 03:44:01 am
content: Quote from: davegravy on March 09, 2024, 12:58:04 amIt is normal on Linux SBCs at such 'low' baud rates. It is only about 11520 bytes per second, after all, so the kernel has ample time to buffer the incoming data –– there is no buffer per se, but the entire tty layer acts like one ––, and the application handling the data keeps consuming the data fast/often enough so there is no stall. Even on older SBCs like Odroid C1+s and original Raspberry Pis, you need a much higher sustained data flow to start seeing non-clear-to-send state.Quote from: davegravy on March 09, 2024, 12:58:04 amI'd use a simple program on the SBC to send and receive data, and a microcontroller sending and receiving data at the maximum baud rate.I like to use the Xorshift64* pseudo-random number generator to generate the sequence (two in parallel here), with the SBC providing the random (64-bit unsigned nonzero) seeds, with both generating their own copies using the same two seeds, and comparing to what they receive.I use similar code to measure the sustained bandwidth over USB Serial, except that because USB 2 is half-duplex, I only send OR receive, not both at the same time.Reduce the priority of the program running on the SBC, for example down to idle by usingnice -n +19 ionice -c 3 ./program..., and run other stuff on it (representing maximum expected load on the SBC during communications), and see if the SBC and the microcontroller fall out of sync.You can use any microcontroller you like for such a test, even Arduino Nano, although I prefer to use Teensies. If the SBC uses different logic levels than the microcontroller (Odroid HC1 for example uses 1.8V levels on its UART), I recommend you use a TI TXU0204 level shifter; these have proven to be extremely robust in my use. (I used to use 74LVC1T45 etc. before I stumbled on the TXU0n0m series. Bidirectional level shifters often have a "glitch" in the low state when they sense the direction wrong, and sometimes the change in the low-level signal, while small, can cause issues. I only use either unidirectional ones, ones with a direction pin, or dedicated I2C ones.)Essentially, this is a practical test for the robustness of the communication channel, with or without hardware handshaking.

author: davegravy
author_rank: Regular Contributor
timestamp: March 09, 2024, 03:59:02 am
content: Thanks, that sounds like a good stress test and I'll give it a shot.I do think something is wrong with my setup however because I just noticed the SBC is writing to TX even when I have the RTS/CTS lines disconnected (floating).First though, a connection diagram because I've seen multiple on the internet now. It seems like the SBC is outputting to its RTS pin, so I assume the host CTS is the input. According to module datasheet, RTS is an input and CTS output (see attachment).So:Host RTS (output) ---> (input) Module RTSHost CTS (input) <---> (output) Module CTSTurns out the SBC's CTS is low (active) when it's floating, the same is not true on the shield because according to the module datasheet it has an internal pull-up. I decided to edit the SBC device tree and set pull-up biasing. Now it floats high, but it still writes to TX when it's floating

author: Nominal Animal
author_rank: Super Contributor
timestamp: March 09, 2024, 05:29:33 am
content: I took a look, and found the datasheet of the actual module used on the board, SARA-R410M-02B,here. It has this to say:"HW flow control is not supported by the SARA-R410M-01B or the SARA-R410M-02B-00, and the RTS input has to be set low (= ON) to communicate over the UART on the SARA-R410M-01B."The -00 version is old/obsolete, and unlikely to be used on your board.The board uses a TXB0104 bidirectional level shifter for RX and TX on the J5 connector, according to thedatasheet. I don't like it, but it almost certainly works just fine; the SparkFun designers know their work better than I do, as I'm just a hobbyist myself.However, theschematicreveals interesting stuff. In particular, RTS is only available on the J6 connector, and CTS on the J7; the CTS and DTR pins on the J5 connector do not seem to be connected to anything. Furthermore, on J6 and J7 the signals use 1.8V logic levels, so to connect to these you need external voltage level translators like 2×74LVC1T45, 2×TXU0101, or 1×TXU0102. Connecting them directly to 3.3V may be destructive. If your SBC uses 1.8V logic levels on the RTS/CTS pins, then connecting them directly is okay. (CTS being an output from the module connected to an 3.3V input pin will be unlikely to pull the pin high enough to change the state, and an internal pullup to 3.3V might cause issues on the module side, since it can only handle up to 1.8V on the logic pins, and the board has no level shifting for RTS or CTS.)Quote from: davegravy on March 09, 2024, 03:59:02 amOn the SBC, you need to explicitly enable hardware flow control when opening the serial port device. Usingtermiosyou OR.c_cflagwithCRTSCTS. If you use a shell script andsttyto set the serial port properties, includecrtscts. By default, hardware flow control (RTS and CTS) is ignored, so the behaviour you see would be expected then.

author: davegravy
author_rank: Regular Contributor
timestamp: March 09, 2024, 05:54:39 am
content: Quote from: Nominal Animal on March 09, 2024, 05:29:33 amYes, 1.8V logic off the SBC so should be fine.Quote from: Nominal Animal on March 09, 2024, 05:29:33 amI'm opening the serial port via pyserial and passing in rtscts=True.I am getting toggling of the SBC's RTS output, so it gives the impression flow control is enabled, at least partly?I have an idea what the issue may be, which explains why CTS on the SBC isn't working. Ijust posted about it on the Microchip forumas they make the ATSAMA5D27 SoC for my SBC. I'm not sure if it's a hardware bug but the GPIO I'm supposed to use for CTS is shown in the manual to be an output-only pin. But I'm not really sure this is it, based on some bare-metal projects I see around the net.I may try to see if I can change the pin assignment.Hmm, or it could be a pyserial issue:https://github.com/pyserial/pyserial/issues/89

author: Nominal Animal
author_rank: Super Contributor
timestamp: March 09, 2024, 08:21:04 am
content: I wouldn't know, because I usetermiosinstead of the pyserial abstraction, including from Python.

author: davegravy
author_rank: Regular Contributor
timestamp: March 09, 2024, 04:52:43 pm
content: Quote from: Nominal Animal on March 09, 2024, 08:21:04 amI think I can put this to rest. Minicom, stty, and termios all refuse to send if CTS is floating, only pyserial ignores it. Looks like I'll need to switch my library to use termios.Thanks for the help!