Compiling Kernel Modules for Jetson TX1

I have to build some kernel modules for working with some USB/Serial devices using the Jetson TX1. I have already marked the needed modules using the “menuconfig”, but I couldn’t manage to compile then afterwards.

How do I compile kernel modules for Jetson TX1? I prefer building in the Jetson itself, rather than using a Linux host.

Thank you!

Unfortunately, right now my TX1 has actually turned into my main machine due to catastrophic failure of my x86_64 desktop, so testing and experimenting isn’t possible. What you do need to know is that kernel and module compile on TX1 is currently recommended to be cross compiled on a desktop system. The reason is that the initial release of R23.1 for JTX1 is a mix of a 64-bit kernel and some 32-bit user space…two compilers are required. Setting up both compilers on the TX1 has not been found to be particularly advantageous. A later release of L4T on JTX1 will migrate to all 64-bit, but for now it isn’t there.

I am trying to cross-compile the kernel from source code, using the existing .config file from my Jetson TX1 (from /proc/config.gz). But when I try to build the modules (“make modules”), I get an error telling that my kernel directory is not clean, and I should run “make mrproper”. But when I run this command, it erases my .config file.

Am I doing something wrong? Is there some way to use the existing .config file?

A while ago I put up an experimental module build for the FTDI driver on the Jetson TX1:

The scripts downloads the kernel source, decompresses the config.gz file, adds the local version number, adds the FTDI module and then makes the module.

Before doing all that you’ll have to install the 64 bit extensions to gcc, there’s a script in there for that too.

In your case, you’ll have to modify the script and config file for the modules you’ll need, but at least this is an outline.

Just to be safe, I would suggest a fresh install in L4T 23.1, build your modules, save your modules off of the Jetson after they are built, reinstall L4T 23.1, and then install the modules appropriately. If you want to live on the edge, you won’t do the reinstall, but you’ll want to save the module and config file off board in any case.

I think the intent is that you build everything on a host which makes it easier to deal with a 64 bit kernel/32 bit OS on the TX1, but I haven’t encountered any issues with the FTDI driver that I surreptitiously built.

Thank you! I managed to build the modules based on your scripts and steps!

I built the kernel module based on the steps above but when i try do insmod on another Tx1 board, I get get Invalid file format error. The uname -r command on both boards return different version magics.
How do I overcome this.


Normally you’d build a module separately on each different uname -r. A different uname -r and different module directory is typically required if a non-module feature is compiled or changed. I see the script only changes a module versus the existing and running config, so that should be fine…provided the second Jetson matches the first Jetson. If the two do match, I’d be curious why the uname -r differs between the two of them. Were kernels updated differently between the two Jetsons?

Thanks for the reply. Solved the problem. One of the Jetson had default kernel as received. Reflashing R23 again solved the problem. But now I am getting another issue, the device I am using is a Peak USB to CAN device. I could inster the Ko. The dmesg show the devices is detected and no error.
I can see received data with cat /dev/pcan32 and send the data using echo > /dev/pcan32.

But when I use the provided receiving and transmitting application. I receive ioctl not supported for the device error. What can be the issue ? Do I need to build the CAN libs with 32 bit or 64 bit toolchain.


This is just a guess, but I’d start by thinking of a kernel feature which supports the operation of the ioctl. Sometimes you get one kernel module or feature which supports making a device available in a given format, but still requires some other feature for a protocol used with the device. For example, you could have a module for a network adapter, yet still need other modules for different network protocols. In your situation, you have a USB driver, which would have been there by default; then the USB driver would have had to point to the device itself at a driver (and create the device special file)…all of which seems successful. I do not know protocols related to CAN bus, but some of the kernel options will probably mention this as a feature related to CAN bus (documentation from the device or application using the device may even tell you this one without having to dig too deeply).

I found the issue if I build the so fils for CAN device with 64 bit toolchain it works but if i have 32 bit “so” it does not work. My application requires cuda and can so need both. Please help.

I tried by using the 64 bit “so” with 32 bit but that does not work :(

Are you using cross-compile with both CROSS_COMPILE and CROSS32CC set?

sorry did not get your question but I am compiling everything on Tx1 so no cross compilation. I compiled the CAN so fisrt with 32 bit and ko with 64 bit and it did not work. so to test i compiled both with 64 bit and it works. But now my problem may application requires cuda so no option but tohave 32 bit tools. But only Can so cannot be 64 bit with application being 32 bi

The kernel is 64-bit, but most everything else is 32-bit (until the next release a few months from now…I’m not sure if that’ll be R23.3 or go all the way to an R25.x release, but it’ll unify everything into the 64-bit world). Due to the mixed 32/64-bit, the native compile environment on a JTX1 does not yet support correct compile of kernel code, thus cross-compile is recommended to simplify life (it isn’t often I say cross-compile and simplify in the same phrase, but in this case it is true). Right now only user space compile on JTX1 works natively without special efforts.

So to cross-compile from an x86_64 host, you’d need a tool chain for 64-bit with its prefix named in CROSS_COMPILE; you would need the full path of just the 32-bit cc compiler named in CROSS32CC. I use the precompiled Linaro R5.2 binaries since I use Fedora…those with Ubuntu can probably just install them via the package manager.

If you choose to go the Linaro binary route, see:
…you would want latest-5.2, and within that, aarch64-linux-gnu for the 64-bit prefix of tools, and arm-linux-gnueabihf for the 32-bit gcc.

Thanks for the reply. I am using the ko now compiled with 64 bit toolchain and the device is detected propoerly. Since I cannot use the 64 bt so files with my 32 bit application. I am direclty using file operations with the device to read write for now.