一、说明
本文档介绍如何在 Ubuntu24 系统中启用三路 IMX415 MIPI 摄像头,并实现三路同时采集和 HDMI 三画面预览。
测试环境
- 开发板:泰山派 3M-RK3576
- 系统:Ubuntu24 GNOME
- 内核:Linux 6.1.99
- 摄像头:3 路
IMX415MIPI,I2C 地址均为0x37
IMX415 是 8MP 级别传感器,如果三路都以 3864x2192 模式进入 ISP,容易出现多路同时采集不稳定或内存分配失败。
本次验证采用 1944x1097 crop 模式进入 ISP,最终每路输出 1920x1080 NV12:
IMX415 sensor: 1944x1097 SGBRG12
ISP output : 1920x1080 NV122
二、修改内核
进入内核源码目录:
cd TaishanPi-3-Linux/kernel-6.11、修改IMX415默认模式
打开 drivers/media/i2c/imx415.c,找到 imx415_probe() 中选择 cur_mode 的逻辑。
默认逻辑只按 hdr_mode 选择第一个匹配模式。需要修改为:当 IMX415 使用 4-lane 且为 NO_HDR 时,优先选择宽度为 1944 的已有模式。
核心修改如下:
diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c
index 027f9181a..944b846f7 100644
--- a/drivers/media/i2c/imx415.c
+++ b/drivers/media/i2c/imx415.c
@@ -3226,9 +3226,28 @@ static int imx415_probe(struct i2c_client *client,
imx415->bus_cfg.bus.mipi_csi2.num_data_lanes);
for (i = 0; i < imx415->cfg_num; i++) {
- if (hdr_mode == imx415->supported_modes[i].hdr_mode) {
- imx415->cur_mode = &imx415->supported_modes[i];
- break;
+ if (hdr_mode != imx415->supported_modes[i].hdr_mode)
+ continue;
+
+ /*
+ * Three 8MP streams exceed RK3576's practical ISP input budget.
+ * Prefer the existing 1080p-crop mode for 4-lane linear IMX415.
+ */
+ if (hdr_mode == NO_HDR &&
+ imx415->bus_cfg.bus.mipi_csi2.num_data_lanes == IMX415_4LANES &&
+ imx415->supported_modes[i].width != 1944)
+ continue;
+
+ imx415->cur_mode = &imx415->supported_modes[i];
+ break;
+ }
+
+ if (!imx415->cur_mode) {
+ for (i = 0; i < imx415->cfg_num; i++) {
+ if (hdr_mode == imx415->supported_modes[i].hdr_mode) {
+ imx415->cur_mode = &imx415->supported_modes[i];
+ break;
+ }
}
}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
2、调整CMA大小
内核配置文件:
kernel6.1/arch/arm64/configs/rockchip_linux_defconfig
使用 build.sh 脚本,中的相关预置命令打开 menuconfig:
预置命令说明
这样的好处是预置命令会自动修改 rockchip_linux_defconfig 配置文件,不需要我们手动简化和复制 .config 文件。
# 选择Ubuntu24配置
./build.sh tspi_3m_rk3576_ubuntu_noble_gnome_defconfig
# 打开内核配置界面
./build.sh kconfig2
3
4
5
确认已有:
CONFIG_CMA=y
CONFIG_DMA_CMA=y2
然后修改 CMA 大小为 768MB:
CONFIG_CMA_SIZE_MBYTES=768然后保存退出即可,会自动将修改后的配置写入 rockchip_linux_defconfig。
三路 1920x1080 NV12 同时采集会占用较多连续内存,如果 CMA 仍为默认 16MB,多路采集容易失败。
三、编译内核与烧录
选择 tspi_3m_rk3576_ubuntu_noble_gnome_defconfig 配置:
# 直接使用预置命令选择配置
./build.sh lunch
# 或者
# 直接使用下面的命令选择指定的配置
./build.sh tspi_3m_rk3576_ubuntu_noble_gnome_defconfig2
3
4
5
6
编译内核:
./build.sh kernel编译成功后,会在 kernel-6.1/ 目录下生成新的 boot.img。
然后参考 分散镜像烧录 章节,单独烧录新的 boot.img 即可。
提示
如果需要重新编译完整系统镜像,可以参考 Ubuntu24镜像编译 章节。
四、板端验证
1、检查CMA
启动系统后,先检查 CMA 是否生效:
grep -i cma /proc/meminfo正常应显示:
CmaTotal: 786432 kB如果仍然是 16MB,需要检查实际编译是否使用了修改后的 rockchip_linux_defconfig,或者启动参数中是否存在 cma=16M 覆盖配置:
cat /proc/cmdline2、检查摄像头注册
查看摄像头和 ISP 相关日志:
dmesg --color=never | grep -Ei 'imx415|gc05a2|rkisp|rkcif' | tail -n 160正常应能看到三路 IMX415:
imx415 4-0037: Detected imx415 id 0000e0
imx415 5-0037: Detected imx415 id 0000e0
imx415 6-0037: Detected imx415 id 0000e02
3
并且能看到三个 rkisp:
rkisp rkisp-vir0: virtual isp0 1920x1080 using frm buf
rkisp rkisp-vir1: virtual isp1 1920x1080 using frm buf
rkisp rkisp-vir2: virtual isp2 1920x1080 using frm buf2
3
3、检查video节点
v4l2-ctl --list-devices
ls -l /dev/video-camera*2
本次测试中节点映射如下:
/dev/video-camera0 -> /dev/video33
/dev/video-camera1 -> /dev/video42
/dev/video-camera2 -> /dev/video512
3
实际 /dev/videoXX 编号可能变化,建议使用 /dev/video-camera0、/dev/video-camera1、/dev/video-camera2。
五、三路采集测试
分别测试单路摄像头:
v4l2-ctl -d /dev/video-camera0 \
--set-fmt-video=width=1920,height=1080,pixelformat=NV12 \
--stream-mmap=3 --stream-count=30 --stream-to=/dev/null
v4l2-ctl -d /dev/video-camera1 \
--set-fmt-video=width=1920,height=1080,pixelformat=NV12 \
--stream-mmap=3 --stream-count=30 --stream-to=/dev/null
v4l2-ctl -d /dev/video-camera2 \
--set-fmt-video=width=1920,height=1080,pixelformat=NV12 \
--stream-mmap=3 --stream-count=30 --stream-to=/dev/null2
3
4
5
6
7
8
9
10
11
然后测试三路同时采集:
cam0=$(mktemp /tmp/cam0.XXXX.log)
cam1=$(mktemp /tmp/cam1.XXXX.log)
cam2=$(mktemp /tmp/cam2.XXXX.log)
v4l2-ctl -d /dev/video-camera0 \
--set-fmt-video=width=1920,height=1080,pixelformat=NV12 \
--stream-mmap=3 --stream-count=600 --stream-to=/dev/null >"$cam0" 2>&1 &
p0=$!
v4l2-ctl -d /dev/video-camera1 \
--set-fmt-video=width=1920,height=1080,pixelformat=NV12 \
--stream-mmap=3 --stream-count=600 --stream-to=/dev/null >"$cam1" 2>&1 &
p1=$!
v4l2-ctl -d /dev/video-camera2 \
--set-fmt-video=width=1920,height=1080,pixelformat=NV12 \
--stream-mmap=3 --stream-count=600 --stream-to=/dev/null >"$cam2" 2>&1 &
p2=$!
wait "$p0"; r0=$?
wait "$p1"; r1=$?
wait "$p2"; r2=$?
printf 'cam0 rc=%s %s\ncam1 rc=%s %s\ncam2 rc=%s %s\n' \
"$r0" "$cam0" "$r1" "$cam1" "$r2" "$cam2"
tail -n 3 "$cam0"
tail -n 3 "$cam1"
tail -n 3 "$cam2"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
三路都返回 rc=0,并且日志中出现 30.00 fps,说明三路采集正常。
六、HDMI三画面预览
注意
需要进入桌面环境之后才能使用预览,锁屏页面无法预览!
先测试单路预览:
gst-launch-1.0 v4l2src device=/dev/video-camera0 io-mode=dmabuf \
! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 \
! videoconvert ! autovideosink sync=false2
3
三路合成预览:
gst-launch-1.0 -e compositor name=mix background=black \
sink_0::xpos=0 sink_0::ypos=0 sink_0::width=960 sink_0::height=540 \
sink_1::xpos=960 sink_1::ypos=0 sink_1::width=960 sink_1::height=540 \
sink_2::xpos=480 sink_2::ypos=540 sink_2::width=960 sink_2::height=540 \
! video/x-raw,width=1920,height=1080,framerate=30/1 \
! videoconvert ! autovideosink sync=false \
v4l2src device=/dev/video-camera0 io-mode=dmabuf \
! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 \
! queue max-size-buffers=2 leaky=downstream ! videoconvert ! videoscale \
! video/x-raw,width=960,height=540 ! mix.sink_0 \
v4l2src device=/dev/video-camera1 io-mode=dmabuf \
! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 \
! queue max-size-buffers=2 leaky=downstream ! videoconvert ! videoscale \
! video/x-raw,width=960,height=540 ! mix.sink_1 \
v4l2src device=/dev/video-camera2 io-mode=dmabuf \
! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 \
! queue max-size-buffers=2 leaky=downstream ! videoconvert ! videoscale \
! video/x-raw,width=960,height=540 ! mix.sink_22
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
注意
三路预览时 v4l2src 必须使用 io-mode=dmabuf。如果使用默认方式,可能会出现 Failed to allocate required memory、Buffer pool activation failed 或 not-negotiated 等错误。
七、常见问题
某一路IMX415没有注册
可以按以下顺序排查:
- 检查摄像头排线方向和插接是否可靠;
- 对调摄像头模块,确认故障是否跟随摄像头移动;
- 检查对应 I2C 总线是否能探测到
0x37; - 检查设备树中对应 CSI 节点是否启用
IMX415; - 检查同地址的
GC05A2节点是否已经禁用。
三路采集瞬间出现MIPI错误
三路同时 stream-on 时,可能出现一次 csi size err 或 MIPI_CSI2 ERR2。如果只在启动瞬间出现,采集返回码为 0,且帧率稳定,可以按瞬态告警处理。
如果错误持续出现,需要检查 MIPI 排线、sensor mode、lane 配置和时钟配置。
HDMI预览无法弹窗
先检查 HDMI 桌面是否已经登录:
ls -l /run/user/1000/wayland-*如果没有 wayland-0,说明当前桌面会话未就绪,需要先登录桌面,或者根据实际环境改用其他 sink。