A guide to solve USB serial driver problems on TX2

Some Arduino / USB Serial Converters use CH341 (or HL-340) which are not installed by the default jetpack. After struggling for a while, I solved the problem and decided to write this guide

Known Devices that might have this problem:
– Some Arduinos
– RS232 to USB serial converter

If you happen to have such device, by typing in command

lsusb

You might see “QinHeng Electronics HL-340 USB-Serial adapter”

I found out that HL-340 can be used after CH341 driver is enabled.
There was an outdated guide on eLinux for FTDI drivers. Fortunately, it can be easily applied to CH341 as well.

https://elinux.org/Jetson/Tutorials/Program_An_Arduino

Now,
download the source of your kernel from here at the bottom of the page
https://developer.nvidia.com/embedded/linux-tegra

extract the file, you will see kernel_src.tar.bz2 inside.
Extract kernel_src.tar.bz2 by

tar xvjf kernel_src.tar.bz2

cd into the extract folder, you will see hardware folder and a kernel folder
cd into kernel folder and then cd into kernel-4.4 folder

We then copy the config file to here

zcat /proc/config.gz > ./.config

edit the file,
find the line with “#CONFIG_USB_SERIAL_CH341

uncomment it and change it to CONFIG_USB_SERIAL_CH341=m

Next, find the line CONFIG_LOCALVERSION= ,
make it CONFIG_LOCALVERSION="-tegra"
This step is to avoid the version magic error.

Now,

make prepare
make modules_prepare
make M=drivers/usb/serial/
sudo cp drivers/usb/serial/ch341.ko /lib/modules/$(uname -r)/kernel
sudo depmod -a

Now plug in your serial device and type in dmesg | grep ch341
You should see the device attached to ttyUSB*

The procedure may also be applied to other serial devices, but I found ch341 one of the most common one.

1 Like

Thanks for the sharing from https://devtalk.nvidia.com/default/topic/1026162/

1 Like

Thanks for the guide!

I was trying to do this with R28.2.1 and there doesnt seem to be a kernel_src.tar.bz2 anywhere.

Any idea how I should proceed?

If you download the driver package for your release (and this is automatic if you ever used JetPack to flash since it is a front end to the driver package), then you will find “source_sync.sh” in the “Linux_for_Tegra/” directory. You can copy this script to any computer, e.g., a host PC or the Jetson itself. Then:

./source_sync.sh -k tegra-l4t-r28.2.1

(this shows for R28.2.1, other people can adjust the “tegra-l4t-”)

The source and other direct downloads are here, but you need to log in prior to it showing you anything…which means you might need to go there, log in, and then go there again:
https://developer.nvidia.com/embedded/linux-tegra

The “Jetson TX2 Sources” link (downloads “public_sources.tbz2”), when unpacked, has kernel_src.tbz2.

I have a rookie question here, that I cannot edit the config file. Always seeing the “version magic error”, Can anybady share the steps with me? PLEEEEEASE!

See (this centers on native compile…regular documentation is for cross compile, but the information here is probably relevant to you for either):
https://devtalk.nvidia.com/default/topic/1038175/jetson-tx2/tx2i-wifi-support/post/5274619/#5274619

Pay particular attention to the comments on “CONFIG_LOCALVERSION”.

I followed the procedures above to installed ch341 and FTDi driver, then I found a ch341 device on ttyUSB0 and successfully communicated with the devive. However, it soon disconnected from TX2 after a few seconds. and it showed
“usb_serial_generic_read_bulk_callback - nonzero urb status”
Could you please offer some help?
kernel version is 4.4.15-jetsonbot-v0.1
OS is ubuntu 16.04LTS
board is TX2

It sounds like you still had an application talking to the device at the time the cable was disconnected. If you were to do a fresh reboot with no devices attached, and then attach/detach the device without running any programs, does the same issue occur?

This is what i got after a fresh reboot

nvidia@tegra-ubuntu:~$ dmesg | grep tty
[    0.000000] Kernel command line: fbcon=map:0 net.ifnames=0 console=tty0 OS=l4t console=ttyS0,115200n8 memtype=0 video=tegrafb no_console_suspend=1 earlycon=uart8250,mmio32,0x03100000 gpt tegraid=18.1.2.0.0 tegra_keep_boot_clocks maxcpus=6 android.kerneltype=normal androidboot.serialno=0335115020673 vpr_resize root=/dev/mmcblk0p1 rw rootwait
[    0.022399] console [tty0] enabled
[    1.937767] console [ttyS0] disabled
[    2.347272] 3100000.serial: ttyS0 at MMIO 0x3100000 (irq = 36, base_baud = 25500000) is a Tegra
[    2.396973] console [ttyS0] enabled
[    2.414859] 3110000.serial: ttyTHS1 at MMIO 0x3110000 (irq = 37, base_baud = 0) is a TEGRA_UART
[    2.431709] 3130000.serial: ttyTHS3 at MMIO 0x3130000 (irq = 38, base_baud = 0) is a TEGRA_UART
[    6.404913] systemd[1]: Created slice system-serial\x2dgetty.slice.
[    6.564806] systemd[1]: Created slice system-getty.slice.

Then I attached my device it added

[  213.007417] usb 1-2: ch341-uart converter now attached to ttyUSB0

After I started communication for a few seconds it disconnected and sometimes it reconnected to ttyUSB1 automatically, which I think may account for the error according to your reply.

I assume this is the same system which has the other forum posts…basically follow those (but I think in one you said you got it to work, so you can probably ignore this reply).

Just a hint: In most cases when you add a driver you simply need to add a module and not change the kernel itself. Once you go down the road of changing the whole kernel you have to find a starting config which basically matches the running system, and then install both the kernel and the entire module directory tree.

I have done everything according to guide, but dmesg | grep ch341 gives me this error:
[21944.878711] ch341: version magic ‘4.4.38-tegra+ SMP preempt mod_unload aarch64’ should be ‘4.4.38-tegra SMP preempt mod_unload aarch64’
What is wrong?

my l4t version:
R28 (release), REVISION: 2.1, GCID: 11272647, BOARD: t186ref, EABI: aarch64, DATE: Thu May 17 07:29:06 UTC 2018

to get sources of my version i used:
./source_sync.sh -k tegra-l4t-r28.2.1

This is the issue:

4.4.38-tegra<b><i><u>+</u></i></b>

That “+” is getting in the way and is essentially editing the CONFIG_LOCALVERSION without you knowing it. In your kernel source, edit file “scripts/setlocalversion”. Look for function “scm_version()”. Edit the start of this to return without modifying what you’ve set as CONFIG_LOCALVERSION:

scm_version()
{
        local short
        short=false
        **return**

Make clean, and then build again.

The boyuan99’s guide perfectly works.
Thank you very much for sharing information!