为 NVIDIA Jetson Xavier NX 更改设备树和编译内核
NVIDIA Jetson Xavier NX 模块
如果您正在为 NVIDIA Jetson 模块设计定制载板,您可能需要编辑设备树并从源代码重新编译内核以启动您的板。
鉴于 NVIDIA 的文档很差,而且我对 Linux 内部工作原理的了解有限,我花了很多时间从 NVIDIA 开发者论坛收集这些信息并让我的定制载板工作。😫
就我而言,我已将我的定制载板设计为尽可能接近开发人员套件。尽管如此,HDMI 热插拔检测 (HPD) 极性仍然存在微小差异,并且启用 SDMMC3 以使用 SD 卡。
我的目标是分享这些步骤的精髓,以便其他工程师不必面对我所面临的困难。主要步骤分为以下顺序:
- 在 Ubuntu 中设置交叉编译
- 设置必要的文件
- 更改 pinmux(如果适用)
- 修改设备树文件 (.dtsi)
- 构建内核和设备树
- 替换 dtb 文件
- 闪存设备树
在 Ubuntu 中设置交叉编译
由于我们在我们的主机上为 Jetson(ARM64 架构)进行编译,这很可能是 x86 架构,我们需要下载相应的编译器并设置它以进行交叉编译。所有后续步骤都应该适用于 Ubuntu 18 和 20。
NVIDIA 建议为此使用 Linaro 7.3.1 2018.05 工具链。在此处下载预构建的工具链二进制文件,并在下面执行:
参考
mkdir $HOME/l4t-gcc
cd $HOME/l4t-gcc
tar xf gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz
设置必要的文件
下载 Linux for Tegra BSP、BSP 源代码、示例根文件系统 (RFS)
请注意,您需要创建一个 NVIDIA 开发人员帐户并登录才能下载。
指向所需文件的箭头
提取内核源
在public_sources.tbz2(BSP源zip文件)里面会有很多其他的zip文件,但是我们只对kernel_src.tbz2感兴趣。将此文件解压缩到名为“source”的文件夹中
提取 L4T 和示例根文件系统
- 从 Jetson_Linux_R32.6.1_aarch64.tbz2 中提取“Linux_for_Tegra”(撰写本文时为 32.6.1)
- 将示例 RFS 内容提取到Linux_for_Tegra/rootfs/
创建 extlinux.conf
NVIDIA 没有在示例 RFS 中提供这个文件真的很奇怪!
您将需要创建一个名为“extlinux”的目录并在以下位置创建 extlinux.conf:
Linux_for_Tegra/rootfs/boot/extlinux/extlinux.conf
将以下内容复制到 extlinux.conf 中:
参考
TIMEOUT 30
DEFAULT primary
MENU TITLE L4T boot options
LABEL primary
MENU LABEL primary kernel
LINUX /boot/Image
INITRD /boot/initrd
APPEND ${cbootargs} root=/dev/mmcblk1p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0
请注意,参考链接显示mmcblk0p1,但我这里有mmcblk1p1,这是因为我使用的是开发人员套件模块,该模块带有自定义载板和另一个 sd 卡插槽 (SDMMC3)。由于开发者套件模块有一个 SD 卡插槽 (SDMMC1),我们需要执行此修复,否则它会尝试从错误的 SD 卡启动。我不确定我们是否需要对生产模块进行此修复,您需要自己尝试一下。
更改 Pinmux
如果引脚功能与开发套件不同,则很可能需要对 pinmux 进行更改。此步骤只能在 Windows 上完成,因为它使用 Excel 宏
编辑excel文件非常简单。就我而言,我使用 GPIO 08 作为 SD 卡检测引脚。由于它在开发套件中被配置为冷却风扇转速计输入,因此我需要将其更改为常规 GPIO。
完成更改后,单击“Generate DT File”按钮,为您的电路板命名,您应该会看到在同一文件夹中生成了 3 个文件。
将这些文件复制到您的 Ubuntu 机器上。就我而言,我将它们命名为“jetson_xavier_nx”
生成 .cfg 文件
这些是最终将写入 Jetson 的文件,在这里我采取了替换用于开发工具包的原始 .cfg 文件的捷径,因为我的开发板与开发工具包大部分相似。正确的方法实际上涉及创建一个新的板名和一组特定于该板的新文件。
从 .dtsi 到 .cfg 文件生成的脚本位于:
Linux_for_Tegra/kernel/pinmux/python pinmux-dts2cfg.py
将文件复制到与脚本相同的文件夹中,然后运行:
参考
python pinmux-dts2cfg.py --pinmux addr_info.txt gpio_addr_info.txt por_val.txt --mandatory_pinmux_filemandatory_pinmux.txt tegra19x-jetson_xavier_nx_module-pinmux.dtsi tegra19x-jetson_xavier_nx_module-gpio-default.dtsi 1.0 > tegra19x-mb1-pinmux-p3668-a01.cfg
python pinmux-dts2cfg.py --pad pad_info.txt tegra19x-jetson_xavier_nx_module-padvoltage-default.dtsi 1.0 > tegra19x-mb1-padvoltage-p3668-a01.cfg
复制生成的 .cfg 文件并将文件替换为:
Linux_for_Tegra/bootloader/t186ref/BCT/
修改设备树文件
我将在这里展示 2 个与我的案例相关的示例,这应该让您了解如何调整其他接口。
更改设备树需要编辑 dtsi 文件,将它们编译为 dtb 文件,然后将它们刷写到 Jetson
为了知道要编辑哪些 dtsi 文件,请登录开发工具包并执行以下操作:
dmesg|grep dts
这将向我们展示我们必须进入内核源代码中的哪个文件夹。在 Xavier NX 的案例中,它位于:
source/hardware/nvidia/platform/t19x/jakku/kernel-dts/common
更改 HDMI HPD 极性
编辑 tegra194-p3509-disp.dtsi,将 TEGRA_DC_OUT_HOTPLUG_LOW 更改为 TEGRA_DC_OUT_HOTPLUG_HIGH
启用 SDMMC3
编辑tegra194-p3688-common.dtsi 添加sdmmc3接口
sdmmc3: sdhci@3440000 {
mmc-ocr-mask = <0x0>;
cd-inverted;
cd-gpios = <&tegra_main_gpio TEGRA194_MAIN_GPIO(Q, 2) 0>;
nvidia,cd-wakeup-capable;
mmc-ocr-mask = <0>;
cd-inverted;
vmmc-supply = <&p3668_vdd_sdmmc3_sw>;
status = "okay";
};
请注意,TEGRA194_MAIN_GPIO(Q,2) 来自 pinmux。
还有一个负载开关可以为 SD 卡供电,在我的情况下,我已将其连接到 GPIO 03
编辑 tegra194-fixed-regulator-p3668.dtsi 并添加用于控制负载开关的 GPIO:
p3668_vdd_sdmmc3_sw: regulator@103 {
compatible = "regulator-fixed";
reg = <103>;
regulator-name = "vdd-sdmmc3-sw";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&tegra_main_gpio TEGRA194_AON_GPIO(CC, 0) 0>;
enable-active-high;
};
注意 TEGRA194_AON_GPIO(CC,0) 来自 pinmux:
现在为什么是 AON_GPIO 而不是 MAIN_GPIO?你可以参考这个论坛帖子。
另请注意,我写了“regulator@103”,“103”实际上可以是任何数字,只要它不与其他接口冲突。
要了解哪些号码已被使用,请参阅本指南。
构建内核和设备树
NVIDIA 提供了一个构建脚本来构建内核和设备树,位于:
source/nvbuild.sh
但不幸的是,这个脚本在编写时不起作用😑
修复:
将第 86 行更改为:
O_OPT=(-O “${KERNEL_OUT_DIR}”)
至:
O_OPT=(O="${KERNEL_OUT_DIR}")
为编译器路径设置环境变量:
export CROSS_COMPILE_AARCH64_PATH=“$HOME/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu”
创建一个文件夹来存储已编译的内核和 .dtb 文件(设备树 blob)。就我而言,我把它放在$HOME/Desktop/kernel_out
执行:
./nvbuild.sh -o $HOME/Desktop/kernel_out/
如果您中断了构建过程或没有正确执行某些导致构建失败的操作,您将收到一条错误提示:
“please run make mrproper”
delete the following folder to fix this:
Reference
source/kernel/kernel-4.9/include/config/
Replace .dtb files
Copy tegra194-p3668-all-p3509–0000.dtb from
$HOME/Desktop/kernel_out/arch/arm64/boot/dts
Replace file in:
Linux_for_Tegra/kernel/dtb/
Flash device tree
At the time of writing, I am using jetson dev kit module on my custom carrier board, which uses an SD card on the module instead of a soldered 16gb emmc on the production module. Hence we first download the official xavier nx SD card image and flash it with balena etcher.
Insert the sd card into the module and perform the steps below to flash ONLY Device Tree:
We wont be changing the kernel here, and we will use whatever is in the default dev kit sd card image
- Plug in micro usb to recovery port
- Hold recovery button
- 打开电源,然后松开恢复按钮
- 闪存设备树(在 Linux_for_Tegra/ 中)
sudo ./flash.sh -r -k kernel-dtb jetson-xavier-nx-devkit mmcblk0p1
5.如果连接失败,请参考此修复: