ttyTHS0 CTS/RTS

I am using the Xavier NX /dev/ttyTHS0 device to control 2 dynamixel motors.

I am unable to understand if the CTS/RTS pin is working.

Using this example:

#!/usr/bin/python3
import time
import serial

print("UART Demonstration Program")
print("NVIDIA Jetson Nano Developer Kit")


serial_port = serial.Serial(
    port="/dev/ttyTHS0",
    baudrate=115200,
    bytesize=serial.EIGHTBITS,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    rtscts=True
)
# Wait a second to let the port initialize
time.sleep(1)

try:
    # Send a simple header
    serial_port.write("UART Demonstration Program\r\n".encode())
    serial_port.write("NVIDIA Jetson Nano Developer Kit\r\n".encode())


except KeyboardInterrupt:
    print("Exiting Program")

except Exception as exception_error:
    print("Error occurred. Exiting Program")
    print("Error: " + str(exception_error))

finally:
    serial_port.close()
    pass

I can observe the following with a digital pin analyzer.

The RTS pin is always LOW.
If CTS is HIGH, no data is written to the TX PIN. As soon as CTS is set to LOW, the data is written but RTS is still LOW.

So I understand that the CTS/RTS logic is working, because it waits for CTS to be LOW, but the RTS should be set to HIGH when not writing.

The pin configuration is correct as far as I know.

Hi victor.lopez1,

Are you using the devkit or custom board for Xavier NX?
What’s your Jetpack version in use?

Could you apply the following patch and check if it can help for your case?

diff --git a/drivers/dma/tegra-gpc-dma.c b/drivers/dma/tegra-gpc-dma.c
--- a/drivers/dma/tegra-gpc-dma.c
+++ b/drivers/dma/tegra-gpc-dma.c

 #include <linux/bitfield.h>
@@ -731,6 +731,9 @@ static int tegra_dma_get_residual(struct tegra_dma_channel *tdc)
 	bytes_xfer = dma_desc->bytes_xfer +
 		     sg_req[dma_desc->sg_idx].len - (wcount * 4);
 
+	if (dma_desc->bytes_req == bytes_xfer)
+		return 0;
+
 	residual = dma_desc->bytes_req - (bytes_xfer % dma_desc->bytes_req);
 
 	return residual;

Jetpack is 5.1.3
Using seed J202 carrier board.

I wil test this when I get to the office.

How would I apply the patch? Do I need to modify the sources then flash? Or is there a way to just copy the driver? Where are these sources?

Thank you

Yes, you should apply the patch in kernel source (kernel/kernel-5.10/drivers/dma/tegra-gpc-dma.c).
Please rebuild and update kernel image, you can also refer to Kernel Customization — NVIDIA Jetson Linux Developer Guide 1 documentation for details.

Still same behavior after modifying, building kernel and flashing.

The first time I start the script, the RTS goes to LOW, as the port is configured for CTS/RTS and it stays low during the transmission.

How can I try the non THS driver?
If I write to /dev/ttyS0 I get: write error: Input/output error (as super user)

Please modify the following line from the device tree.

	uarta: serial@3100000 {
- 		compatible = "nvidia,tegra186-hsuart";
+ 		compatible = "nvidia,tegra20-uart";

I have made that change to the device tree, and I see that ttyTHS0 disappears, and I can write to ttyS0.

ttyS0 behaves differently.

Without any configuration on boot, it does the following when I write a few bytes:
Screenshot from 2024-04-25 12-49-58

The RTS signal goes LOW when the transmission starts, which is what should happen, but stays LOW for much longer than the transmission. This is not good enough for us, as the dynamixels motors max delay before answering is 500 microseconds.

Also, if I use the Python code that I pasted on the original post, then RTS stays LOW for the whole duration python script, and I guess on exit it is cleared.

It should stay low when it is busy(tranmission). It seems just 10ms by default behavior.
Please check you UART application.

But if I enable CTSRTS as in the python example, it always stays low, as in the second image of my previous post, during the whole 1 second that the python application has the socket opened.

Can you share an example when it is performed correctly?

Can you try using the serial application like minicom to enable HW flow control and check the signal?

Sorry yesterday was bank holiday over here.

With nvidia,tegra20-uart minicom hardware flow control doesn’t seem to have any effect. When I enter minicom on /dev/ttyS0 it is already active, and as soon as I start minicom the RTS pin changes to LOW, and stays there the whole application, no matter what I write. Same behavior as the python script.

I changed the device tree back to use THS and with /dev/ttyTHS0 the results are the same, the pin changes to LOW upon minicom starts and to HIGH when exiting.

Do you enable HW flow control through minicom? (maybe you should use -s parameter to configure)

Is the result not expected? RTS is low when it is busy and will be high when it is idle.

I enable through the options, although it is enabled by default.

It should be low while transmitting afaik, and high the rest of the time, so another devices can wait until it is High before transmitting.

You should map the RTS from the jetson to the CTS of rhe other device.

yes, it seems matching with your current bahavior.

Any idea how to proceed? This is impacting us significantly and we have a deadline to meet soon.

Could you try to remove the dma* properties in device tree to check if it could help for your case?

uarta: serial@3100000 {
	compatible = "nvidia,tegra186-hsuart";
	iommus = <&smmu TEGRA_SID_GPCDMA_0>;
#if TEGRA_IOMMU_DT_VERSION >= DT_VERSION_2
	interconnects = <&mc TEGRA194_MEMORY_CLIENT_HOST1XDMAR>;
	interconnect-names = "dma-mem";
#endif
	dma-coherent;
	reg = <0x0 0x03100000 0x0 0x10000>;
	reg-shift = <2>;
	interrupts = <0 TEGRA194_IRQ_UARTA 0x04>;
	nvidia,memory-clients = <14>;
-	dmas = <&gpcdma 8>, <&gpcdma 8>;
-	dma-names = "rx", "tx";
	clocks = <&bpmp_clks TEGRA194_CLK_UARTA>,
		<&bpmp_clks TEGRA194_CLK_PLLP_OUT0>;
	clock-names = "serial", "parent";
	assigned-clocks = <&bpmp_clks TEGRA194_CLK_UARTA>;
	assigned-clock-parents = <&bpmp_clks TEGRA194_CLK_PLLP_OUT0>;
	resets = <&bpmp_resets TEGRA194_RESET_UARTA>;
	reset-names = "serial";
	nvidia,adjust-baud-rates = <115200 115200 100>;
	status = "disabled";
};

Removed the following properties, generated the .dtb, placed it somewhere and pointed /boot/extlinux/extlinux.conf to it and rebooted.

                dmas = <0x1b 0x08 0x1b 0x08>;
                dma-names = "rx\0tx";

After rebooting no signals were detecetd on the TX pin, it seems as if it was not writing at all.
The RTS pin went LOW when opening the device with minicom as before, but I could not TX any data.

Restoring those properties went back to the previous behavior (TX could be seen).

After removing those 2 lines, could you also modify the compatible as following to use 8250 driver?

- compatible = "nvidia,tegra186-hsuart";
+ compatible = "nvidia,tegra20-uart";

Same as with other experiments with ttyS0.

RTS goes to LOW when I open minicom, hardware flow control is enabled:

Stays low for the duration of the session, and doesn’t change when I write data:
Screenshot from 2024-05-10 10-26-30