简介这份资源面向在英伟达Jetson平台上开发计算机视觉与自动驾驶应用的工程师提供GMSL2相机驱动的完整ROS工作空间源码用于解决高带宽、低延迟图像传输场景下的相机接入与调试问题。GMSL2相比传统MIPI CSI-2具备更高数据速率和更长线缆支持适合远程部署的车载摄像头与ADAS系统。资源包共281个文件约104KB以cmake与make构建脚本为主体辅以sh、bash、zsh等环境配置脚本以及py、cpp、c源码和launch启动文件构成可直接编译的catkin工作空间另含rosinstall依赖清单与stamp、marks等编译标记文件。目前已有1583人学习下载。读者可据此完成驱动编译、参数配置与话题数据验证并进一步将相机流接入目标检测、图像处理或SLAM节点快速搭建可复用的Jetson GMSL2相机开发环境。1. 拿到一块 Jetson 板子第一件事为什么是死磕 GMLS2 相机驱动如果你手上有一块 Jetson 开发板不管是 Nano、Xavier NX 还是 Orin 系列插上一颗 GMLS2 接口的相机模组大概率会遇到一个很现实的问题系统能识别到设备但/dev/video*节点死活出不来或者出来了却抓不到图。这不是你接线的问题也不是相机坏了而是 Jetson 平台上的相机驱动链路和普通 x86 Linux 完全不是一回事。Jetson 走的是 NVIDIA 自己的 ISP 和 VIVideo Input通路GMLS2 这类模组需要通过设备树Device Tree正确声明再配合内核驱动和 Argus 或 V4L2 接口才能出流。这篇笔记就是围绕这套驱动链路把从设备树配置到实际抓图验证的完整流程拆开讲清楚。适合正在 Jetson 上做视觉项目、被相机驱动卡住的开发者也适合想提前了解 Jetson 相机接入边界的熟手。2. GMLS2 驱动链路拆解从设备树到 /dev/video 节点2.1 Jetson 相机通路的三个关键层在 Jetson 上接一颗 GMLS2 模组数据流大致经过三层物理接口层MIPI CSI-2 信号、内核驱动层设备树 sensor 驱动 VI 驱动、用户空间层Argus / V4L2。很多人只盯着 sensor 驱动看结果忽略了设备树里 CSI 通道的映射关系最后表现为“驱动加载了但没节点”。常见做法是先把模组的 I2C 地址、MIPI 通道号、lane 数量、时钟频率这几个参数确认清楚。GMLS2 模组通常通过 I2C 配置寄存器地址常见为0x10或0x36具体看模组规格。MIPI 这边要确认是 2-lane 还是 4-lane以及接在 Jetson 的哪个 CSI 端口上。这些信息如果和设备树里写的不一致内核启动阶段就会报tegra-csi相关的 probe 失败。我一般会先跑一遍dmesg | grep -i csi和dmesg | grep -i i2c看内核有没有在启动时尝试探测这颗 sensor。如果连 I2C 通信都没建立后面所有步骤都是白搭。2.2 设备树里必须改对的四个节点Jetson 的设备树文件通常位于内核源码的hardware/nvidia/platform/t19x/或t23x/目录下具体路径取决于你的 L4T 版本。GMLS2 模组需要改的节点主要有四个i2c节点下的 sensor 子节点声明 compatible、reg、时钟、GPIOtegra-camera-platform节点声明模组位置和方向vi或csi节点配置通道和 lanegpio节点复位和电源使能引脚下面是一个典型的 sensor 子节点配置片段以 2-lane 模式为例i2c3180000 { status okay; gmls2_sensor: gmls210 { compatible nvidia,gmls2; reg 0x10; devnode video0; /* 时钟和 GPIO */ clocks bpmp_clk TEGRA194_CLK_EXTPERIPH1; clock-names extperiph1; reset-gpios tegra_main_gpio CAM0_PWDN GPIO_ACTIVE_HIGH; vana-supply p2822_avdd_cam_2v8; vif-supply p2822_vdd_1v8_cam; vdig-supply p2822_vdd_cam_hv_2v8; /* MIPI 配置 */ mode0 { num_lanes 2; tegra_sinterface serial_a; mclk_khz 24000; pix_clk_hz 148500000; active_w 1920; active_h 1080; pixel_t bayer_rggb; line_length 2200; embedded_metadata_height 2; }; }; };这段配置里几个参数容易翻车tegra_sinterface要和实际接的 CSI 端口对应serial_a对应 CSI-Apix_clk_hz要和模组实际输出匹配写大了会花屏写小了会丢帧embedded_metadata_height如果模组不支持嵌入行要设为0否则驱动会多读几行导致图像错位。2.3 编译和刷写设备树改完设备树后需要重新编译并刷写。常见做法是在 L4T 内核源码目录下执行# 编译设备树 make dtbs # 生成的 dtb 文件在 arch/arm64/boot/dts/ 下 # 刷写到 Jetson 的 boot 分区 sudo cp arch/arm64/boot/dts/tegra194-p3668-0001-p3509-0000.dtb /boot/ sudo reboot重启后先别急着抓图先确认设备树有没有生效# 查看设备树中 sensor 节点是否存在 ls /proc/device-tree/i2c3180000/gmls210/ # 查看内核日志中 sensor probe 情况 dmesg | grep -i gmls2如果看到gmls2: probing和gmls2: registered之类的日志说明驱动已经绑定成功。如果只有gmls2: probe failed大概率是 I2C 地址不对或者电源 GPIO 没配对。3. 驱动加载与出流验证从 v4l2-ctl 到实际抓帧3.1 确认 /dev/video 节点和格式支持驱动 probe 成功后用户空间应该能看到/dev/video0节点。先用v4l2-ctl确认设备能力# 列出所有 video 设备 ls /dev/video* # 查看设备支持的格式 v4l2-ctl -d /dev/video0 --list-formats-ext正常输出里应该能看到RG10或YUYV之类的格式以及对应的分辨率列表。如果--list-formats-ext返回空说明 VI 通道没配对回到设备树检查tegra_sinterface和num_lanes。3.2 用 v4l2-ctl 抓一帧原始图确认格式后可以直接抓一帧保存下来# 抓取一帧 1920x1080 的 RAW 图 v4l2-ctl -d /dev/video0 \ --set-fmt-videowidth1920,height1080,pixelformatRG10 \ --stream-mmap4 \ --stream-toframe.raw \ --stream-count1 # 查看文件大小1920x1080 RG10 应该是 1920*1080*2 字节左右 ls -lh frame.raw这里--stream-mmap4表示用 4 个缓冲区做内存映射--stream-count1表示抓一帧就停。如果抓出来的文件大小明显偏小比如只有几百 KB说明丢帧或者格式没设对。3.3 RAW 图转可视格式RAW 图不能直接看需要用工具转成 PNG 或 JPEG。常见做法是用raw2rgb或者自己写个简单的 Python 脚本import numpy as np from PIL import Image # 读取 RAW 数据RG10 是 16 位存储但只有低 10 位有效 raw np.fromfile(frame.raw, dtypenp.uint16) raw raw.reshape((1080, 1920)) # 右移 2 位得到 8 位数据 img (raw 2).astype(np.uint8) # 保存为灰度图先看效果 Image.fromarray(img).save(frame_gray.png) print(saved frame_gray.png)这段脚本把 10 位 RAW 数据右移 2 位转成 8 位灰度图。如果图像整体偏绿或偏紫说明 Bayer 排列顺序和设备树里写的pixel_t不一致需要改成bayer_bggr或bayer_gbrg再试。3.4 用 Argus 接口出流如果项目里用的是 NVIDIA Argus 而不是 V4L2可以用argus_camera工具验证# 启动 Argus 相机预览 argus_camera --device0Argus 对设备树的要求更严格特别是tegra-camera-platform节点里的modules配置。如果 Argus 报No cameras available但 V4L2 能出图基本可以确定是tegra-camera-platform里的badge和position没写对。4. 避坑排查GMLS2 驱动调试中最容易翻车的五个点4.1 现象dmesg 里 I2C 通信失败报 -121 或 -6原因通常是 I2C 地址写错或者模组供电没起来。GMLS2 的 I2C 地址有的是 7 位0x10有的是0x36设备树里写的是 7 位地址。另外检查vana-supply和vdig-supply对应的 regulator 有没有在设备树里使能。解决先用i2cdetect -y -r 0扫描 I2C 总线确认模组地址能出现。如果扫不到用万用表量一下模组供电引脚确认 2.8V 和 1.8V 都正常。4.2 现象/dev/video0 存在但 --list-formats-ext 为空原因一般是 VI 通道没配对或者tegra_sinterface和实际 CSI 端口不一致。Jetson 的 CSI 端口映射在不同载板上可能不同比如 CSI-A 在有的板子上对应serial_a有的对应serial_c。解决查载板原理图确认 CSI 通道号然后逐个试serial_a到serial_f每次改完重新编译设备树并重启。4.3 现象抓图花屏或颜色错乱原因通常是pix_clk_hz和模组实际输出不匹配或者 Bayer 排列顺序写错。GMLS2 常见输出是 RGGB但有些模组出厂配置是 BGGR。解决先用v4l2-ctl --get-fmt-video确认当前格式然后调整设备树里的pixel_t。如果花屏是横向条纹优先调pix_clk_hz每次增减 10% 试。4.4 现象Argus 报 No cameras available 但 V4L2 正常原因是tegra-camera-platform节点里的modules配置不完整。Argus 需要知道模组的位置position和 badge 信息这些在 V4L2 通路里不是必须的。解决在tegra-camera-platform下补全modules节点确保badge和position与设备树里 sensor 节点对应。常见做法是参考同平台其他模组的配置模板改。4.5 现象驱动加载后系统随机重启或内核 panic原因通常是 GPIO 冲突或者时钟配置错误。Jetson 的 GPIO 引脚复用很复杂如果复位引脚和别的外设冲突内核在操作 GPIO 时可能触发异常。解决检查设备树里reset-gpios用的引脚有没有被其他节点占用。用cat /sys/kernel/debug/gpio查看当前 GPIO 占用情况确认没有冲突后再重新编译设备树。5. 进阶技巧用 GStreamer 管道做低延迟预览和录制驱动调通之后实际项目里更常用 GStreamer 做预览和录制因为延迟比 Argus 低而且管道灵活。下面是一个典型的低延迟预览管道# Jetson 上低延迟预览 GMLS2 相机 gst-launch-1.0 nvarguscamerasrc sensor-id0 ! \ video/x-raw(memory:NVMM),width1920,height1080,framerate30/1 ! \ nvvidconv ! \ nv3dsink syncfalse这里nvarguscamerasrc走的是 Argus 底层但 GStreamer 管道比直接调 Argus API 更容易做后续处理。syncfalse是降低延迟的关键表示不按时间戳同步直接渲染。如果要同时录制和预览可以用tee分支gst-launch-1.0 nvarguscamerasrc sensor-id0 ! \ video/x-raw(memory:NVMM),width1920,height1080,framerate30/1 ! \ tee namet \ t. ! queue ! nvvidconv ! nv3dsink syncfalse \ t. ! queue ! nvvidconv ! nvv4l2h264enc bitrate8000000 ! \ h264parse ! qtmux ! filesink locationrecord.mp4这个管道一边预览一边录 H.264bitrate8000000是 8 Mbps实际项目里根据存储和网络带宽调整。queue是必须的否则两个分支会互相阻塞。我一般会在管道跑起来之后用gst-launch-1.0 -v看每个元素的协商结果确认nvarguscamerasrc输出的格式和分辨率是不是和预期一致。如果预览窗口黑屏但管道没报错大概率是nv3dsink的显示后端没配对换成nvoverlaysink或ximagesink试试。从那以后我每次调新模组都会先把v4l2-ctl --list-formats-ext和dmesg | grep -i csi跑一遍确认底层通路没问题再上 GStreamer省得在管道里瞎猜。希望帮到你。本文还有配套的精品资源点击获取 SEO 优化官网定制响应式建站教育培训建站