UART pins 8 and 10 not working even with loopback test

Hi dear developers,

I am using Jetson Xavier NX Developer Kit with the following Jetpack version:
nvidia-l4t-core 32.6.1-20210726122859
# R32 (release), REVISION: 6.1, GCID: 27863751, BOARD: t186ref, EABI: aarch64, DATE: Mon Jul 26 19:36:31 UTC 2021

I am facing a problem using the UART from pins 8 and 10 (BOARD mode). My setup is very simple: I am trying a loopback for self test. I used a jumper to connect those two pins. But still there is no connection (e.g. minicom is offline on all ports of available ls /dev/ttyTHS* ).

I’ve noticed something strange. When I run sudo /opt/nvidia/jetson-io/config-by-function.py -l all, I get:
Header 1 [default]: Jetson 40pin Header
Supported functions (pins):

  1. aud_mclk (7)
  2. dmic4 (35,38)
  3. dspk0 (12,40)
  4. dspk1 (35,38)
  5. extperiph3_clk (29)
  6. extperiph4_clk (31)
  7. i2s5 (12,35,38,40)
  8. pwm1 (33)
  9. pwm4 (15)
  10. pwm8 (32)
  11. spi1 (19,21,23,24,26)
  12. spi3 (13,16,18,22,37)
  13. uarta-cts/rts (11,36)
    Header 2: Jetson Nano CSI Connector
    No functions are supported.
    Header 3: Jetson M.2 Key E Slot
    Supported functions (pins):
  14. dmic1 (8,14)
  15. dmic2 (10,12)
  16. i2s3 (8,10,12,14)

Pins 8 and 10 are only available in header 3 despite that they are not enabled there.
sudo /opt/nvidia/jetson-io/config-by-function.py -l enabled
I get:
Header 1 [default]: Jetson 40pin Header
Enabled functions (pins):

  1. pwm1 (33)
  2. pwm8 (32)
  3. spi1 (19,21,23,24,26)
  4. spi3 (13,16,18,22,37)
    Header 2: Jetson Nano CSI Connector
    No functions are enabled.
    Header 3: Jetson M.2 Key E Slot
    No functions are enabled.

And by running sudo /opt/nvidia/jetson-io/jetson-io.py, I do not see UART function corresponding to pins 8 and 10 to enable it (see attached).
Screenshot 2024-10-01 143748

I even tried to overlay the device tree by creating a custom.dtb and point to it in extline.config, but with no success.

the content of the custom dtb is:

/dts-v1/;
/plugin/;

/ {
    compatible = "nvidia,p3509-0000+p3668-0000", "nvidia,jetson-xavier-nx", "nvidia,tegra194";

    fragment@0 {
        target = <&tegra_main_gpio>;
        __overlay__ {
            gpio14 {
                nvidia,pins = "gpio14";
                nvidia,function = "gpio";
                nvidia,pull = <0>; /* 0: no pull, 1: pull-down, 2: pull-up */
                nvidia,tristate = <1>; /* 0: enable, 1: disable */
                nvidia,enable-input = <1>;
            };
            gpio15 {
                nvidia,pins = "gpio15";
                nvidia,function = "gpio";
                nvidia,pull = <0>; /* 0: no pull, 1: pull-down, 2: pull-up */
                nvidia,tristate = <1>; /* 0: enable, 1: disable */
                nvidia,enable-input = <1>;
            };
        };
    };
};

and I added fdtdir /boot/dtb/ fdt custom_uart810_pinmux.dtb to the end of APPEND in extlinux.config

I do not think that is normal. Why can I not use the uart as supposed? I will appreciate any guidance to help me fix this issue.

Hi Berr00,

UART is not enabled through Jetson-IO tool.
You have to enable it from the device tree.

Please decompile the /boot/dtb/kernel_XXX.dtb to DTS and share this device tree.
And also the full dmesg for further check.

Example decompile, if your tree is file custom_uart810_pinmux.dtb:
dtc -I dtb -O dts -o source.dts custom_uart810_pinmux.dtb
(then attach source.dts to the forum thread)

Thank you guys for the help. I really appreciate it. I attached the required files.

dmesg.txt (70.7 KB)
kernel_tegra194-p3668-all-p3509-0000.txt (253.1 KB)

[    1.680515] 3100000.serial: ttyTHS0 at MMIO 0x3100000 (irq = 47, base_baud = 0) is a TEGRA_UART

From the log you shared, it seems UART1 has been enabled correctly.

Could you short PIN8 and PIN10 from 40-pins expansion header and run the following commands to verify loopback test?

$ sudo su
# stty -F /dev/ttyTHS0 115200 raw -echo
# cat /dev/ttyTHS0 &
# echo "test" > /dev/ttyTHS0

I did not get “test” and a result of running the above commands. I got literally nothing except for the process number I got when I run the cat /dev/ttyTHS0 & command.

Untitled

What do you see from:
ls -l /dev/ttyS* /dev/ttyTHS*

I got the following output:

crw-rw---- 1 root dialout   4, 64 Jul 21  2021 /dev/ttyS0
crw-rw---- 1 root dialout   4, 65 Jul 21  2021 /dev/ttyS1
crw-rw---- 1 root dialout   4, 66 Jul 21  2021 /dev/ttyS2
crw-rw---- 1 root dialout   4, 67 Jul 21  2021 /dev/ttyS3
crw--w---- 1 root tty     238,  0 Okt 14 17:54 /dev/ttyTHS0
crw-rw---- 1 root dialout 238,  1 Jul 21  2021 /dev/ttyTHS1
crw-rw---- 1 root dialout 238,  4 Jul 21  2021 /dev/ttyTHS4

Those with group dialout are available. “/dev/ttyTHS0” is not available, it is group tty. That group means it is a serial console. Using this with some other program will basically result in gibberish if you are lucky (suppose you echo something with the characters “rm *”; the result won’t be good).

When I run the following command: cat /proc/cmdline, I get:
console=ttyTCU0,115200 video=tegrafb earlycon=tegra_comb_uart,mmio32,0x0c168000 gpt rootfs.slot_suffix= tegra_fbmem=0x800000@0xa06b2000 lut_mem=0x2008@0xa06af000 usbcore.old_scheme_first=1 tegraid=19.1.2.0.0 maxcpus=6 boot.slot_suffix= boot.ratchetvalues=0.4.2 vpr_resize sdhci_tegra.en_boot_part_access=1 quiet root=PARTUUID=806e6259-cae1-4d1c-b3d6-e6a870904528 rw rootwait rootfstype=ext4 console=ttyTCU0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 fdtdir /boot/dtb/ fdt custom_uart810_pinmux.dtb

The output means that the port (/dev/ttyTHS0) is not being used by primary console.

When I run (sudo lsof /dev/ttyTHS0) to see who is using the port, I got:

lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
      Output information may be incomplete.
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
getty   6286 root    0u   CHR  238,0      0t0 8401 /dev/ttyTHS0
getty   6286 root    1u   CHR  238,0      0t0 8401 /dev/ttyTHS0
getty   6286 root    2u   CHR  238,0      0t0 8401 /dev/ttyTHS0

Which seems it is being used for user login through headless serial connection. But I still get this exact result even if I stop, disable, and mask the getty service:

sudo systemctl stop getty@ttyTHS0.service
sudo systemctl disable getty@ttyTHS0.service
sudo systemctl mask getty@ttyTHS0.service
sudo systemctl status getty@ttyTHS0.service

:

getty@ttyTHS0.service - Getty on ttyTHS0
   Loaded: loaded (/lib/systemd/system/getty@.service; enabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:agetty(8)
           man:systemd-getty-generator(8)
           http://0pointer.de/blog/projects/serial-console.html

After a reboot, I see again the same getty’s processes as a result of running (sudo lsof /dev/ttyTHS0).

To see any other services on a system level which could use getty, I run sudo systemctl list-units --all | grep getty and got:

getty-static.service                 loaded    inactive dead      getty on tty2-tty6 if dbus and logind are not available              
getty@tty1.service                   loaded    inactive dead      Getty on tty1                                                        
getty@tty7.service                   loaded    inactive dead      Getty on tty7                                                        
nvgetty.service                      loaded    active   running   UART on ttyTHS0                                                      
serial-getty@ttyGS0.service          loaded    active   running   Serial Getty on ttyGS0                                               
serial-getty@ttyS0.service           loaded    inactive dead      Serial Getty on ttyS0                                                
serial-getty@ttyTCU0.service         loaded    active   running   Serial Getty on ttyTCU0                                              
system-getty.slice                   loaded    active   active    system-getty.slice                                                   
system-serial\x2dgetty.slice         loaded    active   active    system-serial\x2dgetty.slice                                         
getty-pre.target                     loaded    inactive dead      Login Prompts (Pre)                                                  
getty.target                         loaded    active   active    Login Prompts

and this command: sudo systemctl list-units --all | grep serial and its output:

  dev-serial-by\x2did-usb\x2d1a86_USB_Serial\x2dif00\x2dport0.device                                 loaded    active   plugged   HL-340 USB-Serial adapter                                            
  dev-serial-by\x2dpath-platform\x2d3610000.xhci\x2dusb\x2d0:2.3:1.0\x2dport0.device                 loaded    active   plugged   HL-340 USB-Serial adapter                                            
  sys-devices-3100000.serial-tty-ttyTHS0.device                                                      loaded    active   plugged   /sys/devices/3100000.serial/tty/ttyTHS0                              
  sys-devices-3110000.serial-tty-ttyTHS1.device                                                      loaded    active   plugged   /sys/devices/3110000.serial/tty/ttyTHS1                              
  sys-devices-3140000.serial-tty-ttyTHS4.device                                                      loaded    active   plugged   /sys/devices/3140000.serial/tty/ttyTHS4                              
  sys-devices-platform-serial8250-tty-ttyS0.device                                                   loaded    active   plugged   /sys/devices/platform/serial8250/tty/ttyS0                           
  sys-devices-platform-serial8250-tty-ttyS1.device                                                   loaded    active   plugged   /sys/devices/platform/serial8250/tty/ttyS1                           
  sys-devices-platform-serial8250-tty-ttyS2.device                                                   loaded    active   plugged   /sys/devices/platform/serial8250/tty/ttyS2                           
  sys-devices-platform-serial8250-tty-ttyS3.device                                                   loaded    active   plugged   /sys/devices/platform/serial8250/tty/ttyS3                           
  serial-getty@ttyGS0.service                                                                        loaded    active   running   Serial Getty on ttyGS0                                               
  serial-getty@ttyS0.service                                                                         loaded    inactive dead      Serial Getty on ttyS0                                                
  serial-getty@ttyTCU0.service                                                                       loaded    active   running   Serial Getty on ttyTCU0                                              
  system-serial\x2dgetty.slice                                                                       loaded    active   active    system-serial\x2dgetty.slice

When I run (grep -r "ttyTHS0" /etc/systemd/) I see:

/etc/systemd/nvgetty.sh:                setsid /sbin/getty -L 115200 ttyTHS0
/etc/systemd/system/nvgetty.service:Description=UART on ttyTHS0

Which points to nvgetty.service to be responsible for using /dev/ttyTHS0.
I stopped and disabled it:

sudo systemctl stop nvgetty.service
sudo systemctl disable nvgetty.service

and did a reboot. Indeed to getty’s processes are not running anymore. But when I execute the loopback UART test suggested above, I still get no echoed “test” back.

Is there a way to use the GPIO pins 8 and 10 (BOARD numbering) for personalized UART connection to an external hardware (in my case an ESP32; I am connecting them through a USB port but I would like to do it through GPIO UART pins)? What do you guys suggest here? What are my options? I very appreciate your insights.

Even when I change the ownership of ttyTHS0 to dialout (instead of tty) after disabling all the services using it (sudo chown root:dialout /dev/ttyTHS0 and sudo chmod g+rw /dev/ttyTHS0), the loopback test did not succeed.

ls -l /dev/ttyS* /dev/ttyTHS* and the output:

crw-rw---- 1 root dialout   4, 64 Okt 16 13:39 /dev/ttyS0
crw-rw---- 1 root dialout   4, 65 Okt 16 13:39 /dev/ttyS1
crw-rw---- 1 root dialout   4, 66 Okt 16 13:39 /dev/ttyS2
crw-rw---- 1 root dialout   4, 67 Okt 16 13:39 /dev/ttyS3
crw-rw---- 1 root dialout 238,  0 Okt 16 13:39 /dev/ttyTHS0
crw-rw---- 1 root dialout 238,  1 Okt 16 13:39 /dev/ttyTHS1
crw-rw---- 1 root dialout 238,  4 Okt 16 13:39 /dev/ttyTHS4

As noted in my initial question: I do not see GPIO pins 8 and 10 (UART1 or uarta) in /opt/nvidia/jetson-io/jetson-io.py in order to enable it.

After the port has nvgetty.service stopped it should be available. However, this is not a real file, it is a driver living in RAM and pretending to be a file, so permissions do not work like a regular file. I suggest that you add your user to group dialout. Example, if your user name is “ubuntu”:
sudo usermod -aG dialout ubuntu

I don’t know for sure if that is the right device though for those pins. What I suggest is a loopback test. Jumper the TX to RX, and then open a serial console program as that user (which you just added to group dialout), with the settings to speed 115200, 8 bits, no parity, 1 stop bit (the default). Don’t use CTS/RTS flow control. See if you get echo. Nothing with group dialout is in use, so you are free to try your serial console program on each of those ports.

Note that the ttyS# ports are from a different driver than the ttyTHS# ports, but in general, because the hardware is compatible with both, you will find that two drivers each refer to one actual hardware port. I’m not sure which one corresponds to the other, but they might use different numbers. So I cannot guarantee (nor do I suggest) that there is a 1:1 correspondence between the numbering. It is possible that ttyS0 accesses the same UART as ttyTHS0. You shouldn’t use both at the same time, but there will be two device special files in /dev which go to that UART.

Incidentally, those pins are always available by default. I don’t think you need to modify anything for GPIO for that to work. If you have changed something, then perhaps it needs to be changed back. Just try each of those ttyS# and ttyTHS# one at a time with the TX and RX shorted together with loopback until you find the working file. Never do that with a port that has group tty, but have no fear of testing anything group dialout.

Non did result with an echoed “test”. I tried ttyTHS0, ttyTHS1, and ttyTHS4. While ttyS0, ttyS1, ttyS2, and ttyS3 gave an error: stty: /dev/ttyS0: Input/output error when runningstty -F /dev/ttyS0 115200 raw -echo.
In theory there should be an available UART for 40-pins but I cannot utilize it somehow, that is quite annoying.
Do I need to change anything in the device tree (that was the first diagnosis suggested above in the first answer)?

Please get a scope to check where’s the issue when you perform the loopback test.
(If TX sends data out, or RX receives data correctly.)

From previous results shared from you, you’ve configured it in device tree correctly.
Could you also verify with the latest R32.7.5 on the devkit?

I do know that this works for loopback I’ve tested (you might need to “sudo apt-get install gtkterm”; substitute ttyTHS2 with the actual terminal you use):
gtkterm -b 8 -t 1 -s 115200 -p /dev/ttyTHS2

Your other commands should work as well, but I know that this gtkterm command sets every parameter correctly in the command itself. Incidentally, when doing loopback, you never want the software to echo, it is the wire between TX and RX which echoes (otherwise it wouldn’t be “loopback”).

Thank you guys! I did not think the issue could be the hardware. I eliminated that option completely. But at the end I was able to bring another Jetson and it works following the instructions above.

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