The best serial port communication library for c++ in jetson tx1

Hi.
I want to communicate with other devices with serial port (UART) in my C++ application.
I don’t know what the best and easiest library for the C++ language is.
I have to read and write byte arrays and I want to flush the rx and tx line.
how can I do that?

If the port is already set up, then you just read or write the port like a file. You can also sync or flush like any other file.

Incidentally, if you were to use a C-style fprintf or read, you’d simply wrap it with extern “C”. You can use ordinary C++ I/O as well.

The default for Jetson ports is 115200 8N1. Traditionally, one would tend to use an ioctl call when setting up if the port is not already what you want for settings. If you use the C-style ioctl, then just wrap it extern “C”. Note that ioctl talks directly to the driver of the device you use it with, so the ioctl function depends on which driver runs the device special file.

Incidentally, look at who owns the device special file before using it. For example, if you are using “/dev/ttyTHS0”, then:
ls -l /dev/ttyTHS0

If the owner is console, then this is in use by serial console. If the owner is dialout, then it is free to use. If the group is dialout, then you could either operate on the port as root (sudo), or you could add your user to group dialout. If your user name is “nvidia”, then you could add your user to group dialout like this:
sudo usermod -aG dialout nvidia

@linuxdev
thank you for your help
could you please show me a sample code on this function that you say?
like read, write, and flush the rx and tx.
or let me know if there is any documentation for this method.
thank you

Just treat it like a file. Use fstream to open your device special file read/write. A nice example, although not specific to device special files:
https://www.guru99.com/cpp-file-read-write-open.html

Which serial port do you want to open? Perhaps it is something like “/dev/ttyTHS0”? If so, just substitute that for the file name in the example on that URL. From there flush() and sync() can be used, and those are members of your fstream() (or iostream). A great C++ reference is here:
https://cplusplus.com/reference/

You can look up the member methods to your stream class.

All of that assumes you’ve set up the port speed and settings. If you are running at speed 115200, 8-bit data, no parity bit, and one stop bit, then there is no need to change anything (and no need to deal with ioctl). To learn more about the C ioctl, if the man pages are installed, see “man ioctl”. More description:
https://en.wikipedia.org/wiki/Ioctl

I’m not sure I can give you a good ioctl description or example. When it comes to ioctl, the argument being passed depends on the particular driver which created the device special file. It is often said in any *NIX environment, e.g., Linux, that “everything is a file”. That’s true for reading, writing, opening, closing, dealing with buffers, so on. However, there are operations which simply don’t exist for some drivers. UARTs in general have a speed (baud rate), but regular files do not, and although ethernet has a speed, it isn’t set as a baud rate. Within UARTs it depends on the chipset driver what ioctl to use, e.g., you might find a different ioctl for changing something based on one manufacturer versus another. Historically, there are the older 16450 UARTs, then 16550 UARTs, then 16550A UARTs, which the Tegra SoCs can be set to emulate any one of those. The 16550A is what serial UARTs using the legacy port would use, and those in turn have the naming convention “/dev/ttyS#” (where # is a number from 0 or higher). That same UART might have a naming convention like “/dev/ttyTHS#”, which means a different driver created it, and this means the ioctl is custom to that driver.

FYI, files of the name “/dev/ttyS#” can be the same exact hardware as a file of the name “/dev/ttyTHS#”. This is the case because the Tegra UARTs are compatible with both legacy drivers and with their “Tegra High Speed” (THS) drivers, and when using the ttyTHS driver, DMA is available (but you don’t need to change anything to use DMA, it just happens if you use the ttyTHS device special file). You wouldn’t want to use both the ttyS# and ttyTHS# driver simultaneously, but look at this and you will see both versions exist:
ls -l /dev/ttyS* /dev/ttyTHS*

Trivia: The reason both exist is that (A) the UART can be set up as either, and (B) third party software used during boot, e.g., the bootloader itself, usually does not understand the ttyTHS version. The implication is that if you want a serial console to log or interact with the bootloader, when the bootloader software is from a third party, then you cannot use the ttyTHS driver unless you’ve customized the bootloader. Thus pretty much the only time people use the ttyS# legacy driver is if (A) the operation has to exist in boot stages, or (B) the software is from a third party which doesn’t understand that this is a serial UART.

As for the list of ioctl control calls which actually set up speed, parity, bits, stop bits, so on, I don’t know from memory. Someone from NVIDIA would have to give the ioctl calls for controlling the THS driver. Most people just set up the UART to default to what they want it to be during boot (which can be accomplished via the device tree). Are you ok with running with the default setting of 115200 baud, 8-bit, no stop bits, and one parity bit? If so, you don’t even need to worry about it.

1 Like

thank you so much for your help @linuxdev
your explanation was very helpful 🖐🌸
have a good day ❤

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.