在Jetson TX2上编译模块

前言

本文翻译于Chiral Software的《Compiling Modules For The Jetson TX2》,点击阅读原文了解更多信息。

英伟达的Jetson TX2是在小型和低功耗设备上做机器学习方面应用开发的好东西。它的主机操作系统是标准的Ubuntu 16.04。这意味着我们可以启用任何我们需要的Linux内核模块,比如我们需要启用某些默认TX2不支持的网络设备。在我们的例子中,需要接入一个串行USB调制解调器,需要串行usb模块和其它一些模块。通过交叉编译模块,我们能够使用这些网络设备。

另一个选择是在Jetson本身上构建新的映像。这可以用来启用CDC ACM模块,这也是我们在这个过程中的目标。这样的脚本很容易使用,并且工作得很好。缺点是,在Jetson上编译比在桌面计算机上编译要慢而且不太方便。在这篇文章中,我们将展示从一个普通的桌面PC运行Ubuntu 16.04的具体步骤。

1

交叉编译

这已经在一个干净的安装上进行了测试,是没问题的。我已经提供了MD5s的文件来验证是否使用了正确的文件。

在普通PC上构建系统是ubuntu-16.04。

您将需要设置一些环境变量以使事情更容易。我创建了一个名为~/var .sh的文件:

export TEGRA_KERNEL_OUT=~/tegra/kernel
export TEGRA_MODULES_OUT=~/tegra/modules
export ARCH=arm64 
export WORK=~/tegra-build
export JETPACK=~/jetpack
export DOWNLOADS=~/Downloads
 
export CROSS_COMPILE=$WORK/install/bin/aarch64-unknown-linux-gnu-
 
mkdir -p $TEGRA_KERNEL_OUT
mkdir -p $TEGRA_MODULES_OUT

根据需要调整目录位置。运行此脚本建立变量: source ~/vars.sh

备注

export TEGRA_KERNEL_OUT=~/tegra/kernel export TEGRA_MODULES_OUT=~/tegra/modules

他在PC上建立了2个目录,用来存放编译出来的kernel和模块(例如一些驱动),这两行是两个环境变量. 后面用这2个变量的: mkdir -p $TEGRA_KERNEL_OUT mkdir -p $TEGRA_MODULES_OUT 等于打了mkdir -p ~/tegra/kernel

和打了mkdir -p ~/tegra/modules,

这样就建立了2个目录(注意变量被替换了)

2

下载

到NVIDIA官网:https://developer.nvidia.com/embedded/downloads 点击下载L4T Source。我们使用的是L4T 28.1 源文件。也可以打开open GCC Tool Chain for 64-bit BSP,下载文件GCC 4.8.5 Tool Chain for 64-bit BSP,把它们都放在$DOWNLOADS 目录下。

您会有:

b13f3e54a49483674ae2ef77dab1e0e5 source_release.tbz2
504b53528c2cd0e609dc2c5da6a7190c gcc-4.8.5-aarch64.tgz

建立一个工作目录,然后建压缩文件:

mkdir $WORK
cd $WORK
tar xf $DOWNLOADS/source_release.tbz2
tar xf $DOWNLOADS/gcc-4.8.5-aarch64.tgz
cd sources
tar xf kernel_src-tx2.tbz2

配置:

make -C kernel/kernel-4.4/ mrproper
make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT tegra18_defconfig
make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT menuconfig

备注

make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT menuconfig ,

这里会出现一个菜单,用键盘上的光标键能选东西.这里得选需要的驱动.

这将在:$WORK/kernel/.config中创建内核配置文件。查看该文件,查看将使用的实际选项。构建命令使用CROSS_COMPILE的设置来使用针对ARM64的Nvidia的交叉编译器。

如果有警告说找不到courses.h,您可以使用apt安装libncurses5-dev。

在运行内核配置之前,您需要知道需要哪个模块。如果它是一个USB设备,一个简单的方法就是在Ubuntu上安装usbutils软件包,插入设备,并使用USB设备实用程序:

# usb-devices
 
T: Bus=03 Lev=01 Prnt=01 Port=08 Cnt=04 Dev#= 15 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=02(commc) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=2a19 ProdID=0c00 Rev=01.00
S: Manufacturer=Numato Systems Pvt. Ltd.
S: Product=Numato Lab 2 Channel USB Relay Module
C: #Ifs= 2 Cfg#= 1 Atr=c0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=02 Prot=01 Driver=cdc_acm
I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_acm

这表明我们需要的模块是cdc_acm。

在menuconfig期间,您可以根据需要启用模块。menuconfig中的一个重要步骤是进入通用设置并定义一个本地版本。Nvidia的默认本地版本是-tegra。更改它,以明确这是一个独立的内核构建。如果使用本地版本,则必须与模块一起使用相同的本地版本。

3

建立模块

make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT modules_prepare
make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT modules 
make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT modules_install INSTALL_MOD_PATH=$TEGRA_MODULES_OUT

4

建立内核

如果您保持与默认内核相同的标记(-tegra),您应该能够通过将它们复制到/lib/modules并运行depmod来安装这些模块,从而避免reflashing。在这种情况下,你可以在这里结束。但是,我们将继续构建内核,设置文件系统,并flashing。

make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT zImage
make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT dtbs

这些将编译内核映像。如果想要加快速度,可以使用-j4这样的选项并行运行make。在我的现代系统中,它在大约20分钟内编译了整个内核,没有并行编译。

备注

这里是说, 如果保留这上一步的-tegra的tag不变,生成的kernel模块文件可以直接复制到目标机器的对应目录,然后sudo depmod一下,这样其实可以不用编译kernel的. 然后这样你就可以本文终止了.

但是我们还是继续编译kernel(注意这里的kernel是Linux的kernel(内核), 不是CUDA C的kernel(核函数)),设好文件系统, 刷机(否则本文就太短了)。

make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT zImage make -C kernel/kernel-4.4/ O=$TEGRA_KERNEL_OUT dtbs

注意编译kernel时候的变量使用,(之前你定义的$TEGRA_KERNEL_OUT)。

文中作者还说如果你的PC如果有4核,就-j4, 能加速,8核上-j8,16核上-j16,其实这个过程很快的。

5

用Jepack准备文件系统

你需要用JetPack来下rootfs(根分区或者叫根文件系统), 本文中是下载Jetpack3.1.

64ada3b06f3a5e664bd8ee92ca719172 JetPack-L4T-3.1-linux-x64.run

将 JetPack-L4T-3.1-linux-x64.放在 $JETPACK 下,然后运行:

mkdir $JETPACK cd $JETPACK cp $DOWNLOADS/JetPack-L4T-3.1-linux-x64.run . chmod ugo+rx JetPack-L4T-3.1-linux-x64.run ./JetPack-L4T-3.1-linux-x64.run

然后用Root运行JePack这个刷机软件, 里面选TX2,默认选了"全部"安装各种包,虽然这个很好, 但需要一些时间来下载,点击next开始下载过程。等下载和安装(到本地的对应的roofs目录下)所有的组件,JetPack将提示刷机过程, 询问你的TX2是怎么连接的。这里不要选继续,我们需要更新这个(本地)的rootfs和boot目录先,注意必须到了这个JetPack的生成(填充)好了rootfs的阶段, 你才能复制刚才编译得到的新kernel和模块们过去。Jetpack将会生成一个$JETPACK/64_TX2/Linux_for_Tegra_tx2的目录,在这个目录下面, 有一个flash.sh(刷机实用脚本),也包括一个叫kernel的目录, 用来生成启动ramdisk镜像,这个目录还包括一个rootfs目录, 里面是(最终用来刷给TX2)的根文件系统.

备注

这些就是说, 在刷给TX2之前, 需要从NV网站下载下来(自动的)并在本地PC上有了这些文件和目录,下一步就会将你改过(新编译出来的)kernel和modules目录复制过去

6

安装新的Kernel和模块

复制Kernel、Device Tree Blob (DTB)和模块:

sudo -s
source ~/vars.sh
cd $JETPACK/64_TX2/Linux_for_Tegra_tx2
cp $TEGRA_KERNEL_OUT/arch/arm64/boot/Image kernel
cp $TEGRA_KERNEL_OUT/arch/arm64/boot/Image rootfs/boot
cp -R $TEGRA_MODULES_OUT/lib/modules rootfs/lib/

现在,最终的得到的这个文件系统(目录)可以用来给TX2了,请注意, 之前的复制必须是root账号下进行,这是因为JetPack创建(这个系统目录里的)文件的时候,它是作为root权限运行的(你不是root权限改不掉之前的jetpack生成的这些文件的)。你可能继续再需要source一次vars.sh文件来设定变量 (就是从键盘输入source vars.sh回车,注意路径,来用你之前的那些设定过的变量)。

7

用JetPack刷机

本文作者推荐用的方式。点击JetPack界面里的"继续"(还记得你之前没有点继续嘛),来继续刷机过程。这个方法可以安装CUDA和其他后续安装的组件。

当然(作者认为)只能在界面上点来点去, 很烦人的,特别是当你要这样处理很多设备的时候,希望NV能弄一种方便的方式, 来缓存需要的这些软件包。JetPack刷机的时候每次给每个设备, 都需要重新下载一大堆包,所以刷机需要很长时间的.

8

刷机完成

刷机完成,会出现这样的提示:

[ 156.2511 ] Flashing completed
[ 156.2512 ] Coldbooting the device
[ 156.2520 ] tegradevflash_v2 --reboot coldboot
[ 156.2526 ] Bootloader version 01.00.0000
[ 156.3605 ] 
*** The target t186ref has been flashed successfully. ***
Reset the board to boot from internal eMMC.

如果你没看到这些文字(就是上面那些行), 肯定是哪里出错了,确定device处于recover模式,并且设备上电了, 并且整个刷机器件连接的良好。

连好网线,然后用ssh登录:

ssh 192.168.1.132 -l nvidia
[email protected]'s password: 
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.38-chiral aarch64)

这说明TX2已经在运行定制过的kernel了,用root用户登录, 运行一次depmod(让你的系统能用上这些新编译的模块,然后重启。你的新模块就会看到,硬件开始工作!

9

DBT文件

关于Device Tree Binary,很多(教程里面)建议这样复制DTB文件:

cp $TEGRA_KERNEL_OUT/arch/arm64/boot/dts/*.dtb kernel/dtb
cd $JETPACK/64_TX2/Linux_for_Tegra_tx2
./apply_binaries.sh

作者尝试了这样做, 结果CUDA不能用了,CUDA只能在原始的DTB文件下工作。可能有一种重建DTB文件的方法, 同时不对CUDA造成干扰,但是本文作者没有提到。

10

总结

你应该已经完成好了这些步骤了:

  • 下载所有的必须的kernel源代码, GCC交叉编译器;
  • 构建了你的kernel和kernel模块;
  • 将(构建好的)kernel和模块放入了PC上的(用来刷机的)样本rootfs根分区目录;
  • 然逅将它们刷到了你的Jetson;

这样你现在能很容易的使用那些能用来访问(驱动)你的设备的kernel模块了,登录到Tegra上, 看看我们的设备是否在那里:

ls /dev/ttyA*
/dev/ttyACM0

你可能感兴趣的:(NVIDIA)