nvidia-jetson开发笔记

2024/05/01

Tags: C++ Nvidia Jetson

Table of Contents

1. 刷机

jetson xavier NX开发板官方推荐的方式是使用刷sd卡的方式, 也可以使用flash.sh脚本或l4t_initrd_flash.sh直接刷,这样可以省略制作镜像的步骤

截止2024.3.26, jetson xavier NX已然停产,不过仍然可以使用 JetPack 5.1.3 开发包进行开发

我使用我的ubuntu16.04 开发环境的虚拟机制作镜像及烧录脚本烧录,

也可以使用官方的gui刷机工具sdk-manager(ps 名称有点忘记了,好像是这个),不过那需要ubuntu18或ubuntu20

1.1 准备工作

Jetson Linux | NVIDIA Developer下载这两个

Title
Driver Package (BSP)
Sample Root Filesystem

最好在linux中下载,因为windows文件系统不支持符号链接文件,我担心解压后会影响文件完整性

下载后得到

1
2
3
4
5
6
~/Downloads/nvidia/Linux_for_Tegra$ ll
total 2229716
drwxrwxr-x  3 deepvision deepvision       4096 3月  26 13:10 ./
drwxr-xr-x 11 deepvision deepvision       4096 3月  26 12:03 ../
-rwxrw-rw-  1 deepvision deepvision  759217542 3月  26 11:10 Jetson_Linux_R35.5.0_aarch64.tbz2*
-rwxrw-rw-  1 deepvision deepvision 1523988703 3月  25 11:27 Tegra_Linux_Sample-Root-Filesystem_R35.5.0_aarch64.tbz2*

解压出Linux_for_Tegra目录

1
~/Downloads/nvidia$ tar xf Jetson_Linux_R35.5.0_aarch64.tbz2

解压根目录

1
~/Downloads/nvidia$ sudo tar xpf Tegra_Linux_Sample-Root-Filesystem_R35.5.0_aarch64.tbz2 -C Linux_for_Tegra/rootfs/

组装

1
~/Downloads/nvidia/Linux_for_Tegra$ sudo ./apply_binaries.sh

为执行脚本做准备

1
~/Downloads/nvidia/Linux_for_Tegra$ sudo ./tools/l4t_flash_prerequisites.sh  

执行过程可能会提示需要安装一些包,按照提示安装就行了

1.2 jetson xavier

1.2.1 刷sd卡

制作刷机用的镜像包

1
~/Downloads/nvidia/Linux_for_Tegra/tools$ ./jetson-disk-image-creator.sh -o <blob_name> -b <board>

<blob_name> 为输出的镜像名称

<board> 则通过查表的方式获取 jetson-modules-and-configurations

最终我需要执行的是

1
~/Downloads/nvidia/Linux_for_Tegra/tools$ sudo ./jetson-disk-image-creator.sh -o sd-blob.img -b jetson-xavier-nx-devkit -d SD

执行过程可能会提示需要安装一些包,按照提示安装就行了

如python缺少yaml模块

1
$python3 -m pip install pyyaml

1.2.2 刷eMMC和sd卡

如果之前用的系统是安装在NVMe m2上, 但切换回sd卡,用上面的方式可能会失败,大概是因为这种方式只刷系统到卡上, 不会刷QSPI-NOR/eMMC中的引导

如果遇到这种情况,需要强制刷机,把板子电断后,短接板子的 GND和FC REC(9,10 管脚),再上电,进入recovery模式(这时可以取下短接线,实测不取也不影响),通过Usb线刷机,执行

1
sudo ./flash.sh jetson-xavier-nx-devkit internal

注意,以上说的都是jetson-xavier-nx 其他板子有强制恢复按钮

1.2.3 刷 nvme

理论上应该使用sdkmanage安装,但我的开发环境是ubuntu16,所以仍然使用脚本

官网的资料很少,只是提到需要先刷emmc,才能从nvme启动,

我试了好几次,最好的结果只是完成了1.3,再把nvme 通过systemctl把/挂载以m2 ssd上

但这仍然是从sd卡启动,只是提升了系统空间,对启动加速没有什么提升,并且sd卡需要一直插着才能用

所幸github上有不需要sd卡的方案

使用这种方式,可以在没有sd卡的方式下刷nvme,并且启动时也是直接从nvme启动

把板子电断后,短接板子的 GND和FC REC(9,10 管脚),取下sd卡,只接nvme M2,连接Usb, 运行脚本 ,等到脚本提示,取下短接跳线,之后脚本就会一直自动执行,执行完后,板子会重启后,连接Host的ssh server, 需要输入host密码,

1.3 jetson orin

1.3.1 刷 nvme

由于xavier 官方文档上关于无sd卡刷nvme的方法语焉不详,所以借助了github上的脚本, 但其实那个脚本也是使用了官方的刷新脚本,只是参数让人眼花缭乱,

jetson orin 官方文档上有明确的指示应该怎么把 jetson linux + jetpack 一起刷到nvme上的方法

1
sudo ./flash.sh jetson-orin-nano-devkit-nvme internal

2. 无界面模式(可选)

2.1 电源模式

在我们的需求中, xavier nx只有在出厂前的调试模式下,才需要有界面,其他时间不需要

所以我们需要在命令行中切换电源模式

1
sudo nvpmodel -m 8 //20w 8核

因为需要sudo 所以我们可以把他放到2.2启动服务的启动脚本run.sh中,这样它就可以有root权限了

通过uname -r查看kernel名称是否包含tegra来判断是否是nivida的板,如果是就设置nvpmodel

1
2
3
4
5
6
7
...
shopt -s nocasematch #匹配时忽略大小写
string="$(uname -r)"
if [[ $string =~ .*tegra.* ]]; then
    nvpmodel -m 8
fi
...

验证vnpmodel是否设置成功

1
2
3
dv@dv-desktop:~$ sudo nvpmodel -q
NV Power Mode: MODE_15W_2CORE
0

2.2 服务安装/卸载脚本

install.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
cat << EOF > /etc/systemd/system/dv_app.service
[Unit]
Description=dv app
After=network.target

[Service]
Type=simple
ExecStart=/opt/dv_app/run.sh
WorkingDirectory=/opt/dv_app/
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
EOF

systemctl enable dv_app
systemctl start dv_app

uninstall.sh

1
2
3
4
5
#!/bin/bash
systemctl stop dv_app
systemctl disable dv_app
rm /etc/systemd/system/dv_app.service
systemctl daemon-reload

2.3 qt程序修改无界面

注意,记得把qt程序启动时的qpa 设置为和vnc或其他支持仅命令行环境的模式,

1
export QT_QPA_PLATFORM=vnc

并把qt程序中启动窗口的代码去掉,只执行

1
2
3
4
5
6
int main()
{
    QApplication app;
    //不要启动窗口
    app.exec();
}

如果代码结构没有设计好,估计需要有一些重构工作,好在我使用mvvm设计模式,不需要修改代码,可以在没有ui的情况下运行业务逻辑

2.4 linux设置无界面

linux可以用 runlevel 来指定系统启动时进入哪一种模式,常见的是命令行3和图形界面5,

不同的系统设计方法不一样,因为我给xavier nx安装了最新的jet pack,所以他的系统是ubuntu20

ubuntu20 已经不再使用编etc/inittab的方式设置runlevel,而是使用systemctl

查看可用的选项

1
2
3
dv@dv-desktop:~$ systemctl list-units --type=target|grep -E 'multi-user.target|graphical.target'
  graphical.target        loaded active active Graphical Interface
  multi-user.target       loaded active active Multi-User System

graphical.target 是图形模式

multi-user.target 是命令行模式

1
2
3
4
5
6
7
dv@dv-desktop:~$ systemctl status graphical.target
● graphical.target - Graphical Interface
     Loaded: loaded (/lib/systemd/system/graphical.target; indirect; vendor preset: enabled)
     Active: active since Mon 2024-04-01 15:05:11 CST; 2h 3min ago
       Docs: man:systemd.special(7)

4月 01 15:05:11 dv-desktop systemd[1]: Reached target Graphical Interface.

设置为命令行模式

1
2
3
4
dv@dv-desktop:~$ sudo systemctl set-default multi-user.target
[sudo] password for dv:
Removed /etc/systemd/system/default.target.
Created symlink /etc/systemd/system/default.target → /lib/systemd/system/multi-user.target.

设置完重启一下

1
reboot

3. cuda交叉编译设置

为了让jetson orin nx和jetson xavier nx使用一样的系统(维护成本比较少),

最新的版本是 Jetson linux 36.2 + Jetpack 6.0 DP(dp开发预览版本)

我们刷的是 Jetson linux 35.5.0 + Jetpack 5.1.3

版本兼容遵向后兼容,向前兼容,和小版本兼容

image-20240420203520939

jetpack 5.1.3 的cuda版本是11.4, 可以升级,不过我们算法用的是11.3,所以我决定暂时不升级

下面是cuda 11.4的文档

Installation Guide Linux :: CUDA Toolkit Documentation (nvidia.com)

3.1 安装cuda编译器nvcc

CUDA Toolkit 11.4 Update 4 Downloads | NVIDIA Developer

local方式下载速度比较快, network的方式不额外设置apt source镜像很慢

1
2
3
4
5
6
7
wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.4.4/local_installers/cuda-repo-wsl-ubuntu-11-4-local_11.4.4-1_amd64.deb
sudo dpkg -i cuda-repo-wsl-ubuntu-11-4-local_11.4.4-1_amd64.deb
sudo apt-key add /var/cuda-repo-wsl-ubuntu-11-4-local/7fa2af80.pub
sudo apt-get update
sudo apt-get -y install cuda-nvcc-11-4

3.2 cuda-cross-aarch64

3.1的页面下载不到 cuda-cross-aarch64,只能下载到cuda sbsa aarch64,所以只能从这个位置下载

Index (nvidia.cn)

下载需求要包后

1
2
3
4
5
dpkg -i --force-all  *.deb && \
apt-get update && \
apt-get install -y -f && \
apt-get install -y cuda-cross-aarch64 cuda-cross-aarch64-10-2 && \
rm -rf /var/lib/apt/lists/*

3.3 测试CUDA程序 编译

cuda samples

NVIDIA/cuda-samples: Samples for CUDA Developers which demonstrates features in CUDA Toolkit (github.com)

cmake+cuda, 可以用于验证cmake+cuda是否配置成功

Building Cross-Platform CUDA Applications with CMake | NVIDIA Technical Blog

code-samples/posts/cmake at master · robertmaynard/code-samples (github.com)

1
2
3
4
5
 set(CUDA_TOOLKIT_ROOT_DIR /usr/local/cuda-11.4/)
 set(CUDA_NVCC_EXECUTABLE /usr/local/cuda-11.4/bin/nvcc)
 set(CMAKE_CUDA_COMPILER /usr/local/cuda-11.4/bin/nvcc)
 set(CMAKE_CUDA_ARCHITECTURES 87)  #jetson orin nx devicequery
 set(CMAKE_CUDA_FLAGS "-ccbin ${CMAKE_CXX_COMPILER} -Xcompiler -fPIC" CACHE STRING "" FORCE)

4. 交叉编译 VTK 9.3

jetpack 5.3.1 工具链需要额外的设置

https://forums.developer.nvidia.com/t/question-about-cross-compilation-link-errors/238711/10

先编译本机的 compile tools

1
2
 cmake -GNinja -DVTK_BUILD_COMPILE_TOOLS_ONLY=ON  ..
 cmake --build . --target install

再交叉编译

编译选项 VTK_REQUIRE_LARGE_FILE_SUPPORT需要打开,否则cmake不了

DVTK_MODULE_ENABLE_VTK_libproj:STRING= 也需要关掉,否则交叉编译会因为sqlite数据库失败,这个库用于地图信息视频编码相关方面的,我们用不到

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
cmake \
-DCMAKE_TOOLCHAIN_FILE=/repos/vcpkg/toolchains/arm64-jetson-xavier-nx.cmake \
-DQMLPLUGINDUMP_EXECUTABLE=/build/xavier-nx/bin/qmake \
-GNinja \
-DVTK_REQUIRE_LARGE_FILE_SUPPORT=ON \
-DVTK_MODULE_ENABLE_VTK_RenderingQt:STRING=YES \
-DVTK_MODULE_ENABLE_VTK_ViewsQt:STRING=YES \
-DVTK_GROUP_ENABLE_Qt:STRING=YES \
-DVTK_MODULE_ENABLE_VTK_GUISupportQt:STRING=YES \
-DVTK_MODULE_ENABLE_VTK_GUISupportQtQuick:STRING=YES \
-DVTK_MODULE_ENABLE_VTK_libproj:STRING=NO \
-DVTK_USE_CUDA:BOOL=ON \
-DOPENGL_glx_LIBRARY=/sysroot/usr/lib/aarch64-linux-gnu/libGLX.so  \
-DOPENGL_opengl_LIBRARY=/sysroot/usr/lib/aarch64-linux-gnu/libOpenGL.so  \
-DX11_X11_LIB=/sysroot/usr/lib/aarch64-linux-gnu/libX11.so \
..

#-DVTK_OPENGL_USE_GLES=OFF \
#-DVTK_OPENGL_HAS_EGL=ON \
#-DVTK_USE_X=OFF \
#-DOPENGL_gles3_LIBRARY=/sysroot/usr/lib/aarch64-linux-gnu/libGLESv2.so \
#-DOPENGL_egl_LIBRARY=/sysroot/usr/lib/aarch64-linux-gnu/libEGL.so \

因为qmlplugindump 不支持交叉编译,但是vtk用它来导出插件

所以先给DQMLPLUGINDUMP_EXECUTABLE随便设置一个路径, 然后编译

编译时会在最后导出qml plugin时失败, 这时编辑生成的ninja文件,屏蔽掉 生成qml插件,直接强制编译安装

但发现除了qmltypes文件没有,其他的文件都仍然存在, 去之前编译的x86_64的版本上复制qmltypes过来就ok了

5. 交叉编译PCL 1.13

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
cmake \
-GNinja \
-DWITH_LIBUSB=OFF \
-DBUILD_tools=OFF \
-DBoost_CONTEXT_LIBRARY_RELEASE:STRING=/sysroot/usr/lib/aarch64-linux-gnu/libboost_context.so.1.71.0 \
-DBoost_DATE_TIME_LIBRARY_RELEASE:STRING=/sysroot/usr/lib/aarch64-linux-gnu/libboost_date_time.so.1.71.0 \
-DBoost_DIR:PATH=/sysroot/usr/lib/aarch64-linux-gnu/cmake/Boost-1.71.0 \
-DBoost_FIBER_LIBRARY_RELEASE:STRING=/sysroot/usr/lib/aarch64-linux-gnu/libboost_fiber.so.1.71.0 \
-DBoost_FILESYSTEM_LIBRARY_RELEASE:STRING=/sysroot/usr/lib/aarch64-linux-gnu/libboost_filesystem.so.1.71.0 \
-DBoost_IOSTREAMS_LIBRARY_RELEASE:STRING=/sysroot/usr/lib/aarch64-linux-gnu/libboost_iostreams.so.1.71.0 \
-DBoost_SERIALIZATION_LIBRARY_RELEASE:STRING=/sysroot/usr/lib/aarch64-linux-gnu/libboost_serialization.so.1.71.0 \
-DBoost_SYSTEM_LIBRARY_RELEASE:STRING=/sysroot/usr/lib/aarch64-linux-gnu/libboost_system.so.1.71.0 \
-DBoost_THREAD_LIBRARY_RELEASE:STRING=/sysroot/usr/lib/aarch64-linux-gnu/libboost_thread.so.1.71.0 \
-DCMAKE_TOOLCHAIN_FILE=/repos/vcpkg/toolchains/arm64-jetson-xavier-nx.cmake \
-DOPENGL_opengl_LIBRARY=/sysroot/usr/lib/aarch64-linux-gnu/libOpenGL.so  \
-DOPENGL_glx_LIBRARY=/sysroot/usr/lib/aarch64-linux-gnu/libGLX.so  \
-DX11_X11_LIB=/sysroot/usr/lib/aarch64-linux-gnu/libX11.so \
-DFLANN_LIBRARY_TYPE=SHARED \
-DFLANN_LIBRARY=/sysroot/usr/lib/aarch64-linux-gnu/libflann.so \
..

关掉一些不需要的东西 vtk9.3 + pcl1.13 ,足以让我们在qt quick中快乐的开发点云相关的功能了 有时间再另外写一篇 qt quick + vtk + pcl 的博客,这里不再展开

3. I^2C 开发

image-20240328160546379

从手册上看, 有两对默认的i2c, 把设备接上 pin3 SDA pin5 SCL GND后,可以使用i2cdetect工具查看,系统内置了

1
2
3
4
5
6
7
# 查看所有i2c 总线
i2cdetect -l 

# 查看总线上的设备地址
i2cdetect -y -r  "name"
#或
i2cdetect -y -r  n # /dev/i2c-n

经实测, xavier XN的 3 5管脚的i2c ,在/dev/i2c-8

c++ 编码可以参考我之前写的raspberry pi 5的i2c 博客

raspberry-pi5-i2c-gpio-qt-cpp编程/#23-编码 | hbb’s blog (nocanstillbb.github.io)

4. 附录

4.1 cmake toolchain file

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm64)
set(CMAKE_STAGING_PREFIX /repos/installed)
set(CMAKE_INSTALL_PREFIX /repos/installed)

set(rootfs /sysroot)
set(CMAKE_SYSROOT ${rootfs})

set(target_arch /usr/bin/aarch64-linux-gnu)
set(CMAKE_C_COMPILER ${target_arch}-gcc)
set(CMAKE_CXX_COMPILER ${target_arch}-g++)
set(CMAKE_AR  ${target_arch}-ar CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB ${target_arch}-ranlib)
set(CMAKE_LINKER ${target_arch}-ld)

set(CUDA_TOOLKIT_ROOT_DIR /usr/local/cuda-11.4/)
set(CUDA_NVCC_EXECUTABLE /usr/local/cuda-11.4/bin/nvcc)
set(CMAKE_CUDA_COMPILER /usr/local/cuda-11.4/bin/nvcc)
set(CMAKE_CUDA_ARCHITECTURES 87)  #jetson orin nx devicequery
set(CMAKE_CUDA_FLAGS "-ccbin ${CMAKE_CXX_COMPILER} -Xcompiler -fPIC" CACHE STRING "" FORCE)



set(ENV{QT_DIR} /build/xavier-nx/lib/cmake/Qt5)
set(ENV{Qt5_DIR} /build/xavier-nx/lib/cmake/Qt5)
set(ENV{Qt_DIR} /build/xavier-nx/lib/cmake/Qt5)
set(QT_DIR /build/xavier-nx/lib/cmake/Qt5)
set(Qt5_DIR /build/xavier-nx/lib/cmake/Qt5)
set(Qt_DIR /build/xavier-nx/lib/cmake/Qt5)
set(QT_QMAKE_EXECUTABLE /build/xavier-nx/bin/qmake)
set(Qt5Core_DIR /build/xavier-nx/lib/cmake/Qt5Core)
set(Qt5Gui_DIR /build/xavier-nx/lib/cmake/Qt5Gui)
set(Qt5Widgets_DIR /build/xavier-nx/lib/cmake/Qt5Widgets)
set(Qt5Quick_DIR /build/xavier-nx/lib/cmake/Qt5Quick)
set(Qt5QuickControls2_DIR /build/xavier-nx/lib/cmake/Qt5QuickControls2)
set(Qt5QmlModels_DIR /build/xavier-nx/lib/cmake/Qt5QmlModels)
set(Qt5Qml_DIR /build/xavier-nx/lib/cmake/Qt5Qml)
set(Qt5Network_DIR /build/xavier-nx/lib/cmake/Qt5Network)
set(Qt5LinguistTools_DIR /build/xavier-nx/lib/cmake/Qt5LinguistTools)
set(Qt5Sql_DIR /build/xavier-nx/lib/cmake/Qt5Sql)
set(Qt5OpenGL_DIR /build/xavier-nx/lib/cmake/Qt5OpenGL)


set(Boost_INCLUDE_DIR ${rootfs}/usr/include)
set(Boost_LIBRARY_DIR ${rootfs}/usr/lib/aarch64-linux-gnu)

set(VTKCompileTools_DIR /usr/local/lib/cmake/vtkcompiletools-9.3)
set(Protobuf_DIR /repos/dv_app_solution/vcpkg_installed/x64-linux/share/protobuf)

#set(VTK_DIR /repos/vtk9.3/lib/cmake/vtk-9.3)
#set(PCL_DIR /repos/pcl1.13/share/pcl-1.13/)
#
#set(Genicam_DIR /repos/rc_genicam_api/genicam)
#set(OpenCV_DIR ${rootfs}/usr/lib/aarch64-linux-gnu/cmake/opencv4 )
#set(zlog_Dir /repos/installed/share/zlog)
#set(Eigen3_DIR ${rootfs}/usr/lib/cmake/eigen3)
#set(Flann_DIR /repos/installed/share/flann/)




set(CMAKE_FIND_ROOT_PATH
/sysroot/usr
/sysroot/usr/lib/aarch64-linux-gnu
/repos/installed
)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

4.2 ~/.bashrc

1
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libgomp.so.1:/usr/local/Qt/5.15.11/gcc_arm64/plugins/xcbglintegrations/libqxcb-glx-integration.so:$LD_PRELOAD

5.参考

Jetson Software 入门 |NVIDIA 开发人员

Jetson Linux | NVIDIA Developer

Jetson Xavier NX 开发者套件 - 入门 |NVIDIA 开发人员

Flashing Support — NVIDIA Jetson Linux Developer Guide 1 documentation

>> Home

Comments