I successfully applied the recommended patch to the SPI driver (spi-tegra114.c
), along with the CS pin patch, and built a custom kernel on JetPack 5.1 (L4T 35.2.1). The kernel was compiled directly on the Jetson, without cross-compilation
Here are the steps taken:
-
Download sources from https://developer.nvidia.com/embedded/jetson-linux-r3521:
- copy link from
Driver Package (BSP) Sources
- copy link from
-
On the Jetson:
mkdir custom-kernel cd custom-kernel wget https://developer.nvidia.com/downloads/public-sourcestbz2 # copied on prev step tar -xvf public-sourcestbz2 cd Linux_for_Tegra/source/public/kernel tar -xvf kernel_src.tbz2 cd kernel-5.10
These steps will make files available such as the SPI driver we want to patch (
Linux_for_Tegra/source/public/kernel/kernel-5.10/drivers/spi/spi-tegra114.c
). -
After applying the suggest patch for JP 5.1 in Orin NX SPI delay between transfers - #21 by KevinFFF and the CS pin patch from Jetson orin nano SPI Speed not changing - #9 by KevinFFF we get the resulting file:
spi-tegra114-patch-JP5.1-l4t35.2.1.c.txt (57.5 KB)
(note that I had to change the file extension to .txt to upload, but that is a .c file)
-
Copy the contents of that file into
Linux_for_Tegra/source/public/kernel/kernel-5.10/drivers/spi/spi-tegra114.c
and save it. -
Get possible default kernel configurations:
$ ls custom-kernel/Linux_for_Tegra/source/public/kernel/kernel-5.10/arch/arm/configs/ defconfig tegra_defconfig defconfig_debug.config tegra_defconfig_debug.config tegra_android_defconfig
-
Kernel build and installation:
cd custom-kernel/Linux_for_Tegra/source/public/kernel
# Load the correct kernel configuration
sudo make O=../build/ tegra_defconfig
# Prepare the kernel build environment
sudo make O=../build/ modules_prepare
# Compile the full kernel (including changes to SPI driver)
sudo make O=../build/ -j$(nproc)
# Compile and install kernel modules (including spi-tegra114.ko)
sudo make O=../build/ modules_install
# Update module dependencies
sudo depmod -a
# Copy the new kernel Image to the boot directory
sudo cp ../build/arch/arm64/boot/Image /boot/Image-Custom-Kernel
- Update the boot configuration
- Check the current contents of
/boot/extlinux/extlinux.conf
. In my case, there was a config labelled asJetsonIO
that was being used and running successfully. So I copied that and only changed the boot label and path to the new kernel image:
TIMEOUT 30
#DEFAULT JetsonIO
DEFAULT CustomKernelTest
LABEL CustomKernelTest
MENU LABEL Custom Kernel Test
LINUX /boot/Image-Custom-Kernel
FDT /boot/kernel_tegra234-p3701-0000-p3737-0000-user-custom.dtb
INITRD /boot/initrd
APPEND ${cbootargs} root=PARTUUID=4c1c9478-c986-4839-8cc2-f773fbfac931 rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 console=ttyAMA0,115200 console=tty0 firmware_class.path=/etc/firmware fbcon=map:0 net.ifnames=0
LABEL JetsonIO
MENU LABEL Custom Header Config: <HDR40 User Custom [2024-10-08-125801]>
LINUX /boot/Image
FDT /boot/kernel_tegra234-p3701-0000-p3737-0000-user-custom.dtb
INITRD /boot/initrd
APPEND ${cbootargs} root=PARTUUID=4c1c9478-c986-4839-8cc2-f773fbfac931 rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 console=ttyAMA0,115200 console=tty0 firmware_class.path=/etc/firmware fbcon=map:0 net.ifnames=0
Be aware that if the kernel image used by CustomKernelTest is faulty, the Jetson may fail to boot. In such a case, you’ll need to connect a monitor and keyboard to manually roll back to the JetsonIO option (in this example) during boot.
It appears that /boot/extlinux/extlinux.conf
supports configuring a fallback kernel, based on the default comments in the file. However, I have not explored this option.
-
Make a note of what
uname -r
returns to compare after rebooting. -
Reboot the Jetson.
-
Run
uname -r
, it should have changed from the previous value. In my case it changed from5.10.104-tegra
to5.10.104
(I basically used this to flag that something had actually changed after the reboot). -
When back up:
# Enable spidev
sudo modprobe spidev
$ lsmod | grep spi
spidev 28672 0
spi_tegra114 28672 0
Which I believe is what’s required to run SPI applications on the Jetson.
- Run your application.
- In my case I tweaked the code from https://raw.githubusercontent.com/torvalds/linux/v4.9/tools/spi/spidev_test.c to log SPI write time (did not change any functionality) which allowed me to gather logs which I later parsed and graphed. Below are the SPI write time results over two 5min tests of SPI writing “on a loop as fast as possible”:
Before:
Avg: ~240 µs
Median: 240 µs
Stdev: ~51 µs
After
Avg: ~58 µs
Median: 56 µs
Stdev: ~31 µs
The patch seemed to result in better SPI performance and more consistent write times.
As a sanity check confirmed on a logic analyser that the code was indeed writing out data via SPI and got the expected byte sequence:
I will try next on Jetpack 6.2.
Extra: Deploying a Kernel image to multiple devices
-
It’s also possible to reuse the new kernel image in other Jetson Orin devices running the same Jetpack and L4T versions. On the target device:
- copy the newly created kernel image to
/boot
- if the source device is currently running the new kernel image, get (maybe zip) the contents of
ls /lib/modules/$(uname -r)/
from the source device and copy (and unzip) to/lib/modules/
on the target device - edit
/boot/extlinux/extlinux.conf
accordingly as explained above - reboot the target device
- copy the newly created kernel image to