Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flow control or write-throttling #573

Open
jskubick opened this issue Sep 25, 2024 · 0 comments
Open

Flow control or write-throttling #573

jskubick opened this issue Sep 25, 2024 · 0 comments

Comments

@jskubick
Copy link
Contributor

jskubick commented Sep 25, 2024

I have two computers (running OSX and Windows 11 respectively) connected to each other through a pair of CP2102n USB-UART serial ports, wired up as a null modem as follows:

  • ground to ground
  • tx to rx, rx to tx
  • cts to rts, rts to cts

Now, let's suppose I open the port:

// 'port' is an instance of SerialPort
port.openPort();
port.setFlowControl(SerialPort.FLOW_CONTROL_CTS_ENABLED | SerialPort.FLOW_CONTROL_RTS_ENABLED);
port.setBaudRate(3000000);
port.addDataListener(myEventHandler);

... and now, I have to somehow shovel a few hundred megabytes of data over that serial link, spoonfeeding JSerialComm's SerialPort something like 64 or 128 bytes at a time... at a rate that ideally keeps the actual UART-to-UART serial link completely saturated at 3mbps, without overflowing the 512-byte transmit buffer (in the cp2102n) sitting between the USB bus and the actual UART.

Is there anything special I need to do, or somewhere between JSerialComm's SerialPort.writeBytes() and the low-level port driver, is there logic in place to either pause writing bytes when the TX buffer (on the cp2102n) gets full, abort and return -1, etc?

If you happen to know & wouldn't mind elaborating, what actually happens when the transmit buffer of a USB-UART bridge actually fills up? I'd love to know, and it's really hard to find information like this :-)

Purely speculating, I can think of a few possibilities (all or most of which are probably wrong):

  • writeBytes() passes a 64-byte chunk to the OS, which passes them to the USB driver, which sends them over the USB cable to the cp2102n.
    • The cp2102n accepts 17 of the bytes and puts them in the TX buffer. A moment later, a control packet from the host asks what happened, and it sends a reply that means something like, "17 bytes were accepted". The reply eventually makes its way back to JSerialComm's SerialPort, which returns 17.
    • The cp2102n sees 64 bytes, knows it only has room for 17, and discards them all. A moment later, the host polls the cp2102n, which gives a reply that indicates "the previous request was discarded", and ultimately causes JSerialComm's SerialPort to return -1.
  • writeBytes() passes a 64-byte chunk to the OS, which accepts them and says "thank you". JSerialComm's SerialPort.writeBytes() returns 64 and calls it a day, even if some or all of that 64 byte chunk ultimately gets rejected by the cp2102n at the other end of the USB cable.
  • A variant of the above... except, behind the scenes, the OS and/or host-side USB driver maintains its own large buffer to hold outbound data until it's able to ferry it along to the USB bridge chip on the other side of the USB cable... which probably works automagically, until the day you try to shovel a gigabyte or two into it and it blows up because it can't locally-buffer that much outbound data.
  • Something more subtle, like overloading the "CTS" state presented to the host so that it COMBINES "ability of the remote host to accept data, as indicated by the remote RTS pin driving the local CTS pin" with "ability of the local TX buffer to absorb more outbound data without overflowing" and asserts only when BOTH are true.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant