Jetson/Porting Arch

From eLinux.org
Jump to: navigation, search

Introduction

This will go over the important steps of installing Arch Linux on the Jetson TK1. Including installing the kernel, drivers, and configuration from the Linux for Tegra release provided by NVIDIA. It will also provide steps for testing that the NVIDIA drivers have been installed correctly and are working correctly.

The first step is to download the latest TK1 Driver Package: https://developer.nvidia.com/linux-tegra

Extract the Jetson TK1 Driver Packages, which should contain a top folder called "Linux_for_Tegra".

 sudo tar jxpf <latest_l4t_driver_package>.tbz2
 cd Linux_for_Tegra     # We will refer to this directory as <path_to_L4T_TOP_DIR>
 cd rootfs              # We will refer to this directory as <path_to_L4T_rootfs>

Obtaining Image

The first step is to obtain the image for Arch Linux ARM and create the root filesystem from it.

The list of all Downloads can be found on the Downloads page on the Arch ARM website [1]

Specifically you will want the armv7 multi platform version, latest is linked here

wget http://archlinuxarm.org/os/ArchLinuxARM-armv7-latest.tar.gz

Extract the tar into your rootfs directory.

cd <path_to_L4T_rootfs>                                        
sudo tar -xpf ArchLinuxARM-armv7-latest.tar.gz .

Changes to the Apply Binaries script

apply_binaries.sh is a script found in drivers tarball of the L4T drivers package, located at <path_to_L4T_TOP_DIR>

As the apply_binaries script (apply_binaries.sh) was written to work with Ubuntu, and Ubuntu stores its libraries in a different place than Arch Linux, the script will need to be updated to look in the correct place.

Find the section of the file that looks like the below script, and add the two lines indicated:

if [ -d "${LDK_ROOTFS_DIR}/usr/lib/arm-linux-gnueabihf/tegra" ]; then
	ARM_ABI_DIR="${LDK_ROOTFS_DIR}/usr/lib/arm-linux-gnueabihf"
elif [ -d "${LDK_ROOTFS_DIR}/usr/lib/arm-linux-gnueabi/tegra" ]; then
	ARM_ABI_DIR="${LDK_ROOTFS_DIR}/usr/lib/arm-linux-gnueabi"
elif [ -d "${LDK_ROOTFS_DIR}/usr/lib/aarch64-linux-gnu/tegra" ]; then
	ARM_ABI_DIR="${LDK_ROOTFS_DIR}/usr/lib/aarch64-linux-gnu"
elif [ -d "${LDK_ROOTFS_DIR}/usr/lib/tegra" ]; then                     # Add this line
        ARM_ABI_DIR="${LDK_ROOTFS_DIR}/usr/lib"                         # and this one.
else
	echo "Error: None of Hardfp/Softfp Tegra libs found"
	exit 4
fi

Next, to preserve Arch's symbolic directory paths, find any lines that look like:

tar xpfm #...
tar jxpfm #...

And replace them so they look like:

tar --keep-directory-symlink -xpmf #...
tar --keep-directory-symlink -jxpmf #...

Configuration Changes

Compared to Ubuntu a few configuration changes are needed as Arch Linux has a different directory structure and init program. This section outlines the changes that need to be made to the archives in nv_tegra folder of the driver package of Release. Many of the files / directories need to be relocated as the file system hierarchy differs between Arch Linux and Ubuntu.

Before making changes, extract the tars of the nv_tegra folder into directories of the same name:

cd <path_to_L4T_TOP_DIR>/nv_tegra
sudo mkdir nvidia_drivers config nv_tools nv_sample_apps/nvgstapps

sudo tar -xpjf nvidia_drivers.tbz2 -C nvidia_drivers/
sudo tar -xpjf config.tbz2 -C config/
sudo tar -xpjf nv_tools.tbz2 -C nv_tools/
sudo tar -xpjf nv_sample_apps/nvgstapps.tbz2 -C nv_sample_apps/nvgstapps/


Changes to nvidia_drivers Package

The lib folder will need to be moved into /usr

cd <path_to_L4T_TOP_DIR>/nv_tegra/nvidia_drivers
sudo mv lib/* usr/lib/
sudo rm -r lib

Everything in usr/lib/arm-linux-gnueabihf will need to be moved into usr/lib

sudo mv usr/lib/arm-linux-gnueabihf/* usr/lib/
sudo rm -r usr/lib/arm-linux-gnueabihf

nv_tegra_release in etc/ will need to be updated to include the correct path to the tegra libraries.

The lines in nv_tegra_release need to be replaced to look as follows:

88cc04ed62acc205b2b0d415dddaeba5feac8262 */usr/lib/arm-linux-gnueabihf/tegra/libnvmm.so #Replace these paths
88cc04ed62acc205b2b0d415dddaeba5feac8262 */usr/lib/tegra/libnvmm.so # Correct new path


Update etc/ld.so.conf.d/nvidia-tegra.conf to point to the right directory and add the tegra-egl entry. The contents of nvidia-tegra.conf should look like this:

/usr/lib/tegra
/usr/lib/tegra-egl


Changes to nv_tools Package

The tegrastats script should be moved from home/ubuntu into the /usr/bin directory. This removes the dependency on a user called ubuntu.

cd <path_to_L4T_TOP_DIR>/nv_tegra/nv_tools
mkdir -p usr/bin
mv home/ubuntu/tegrastats usr/bin/
rm -r home


Changes to nvgstapps Package

Move the contents of usr/sbin into usr/bin

cd <path_to_L4T_TOP_DIR>/nv_tegra/nv_sample_apps/nvgstapps/
sudo mv usr/sbin/* usr/bin
sudo rm -r usr/sbin

Move the contents of usr/lib/arm-linux-gnueabihf to usr/lib

sudo mv usr/lib/arm-linux-gnueabihf/* usr/lib/
sudo rm -r usr/lib/arm-linux-gnueabihf


Finalizing Configuration Changes

When you have finished making all the listed changes, repackage the files:

cd <path_to_L4T_TOP_DIR>/nv_tegra

cd nvidia_drivers
sudo tar -cpjf ../nvidia_drivers.tbz2 *
cd ..

cd config
sudo tar -cpjf ../config.tbz2 *
cd ..

cd nv_tools
sudo tar -cpjf ../nv_tools.tbz2 *
cd ..

cd nv_sample_apps/nvgstapps
sudo tar -cpjf ../nvgstapps.tbz2 *
cd ../..

Changes to rootfs

The following are changes that will be made to contents in your rootfs directory.

Initialization Script

As Arch Linux uses systemd rather than upstart, the init script will need to be converted into a systemd service. Information on systemd and how to create services can be found on the Arch Linux Wiki page for systemd

To create the systemd service, we will need the service descriptor file, that tells systemd about the service. Hence need to create a service file as below in <path_to_L4T_TOP_DIR>/usr/lib/systemd/system/nvidia-tegra.service

##Location
## /usr/lib/systemd/system/nvidia-tegra.service

[Unit]
Description=The NVIDIA tegra init script

[Service]
type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/nvidia-tegra-init-script

[Install]
WantedBy=multi-user.target

Similarly, create a new file at <path_to_L4T_TOP_DIR>/rootfs/usr/bin/nvidia-tegra-init-script, and place these contents inside.

<path_to_L4T_TOP_DIR>/rootfs/usr/bin/nvidia-tegra-init-script

#!/bin/bash
# Nvidia tegra init script
# adopted from nvidia_config /etc/init/nv.conf
#
#
# power state
if [ -e /sys/power/state ]; then
	chmod 0666 /sys/power/state
fi

# Set minimum cpu freq.
if [ -e /sys/devices/soc0/family ]; then
	SOCFAMILY="`cat /sys/devices/soc0/family`"
fi

if [ "$SOCFAMILY" = "Tegra13" ] &&
	[ -e /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq ]; then
	sudo bash -c "echo -n 510000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"
fi

# CPU hotplugging
if [ -d /sys/devices/system/cpu/cpuquiet/tegra_cpuquiet ] ; then
	echo 500 > /sys/devices/system/cpu/cpuquiet/tegra_cpuquiet/down_delay
	echo 1 > /sys/devices/system/cpu/cpuquiet/tegra_cpuquiet/enable
elif [ -w /sys/module/cpu_tegra3/parameters/auto_hotplug ] ; then
	# compatibility for prior kernels without cpuquiet support
	echo 1 > /sys/module/cpu_tegra3/parameters/auto_hotplug
fi

# lp2 idle state
if [ -e /sys/module/cpuidle/parameters/power_down_in_idle ] ; then
	echo "Y" > /sys/module/cpuidle/parameters/power_down_in_idle
elif [ -e /sys/module/cpuidle/parameters/lp2_in_idle ] ; then
	# compatibility for prior kernels
	echo "Y" > /sys/module/cpuidle/parameters/lp2_in_idle
fi

# mmc read ahead size
if [ -e /sys/block/mmcblk0/queue/read_ahead_kb ]; then
   echo 2048 > /sys/block/mmcblk0/queue/read_ahead_kb
fi
if [ -e /sys/block/mmcblk1/queue/read_ahead_kb ]; then
	echo 2048 > /sys/block/mmcblk1/queue/read_ahead_kb
fi

#FIXME remove once kernel CL merges into main Bug 1231069
for uartInst in 0 1 2 3
do
	uartNode="/dev/ttyHS$uartInst"
	if [ -e "$uartNode" ]; then
		ln -s /dev/ttyHS$uartInst /dev/ttyTHS$uartInst
	fi
done
# remove power to dc.0 for jetson-tk1
machine=`cat /sys/devices/soc0/machine`
if [ "${machine}" = "jetson-tk1" ] ; then
	echo 4 > /sys/class/graphics/fb0/blank
            BoardRevision=`cat /proc/device-tree/chosen/board_info/major_revision`
            if [ "${BoardRevision}" = "A" ] ||
                    [ "${BoardRevision}" = "B" ] ||
                    [ "${BoardRevision}" = "C" ] ||
                    [ "${BoardRevision}" = "D" ]; then
                    echo 0 > /sys/devices/platform/tegra-otg/enable_device
                    echo 1 > /sys/devices/platform/tegra-otg/enable_host
            fi
fi

if [ -e /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors ]; then
	read governors < /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
	case $governors in
		*interactive*)
			echo interactive > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
			if [ -e /sys/devices/system/cpu/cpufreq/interactive ] ; then
				echo "1224000" >/sys/devices/system/cpu/cpufreq/interactive/hispeed_freq
				echo "95" >/sys/devices/system/cpu/cpufreq/interactive/target_loads
				echo "20000" >/sys/devices/system/cpu/cpufreq/interactive/min_sample_time
			fi
				;;
		*)
				;;
	esac
fi

echo "Success! Exiting"
exit 0

Instructions on how to enable the script are in After First Boot section. If you wish to enable the script before flashing / first boot, create the following symbolic link to enable the service.

cd <path_to_L4T_rootfs>/etc/systemd/system/sysinit.target.wants/

ln -s ../../../../usr/lib/systemd/system/nvidia-tegra.service nvidia-tegra.service

This should be executed after apply_binaries, so the nvidia-tegra service is in place.

Pacman Configuration

As we have installed a custom kernel to boot linux on the Jetson-TK1, it is necessary to update pacman.conf to ignore updates to the kernel package.

To do so add linux as an ignored package to your <path_to_L4T_rootfs>/etc/pacman.conf as below:


IgnorePkg=linux

Alternatives Support

Arch Linux does not have a built in application for managing alternative versions of the same package as Debian/Ubuntu does.

It does however support having multiple packages installed at the same time, as long as their names are different.

A script can be created to automate the switching between which of the installed versions is treated as the default. As has been done with java [2].

Flashing Jetson TK1

The steps for flashing the Arch Linux image to the Jetson are no different than flashing the image for Ubuntu.

Run the following commands to apply the configuration, create the image, and flash it to the Jetson

# Apply the NVIDIA specific configuration, binaries, and the L4T kernel
sudo ./apply_binaries.sh

# Create the image from the rootfs directory and flash the image to the Jetson
sudo ./flash.sh jetson-tk1 mmcblk0p1

Your device should reboot and prompt you to login. The default login for Arch Linux ARM is root/root.

After First Boot

Steps to perform after initial boot of Arch Linux

  • Enable the nvidia-tegra initialization script to start on boot.
    systemctl enable nvidia-tegra.service
    
  • Optionally create a user account for yourself
    # useradd -m -g [initial_group] -G [additional_groups] -s [login_shell] [username]
    useradd -m -g users -G wheel -s /bin/bash archie
    
    #set the password for archie
    passwd archie    
    

    More information about User and Group management can be found here.

  • Add your user account to the video group to allow access to the tegra devices
    usermod -aG video archie
    
  • Sync your pacman repositories to have updated package lists
    pacman -Syy
    
  • Install useful packages such as sudo.
    pacman -S sudo
    
  • Allow members of the group wheel sudo access Launch visudo to edit the sudo configuration file. Replace nano with your preferred text editor.
    EDITOR=nano visudo
    

    To allow members of the wheel group sudo access uncomment (add if it doesn't exist) the following line

    %wheel      ALL=(ALL) ALL
    

X11 Support

In order to configure X11 with the NVIDIA provided binaries, it is necessary to use an older version of xorg-server, as the NVIDIA drivers were compiled with ABI 15 support, eg xorg-xserver 15.

Older versions of packages xorg-server and xf86-input-evdev are required. Versions 1.15.2-1 and 2.8.4-1 respectively, work. They will have to be build however, information about the packages, including a download link, can be found here: xorg-server 1.15.2-1 and xf86-input-evdev 2.8.4-1.

You will need to build the packages for the arm architecture. Update the PKGBUILDs and add "armv7h" to the arch field.

It is also necessary to apply this patch on xorg-server: