Hardware flow control in USB CDC? - Page 1
Forum section: electronics / general

author: Fabian
author_rank: Contributor
timestamp: April 19, 2020, 06:27:34 pm
content: Hi there! I need an USB expert. I want to implement a USB-UART bridge using a microcontroller (ATSAMD21) which also supports hardware flow-control.I know that there is no flow control required on the USB side, as it has an instrinsic flow control by resending NACK'ed packets. And yes, you can implement hardware flow control on the UART side, no problem. But the question is: How do I know if the user (i.e. the terminal program or whatever) turned on flow control? There seems to be no message telling the mico to turn on or off flow control, is that correct? I could use a jumper or something to tell my micro what to do, but that is quite ugly. Also I could write my own UART bridge standard (like FTDI did, so they have this feature), but that is a pain for windows I am not willing to accept. Not even talking about certification of that driver.

author: oPossum
author_rank: Super Contributor
timestamp: April 19, 2020, 08:26:10 pm
content: The host side (computer) can control DTR and RTS. See section 6.3.12 of "Universal Serial Bus Communications Class Subclass Specification for PSTN DevicesRevision 1.2"

author: bson
author_rank: Unknown
timestamp: April 20, 2020, 02:27:54 am
content: I'd trace it out and see what a Windows host sends in terms of line encodings, features etc when you enable flow control. There might be something nonstandard there, either by tracing it in the firmware or use a USB Analyzer. Whatever Windows does is effectively going to be the standard. Yes, USB is a clowncar.

author: Fabian
author_rank: Contributor
timestamp: April 20, 2020, 08:14:24 am
content: Hi, thanks for the quick response.@oPossum: Yes, I know that, but what about CTS? How do I know if the controller should implement that?@bson: I debugged the USB communication on my Liunux machine using wireshark and could not find any difference in the packets between turning on and off flow control before connecting to the port. But that does not necessarily mean that this is not possible. There is for example the bmCapabilities field in the ACM descriptor, but I could not figure out what this exactly means. And there are many more things I have not fully understood, which may help.

author: pigrew
author_rank: Frequent Contributor
timestamp: April 20, 2020, 08:32:30 pm
content: As far as I know, the CDC PSTN standard doesn't support configuration of hardware flow control.You could create a new control request to configure it, but I don't think these can easily be configured on Windows using non-standard drivers.Perhaps you can do something non-standard like using the parity or number of stop bits to enable/disable hardware flow control? It's ugly, but would work.Table 5.3.1 of the PSTN spec describes ACM capabilities. These just advertise what the USB device supports to the host, but don't allow any configuration by the host.ADDED: You might be able to use the BREAK signal somehow, too.

author: NorthGuy
author_rank: Super Contributor
timestamp: April 20, 2020, 09:07:48 pm
content: The bridge<->MCU communication is separate from bridge<->USB communication and should have its own flow control. Your bridge will probably have some sort of internal buffers. If there's room in the buffer, you still can accept the data from USB even after MCU has stopped the communication. Same with the other direction, you stop communication with MCU when your internal buffer is full, which may be considerably later than USB NACK'ed you.If you try to control flow between end points (MCU<->USB) ignoring the presence of the bridge (say by sending XON/XOFF symbols) you will slow down the communication beyond usable.

author: Fabian
author_rank: Contributor
timestamp: April 21, 2020, 12:20:36 pm
content: OK, thanks @oPossum. At the bottom line, there is no way to get this information. That was my fear... So we will have to use some buttons or something else to tell the µC what to do. It is not a very user friendly solution, aspecially if the user does not know if the connected device needs flow control or not.Thanks guys!

author: Nominal Animal
author_rank: Super Contributor
timestamp: April 21, 2020, 09:31:21 pm
content: Do what other native-USB microcontrollers do, and implement a Class 02h (Communications and CDC), SubClass 02h (Abstract Control Model), Protocol 00h (No class specific protocol required) CDC ACM device.There are several abstract control model requests the host computer can send to the device; among these, SetLineCoding and SetControlLineState.Line Coding defines data terminal rate in bits per second (32-bit field), number of stop bits (0:1, 1:1.5, 2:2), parity, and data bits.Control Line State is a 16-bit bitmap, with bit 1 corresponding to RTS, and bit 0 corresponding to DTR.The device can send SERIAL_STATE notifications to the host. These also contain a 16-bit bitmap, with bit 0 corresponding to DCD, bit 1 DSR, bit 2 Break, bit 3 Ring, bit 4 Framing error, bit 5 parity error, bit 6 overrun, and bits 7-15 reserved.While CTS is not available to the host, but you can use DSR instead; that one is.If you use say a cheap Pro Micro clone (and treat it as an Arduino Leonardo) in the Arduino environment, these are exposed viabaud(),stopbits(),paritytype(),numbits(),dtr(), anddtr()methods in the CDC Serial object. AFAIK it doesn't expose any functions for sending SERIAL_STATE notifications (from device to host computer), though.I do not know if or how the Windows CDC ACM driver provides these to userspace, but in Linux, the termios interface and the TIOCMGET/TIOCMSET/TIOCMBIC/TIOCMBIS ioctl()s expose these just fine. There is even an TIOCMIWAIT and TIOCGIGOUNT ioctl()s, that efficiently wait and provide the number of changes in each field, respectively.

author: cv007
author_rank: Frequent Contributor
timestamp: April 22, 2020, 04:48:41 am
content: >How do I know if the user (i.e. the terminal program or whatever) turned on flow control?The SAM could just assume it is using hardware flow control, weakly pull the cts line to asserted state, and let the rts output work as normal. If the target does not use flow control, no harm and you have no flow control. If the target does use flow control, it overrides the weakly asserted cts line and uses the rts info. If the target hardware is capable of flow control (and you want to use it), you have to hook up the extra lines so let the hardware capabilities decide at connection time and software does not have to know or care.You could also pretend you are a modem and implement a mini AT-like command set, but would require user intervention to send the commands (unless your terminal software can send modem init commands, I guess). Back when signed drivers were starting (WinXP?), for just messing around I just used a vid/pid of some old Compaq usb modem that was probably from the Win98 days and was long gone but had a signed driver. Worked ok, but I had to ignore the initial modem init/inquiry.

author: David Hess
author_rank: Super Contributor
timestamp: April 22, 2020, 06:24:00 pm
content: Quote from: oPossum on April 19, 2020, 08:26:10 pmHow could that possibly work successfully except at low baud rates? USB latency is longer than the character transmission time at common high baud rates.When receiving, the buffer could handle overflow but on transmit, there is no way for the device to notify the computer in time to stop transmitting unless flow control is handled by the UART. I think the standard for USB to serial was always flawed for this reason.

author: oPossum
author_rank: Super Contributor
timestamp: April 22, 2020, 06:34:42 pm
content: Per character flow control is local (in the USB to serial bridge). The DTR/RTS control from the host just changes the state of readiness.

author: bson
author_rank: Unknown
timestamp: April 24, 2020, 01:21:51 am
content: Quote from: oPossum on April 22, 2020, 06:34:42 pmAs far I can tell from the PSTN spec they're only used to control the direction when the link is operating in half duplex.

author: NorthGuy
author_rank: Super Contributor
timestamp: April 24, 2020, 01:52:41 am
content: The protocol has been developed for communicating with modems through the serial link where both modem and PC had direct access to the wires. Thus it was possible to do hardware flow control through the signal on wires. USB doesn't work that way. If you want to set any signal on the wire between bridge and modem, the packet must be transmitted to the bridge, then the bridge can put a signal on the wire. This is at least 1ms delay, so the very best speed at which you can accomplish this is 9600 baud, most likely much less.Unlike the serial era, today's UARTs can easily work at several Mbaud. There's no way to come even close if you send flow control signals from PC.

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: April 24, 2020, 09:43:48 am
content: RS232 has always been a can of worms...No hardware flow control:1) Most (decent) USB-Serial dongles have RTS/CTS. If you're making one, be sure to provide RTS/CTS.2) Most USB-Serial dongles have hardware flow control AND IT'S ALWAYS ENABLED AND CAN'T BE DISABLED.3) Most serial devices *used* to have RTS/CTS signal pins, but nowadays not so often.4) /CTS is the (important!) input that when LOW means "the other end is ready for more".5) /CTS is driven by the other end RTS.6) To disable hardware flow control just leave /CTS disconnected and make sure that it always stays LOW, at both ends, no matter what.7) Some devices read LOW at /CTS when it's left unconnected, some don't. Watch out for that and act accordingly.RTS doesn't matter at all for this to work and can be ignored. NC.Hardware flow control:1) Just connect the DTR of one end to the /CTS of the other end, and viceversa, and it will work.2) The hardware flow control of most (decent) USB-Serial dongles is ALWAYS ENABLED because it has a buffer that can be overflowed w/o it. If you want to take that risk, up to you, see above and leave /CTS disconnected (and make sure it's LOW).The thing is, many, many devices have shallow RX buffers (e.g. ATMEGAs have two bytes) and need a way to cut the traffic when/if they can't keep up for any reason (e.g. 250000 baud and noInterrupts() ?). It's better to connect and use DTR/CTS flow control, unless the upper layer protocol can detect overruns, which isn't always the case.

author: westfw
author_rank: Super Contributor
timestamp: April 24, 2020, 11:50:29 pm
content: QuoteThat's for sure. For example, "hardware flow control" does not officially exist. "They" took some rarely-used modem signals aimed at half-duplex communications and STRETCHED their meanings quite a lot to get the "cts""/"rts" means you can send me data right now (depending on whether you're DTE/DCE.) But you're still unlikely to find specs for exactly when cts should be de-asserted, or how much a transmitter can "skid" after it sees that. Hardware support based on deep FIFOs and configurable setpoints is ideal. Microcontrollers with 1 byte of buffer (plus a shift register) and dependence on an ISR manipulating CTS is software ... probably problematic.QuoteIIRC, actual rs232 ports 'float" in the wrong direction. Leave CTS disconnected, and the port would decide that it was flow-controlled and couldn't send anything. This led to one of the famously "is this the right cable?" designs with pins 4,5, 6, and maybe 20 jumpered together on each end (RTS, DSR, CTS and maybe DTR)I'm not sure I'd trust USB/UART (with no rs232) float states. But of course you can fix that in hardware.I'm also nor sure that it makes sense for a PC-like endpointto be ableto manipulate the state of HW flow control at the "other end" of the serial connection. As others have pointed out, that's "very distant" timing-wise, and is in theory a matter solely for the "local" connection between the micro and USB chip.Note that many of the popular USB/Serial chips (FTDI, CH340) have their own drivers that at least theoretically go beyond the limits of what is defined in CDC/ACM...

author: Fabian
author_rank: Contributor
timestamp: April 25, 2020, 07:47:48 pm
content: Thanks a lot, again!But the buttom line is still, that my micro cannot tell if the user (pc program I cannot modify!) turned hardware flow control on or not. I have to handle that either by telling it the micro in advance (using buttons, special USB stuff, ...) or use pull-resistors to fake an always ready DCE.

author: cv007
author_rank: Frequent Contributor
timestamp: April 26, 2020, 09:02:17 am
content: >But the buttom line is still, that my micro cannot tell if the user (pc program I cannot modify!) turned hardware flow control on or not.Your micro does not have to know.Your SAM can provide 4 pins to its target device (tx, rx, cts, rts). The SAM cts pin is weakly pulled to an asserted state. The target device can use or not use the cts/rts pins provided, and if not used you get no flow control. If used, you assume they must have the hardware to do cts/rts so you get flow control between SAM and the target device. Your target connections determines flow control, no software involved. The SAM is coded to use hardware flow control, so uses the cts/rts pins, but if not used by the target device the weakly asserted cts pin effectively disables flow control.The SAM to PC connection already has 'flow control' in the form of usb.

author: Fabian
author_rank: Contributor
timestamp: April 26, 2020, 09:27:04 am
content: So the second option.

author: cv007
author_rank: Frequent Contributor
timestamp: April 26, 2020, 10:27:02 pm
content: >So the second option.>or use pull-resistors to fake an always ready DCE.Except you are not faking anything. You really have hardware flow control when the target is capable and has hooked up the connections. If they want to only use rx/tx, then there is no hardware flow control. In either case the choice is made in the connection, and software settings never enter the picture.