K230 Linux 摄像头路数与 Sensor 配置指南#
本文介绍当前 K230 Linux SDK 各板级摄像头的默认配置,以及如何通过设备树 配置单路、双路或三路摄像头。新增一种 Sensor 驱动的方法请参考 K230 Linux SENSOR 移植指南。
当前 Linux 板级 Sensor 配置#
基本概念#
K230 最多提供 CSI0、CSI1、CSI2 三个物理 MIPI CSI 控制器。设备树中的
mipi.N 表示逻辑摄像头编号 N,不一定连接同编号的物理 CSI。
下面三个编号容易混淆,阅读配置前应先区分:
名称 |
示例 |
含义 |
|---|---|---|
逻辑摄像头编号 |
slot0、slot1、slot2 |
决定 ISP port 和每路输出分组 |
VVCAM 输出序号 |
|
驱动内部序号,也是 entity 名称最后一段 |
Linux video 设备号 |
|
内核动态分配的设备节点,不能由 DTS 固定 |
设备树中两类配置的职责不同:
mipi.N的节点序号 N 决定/dev/vvcam-mipi.N和 ISP port N;节点中的id、reg、interrupts、resets决定该逻辑端口连接哪个物理 CSI。DTS 标签
&v4l2isp指向运行时的v4l2-isp节点。其中devN-sensor-name、devN-sensor-mode和devN-sensor-i2c-bus描述 ISP port N 使用的 Sensor 驱动名称、该驱动的 mode 下标和 Linux I2C adapter 编号。它们不决定物理 CSI 映射。只有
mipi.N已启用并且对应devN-sensor-*完整时,该路才计入摄像头 路数。
可以将数据通路理解为:
物理 CSI(由 id 等资源决定)
→ 逻辑 mipi.N / ISP port N
→ 第 N 组 MP、SP1、SP2 entity
→ 内核动态分配的 /dev/videoX
Sensor 控制信息 devN-sensor-*
→ Sensor 驱动、mode 下标和 /dev/i2c-X
在当前 MCM 配置中,每路 Sensor 注册 MP、SP1、SP2 三个 VVCAM 输出:
逻辑摄像头 |
MIPI 节点 |
VVCAM |
entity 名称 |
当前板端设备节点 |
|---|---|---|---|---|
第 1 路(slot0) |
|
0、1、2 |
|
|
第 2 路(slot1) |
|
3、4、5 |
|
|
第 3 路(slot2) |
|
6、7、8 |
|
|
以上“每路 3 个输出”以加载 vvcam_video mcm_mask=1 为前提。SDK 启动脚本
S31canaan_isp 已按此方式加载模块。若手工加载时不传该参数,会进入旧版
pipeline 布局,单路可能注册包含 RAW 在内的 4 个输出,不适用本文的多路
映射表。
表中的 /dev/video1~/dev/video9 是当前板端实测结果,不是固定规则。
代码调用 video_register_device(..., -1) 让内核自动分配设备号;当前系统中
/dev/video0 已被 mvx 占用,所以 VVCAM 从 /dev/video1 开始注册。
如果其它驱动的注册顺序变化,设备号也可能变化。
应用应通过 entity 名称查找对应设备,而不是直接假定某一路永远是
/dev/video1、/dev/video4 或 /dev/video7:
for d in /sys/class/video4linux/video*; do
echo "$(basename "$d"): $(cat "$d/name")"
done
# 查看完整 media graph;当前板端 VVCAM media 设备为 media0
media-ctl -d /dev/media0 -p
三路 MP 的稳定标识分别是 vvcam-video.0.0、vvcam-video.0.3 和
vvcam-video.0.6。
芯片侧 CSI 资源#
物理 CSI |
id |
reg |
IRQ |
|---|---|---|---|
CSI0 |
0 |
|
115 |
CSI1 |
1 |
|
118 |
CSI2 |
2 |
|
121 |
板级设备树可以把任一物理 CSI 映射到逻辑 mipi.0。例如部分板型将
物理 CSI2 映射到 mipi.0,因此它仍属于第 1 路,MP entity 仍是
vvcam-video.0.0。
SoC 基线 k230.dtsi 默认是 mipi.0→CSI0 且启用,mipi.1、
mipi.2 禁用。板级 DTS 将 CSI2 映射到 slot0 时,会覆盖 mipi0 的
id、寄存器、中断和复位资源,而不是改为启用原生 mipi2。
当前板端实测配置#
在当前连接的板子上读取运行时设备树、/proc/vsi/isp_subdev0 和 media
拓扑,得到以下配置:
逻辑摄像头 |
物理 CSI |
Sensor |
mode |
Linux I2C adapter |
MP entity |
当前设备节点 |
|---|---|---|---|---|---|---|
第 1 路(slot0) |
CSI2 |
GC2093 |
0 |
4 |
|
|
第 2 路(slot1) |
CSI0 |
GC2093 |
0 |
0 |
|
|
第 3 路(slot2) |
CSI1 |
GC2093 |
0 |
1 |
|
|
运行时还确认:
mipi.0、mipi.1、mipi.2均为"okay",物理id分别为 2、0、1。/dev/vvcam-mipi.0~.2均存在。9 个 VVCAM 输出的 entity 为
vvcam-video.0.0~vvcam-video.0.8,本次分别映射到/dev/video1~/dev/video9。/dev/video0是mvx,/dev/video10是canaan-non-ai-2d,说明/dev/videoN的 N 属于系统动态设备号,不等于 VVCAMvideo_index。
可以使用以下命令在目标板上重新核对:
cat /proc/vsi/isp_subdev0
media-ctl -d /dev/media0 -p
ls /dev/vvcam-mipi.*
各板型 SDK 默认配置#
当前 SDK 默认 Sensor 主要为 GC2093,默认 mode 0 对应 1920×1080@30fps。这里描述的是 SDK DTS 默认值,不代表刷入后又被修改过的 板端当前状态:
defconfig / 板型 |
默认路数 |
逻辑槽位到物理 CSI |
DTS bus → 实际 I2C |
说明 |
|---|---|---|---|---|
|
1 |
slot0→CSI2 |
4→i2c4 |
已预置 slot1→CSI0、slot2→CSI1,默认 disabled;CSI2 reset=gpio0_9 |
|
1 |
slot0→CSI2 |
0→i2c4(alias) |
未预置三路;CSI2 reset=gpio1_30,与 SD 版不同 |
|
1 |
slot0→CSI2 |
4→i2c4 |
已预置 slot1→CSI0、slot2→CSI1,默认 disabled;CSI2 reset=gpio0_13 |
|
1 |
slot0→CSI0 |
0→i2c0 |
CanMV 1.0/1.1 |
|
1 |
slot0→CSI2 |
0→i2c4(alias) |
|
|
1 |
slot0→CSI2 |
0→i2c4(alias) |
|
|
1 |
slot0→CSI2 |
0→i2c4(alias) |
|
|
1 |
slot0→CSI2 |
0→i2c4(alias) |
|
|
DTS 1,VVCAM 未启用 |
slot0→CSI2 |
0→i2c4(alias) |
默认未启用 |
|
DTS 1,但配置不一致 |
slot0→CSI2 |
0→i2c0(无 alias) |
defconfig 为 IMX335,DTS 仍为 GC2093,I2C 连接也需核对 |
|
DTS 1,VVCAM 未启用 |
slot0→CSI2 |
0→i2c0(无 alias) |
Sensor 配置不一致,且默认未启用 VVCAM |
|
1 |
slot0→CSI0 |
0→i2c0 |
继承 SoC 基线设备树 |
|
1 |
slot0→CSI1 |
0→i2c4(alias) |
特殊映射 |
需要特别注意:
k230_canmv_01studio_defconfig和k230_canmv_lckfb_defconfig已写好 三路 GC2093 配置,但默认仅mipi.0为"okay",所以只注册一路。BPI-CanMV-K230D-Zero的 defconfig 默认 Sensor 为 IMX335,而基线 DTS 仍可能是 GC2093,使用前应统一 DTS 和 Buildroot 配置。部分 ILP32 配置没有启用
BR2_PACKAGE_VVCAM,仅修改 DTS 不能使摄像头 工作。
Sensor mode 与 I2C bus#
devN-sensor-mode 是对应 Sensor 驱动中 modes[] 数组的下标,不是通用
分辨率枚举。GC2093 当前常用 mode 如下:
mode |
分辨率和帧率 |
MIPI lane |
|---|---|---|
0 |
1920×1080@30fps |
2 |
1 |
1920×1080@60fps |
2 |
2 |
1280×960@90fps |
2 |
3 |
1280×720@90fps |
2 |
更换 Sensor 后必须查看
buildroot-overlay/package/vvcam/src/<sensor>.c 中该 Sensor 的 modes[],
不能沿用 GC2093 的 mode 含义。
devN-sensor-i2c-bus 表示 Linux adapter 编号,即 /dev/i2c-N 中的 N。
该编号会受到板级 aliases 影响,SDK 中存在两种配置方式。
旧式单摄板常把 Linux adapter 0 映射到硬件 i2c4:
aliases {
i2c0 = &i2c4;
};
此时 devN-sensor-i2c-bus = <0> 实际访问硬件 i2c4。
01studio SD 和 lckfb 的多摄配置使用真实编号:
aliases {
i2c0 = &i2c0;
i2c1 = &i2c1;
i2c4 = &i2c4;
};
此时预置三路的 bus 4、0、1 分别表示硬件 i2c4、i2c0、i2c1。修改配置前
必须先检查本板 aliases,再填写 bus;同时确保实际 I2C 控制器节点为
"okay"。
配置单路、双路或三路摄像头#
配置规则#
驱动从 slot0 开始连续统计摄像头路数。每个启用槽位必须同时满足:
mipi.N的status = "okay"。DTS 的
&v4l2isp节点中存在devN-sensor-name。同时配置匹配的
devN-sensor-mode和devN-sensor-i2c-bus。对应 I2C 控制器已启用。
槽位必须从 0 连续配置,不能只启用 slot0 和 slot2。遇到第一个缺失或
disabled 的槽位后,后面的槽位不会计入摄像头路数。可以提前写好
dev1/dev2-sensor-*,只要 mipi.1/mipi.2 保持 disabled,系统仍按单路
注册。
在 mcm_mask=1 下,逻辑 slot N 的三个输出序号固定为 3N、3N+1、
3N+2,依次对应 MP、SP1、SP2。
DTS 源文件中的 &mipi0、&mipi1、&mipi2 是节点标签引用;系统启动后
对应的节点名称是 mipi.0、mipi.1、mipi.2。同样,DTS 标签
&v4l2isp 对应运行时的 v4l2-isp 节点。
映射物理 CSI 时,必须成套修改以下字段:
idreginterruptsresetsreset-gpios对应的
devN-sensor-i2c-bus
不同 mipi.N 不能使用相同的物理 CSI id。其中 reset-gpios 和 I2C
连接是板级属性,必须以原理图和对应板级 DTS 为准,不能直接照搬其它板型。
修改位置和编译#
编译一次 SDK 后,板级 DTS 位于:
output/<defconfig>/build/linux-*/arch/riscv/boot/dts/canaan/
例如:
output/k230_canmv_01studio_defconfig/build/linux-*/arch/riscv/boot/dts/canaan/k230-canmv-01studio.dts
output/k230_canmv_lckfb_defconfig/build/linux-*/arch/riscv/boot/dts/canaan/k230-canmv-lckfb-lcd.dts
直接修改 output 目录适合调试。正式修改还应同步到 SDK 的板级 DTS 补丁或 overlay 中,避免清理 output 后丢失。
修改后重新编译:
make linux-dirclean
make linux-rebuild
make
然后更新板上的 DTB 或完整镜像。若同时修改了 VVCAM 驱动或
libvvcam.so,还需要更新 vvcam_mipi、vvcam_isp_subdev、
vvcam_video 等对应内核模块和用户态库。
单路摄像头#
单路必须使用逻辑 slot0。下面以 01studio / lckfb 已预置的 “slot0→物理 CSI2”为例:
&i2c4 {
status = "okay";
};
&mipi0 {
/* id/reg/irq/resets/reset-gpios 使用板级 CSI2 配置 */
status = "okay";
};
&mipi1 {
status = "disabled";
};
&mipi2 {
status = "disabled";
};
&v4l2isp {
dev0-sensor-name = "gc2093";
dev0-sensor-mode = <0>;
dev0-sensor-i2c-bus = <4>;
};
如果板级 alias 为 i2c0 = &i2c4,则上例的 bus 应写 <0>。若希望第一路
使用 CSI0,应将 mipi0 的整套物理资源改为 CSI0,同时修改 reset GPIO 和
I2C bus,而不是启用 mipi1。
单路配置会注册 3 个 VVCAM 输出:
内部
video_index:0~2。entity:
vvcam-video.0.0~vvcam-video.0.2。当前实测板端:
/dev/video1~/dev/video3;其它系统可能不同。
双路摄像头#
下面以 01studio / lckfb 的预置顺序为例:
slot0 → 物理 CSI2
slot1 → 物理 CSI0
&i2c0 {
status = "okay";
};
&i2c4 {
status = "okay";
};
&mipi0 {
/* 板级 CSI2 资源 */
status = "okay";
};
&mipi1 {
/* 板级 CSI0 资源 */
status = "okay";
};
&mipi2 {
status = "disabled";
};
&v4l2isp {
dev0-sensor-name = "gc2093";
dev0-sensor-mode = <0>;
dev0-sensor-i2c-bus = <4>; /* CSI2 */
dev1-sensor-name = "gc2093";
dev1-sensor-mode = <0>;
dev1-sensor-i2c-bus = <0>; /* CSI0 */
};
对于已经预置三路配置的 01studio 和 lckfb,需要确认 I2C 已启用,并将
mipi1 的 status 从 "disabled" 改为 "okay"。其它板型还需要补充
mipi1 的 CSI0 物理资源、reset GPIO 和 dev1-sensor-*。
只修改 mipi1 而没有启用实际对应的 i2c0,会出现第二路节点已经注册、
但 Sensor 无法访问和出图的情况。
双路配置会注册 6 个 VVCAM 输出:
内部
video_index:0~5。entity:
vvcam-video.0.0~vvcam-video.0.5。两路 MP entity:
vvcam-video.0.0和vvcam-video.0.3。按当前板端设备注册顺序,通常对应
/dev/video1~/dev/video6, 但应用仍应按 entity 名称查找。
三路摄像头#
01studio / lckfb 的预置顺序是:
slot0 → 物理 CSI2
slot1 → 物理 CSI0
slot2 → 物理 CSI1
这是这两类板型的预置 remap 顺序,不是芯片强制顺序。若使用
slot0→CSI0、slot1→CSI1、slot2→CSI2 的原生顺序,需要同时替换每个
mipi.N 的物理 CSI 资源、reset GPIO 和对应 devN-sensor-i2c-bus。
&i2c0 {
status = "okay";
};
&i2c1 {
status = "okay";
};
&i2c4 {
status = "okay";
};
&mipi0 {
/* 板级 CSI2 资源 */
status = "okay";
};
&mipi1 {
/* 板级 CSI0 资源 */
status = "okay";
};
&mipi2 {
/* 板级 CSI1 资源 */
status = "okay";
};
&v4l2isp {
dev0-sensor-name = "gc2093";
dev0-sensor-mode = <0>;
dev0-sensor-i2c-bus = <4>; /* CSI2 */
dev1-sensor-name = "gc2093";
dev1-sensor-mode = <0>;
dev1-sensor-i2c-bus = <0>; /* CSI0 */
dev2-sensor-name = "gc2093";
dev2-sensor-mode = <0>;
dev2-sensor-i2c-bus = <1>; /* CSI1 */
};
对于已预置三路配置的板型,确认 I2C 后将 mipi1、mipi2 都改为
"okay" 即可。未预置的板型必须补齐两个 MIPI 节点的全部物理资源和
dev1/dev2 配置。
三路预置方案需要硬件 i2c4、i2c0、i2c1 全部可用;&i2c0 或 &i2c1
未设置 status = "okay" 时,对应摄像头不能正常工作。
三路配置会注册 9 个 VVCAM 输出:
内部
video_index:0~8。entity:
vvcam-video.0.0~vvcam-video.0.8。三路 MP entity:
vvcam-video.0.0、vvcam-video.0.3和vvcam-video.0.6。当前板端实际设备节点为
/dev/video1~/dev/video9。
更换 Sensor#
将某一路由 GC2093 更换为其它 Sensor 时,需要同步完成:
将
devN-sensor-name改为 VVCAM 支持的名称。根据该 Sensor 驱动的
modes[]设置devN-sensor-mode。根据实际连接修改 I2C bus、reset GPIO、lane 数和 MIPI 频率。
确认 Buildroot 的
BR2_PACKAGE_VVCAM_DEF_SENSOR和libvvcam.so已包含 该 Sensor,并准备/etc/vvcam/下对应的 ISP 标定文件。多路同型号且 I2C 地址相同时,优先使用不同 I2C 控制器,避免地址冲突。
板上验证#
启动后依次检查:
# MIPI 逻辑设备数量
ls /dev/vvcam-mipi.*
# I2C adapter 是否存在
ls /dev/i2c-*
# DTS 中的 sensor、mode、I2C bus 是否被正确解析
cat /proc/vsi/isp_subdev0
# 物理 CSI 与逻辑 DVP/ISP port 的绑定
dmesg | grep -E 'bind SOURCE_CSI|misc_id|sensor_count'
# 根据 entity 名称查找动态分配的 /dev/video*
for d in /sys/class/video4linux/video*; do
echo "$(basename "$d"): $(cat "$d/name")"
done
预期结果如下。“当前板端设备节点”一列用于说明本次实测映射,不应作为 应用程序的固定设备号:
路数 |
MIPI 设备 |
VVCAM entity |
MP entity |
当前板端设备节点 |
|---|---|---|---|---|
1 |
|
|
|
|
2 |
|
|
|
|
3 |
|
|
|
|
如果某一路没有图像,优先检查该路的 I2C adapter、reset-gpios、
devN-sensor-mode 和 MIPI lane 配置。如果 /dev/vvcam-mipi.* 数量或
vvcam-video.* entity 数量不符合预期,检查 mipi.N 是否从 0 连续启用,
以及 devN-sensor-* 是否完整;不要根据 /dev/videoN 的最大编号判断路数。
配置与代码的对应关系#
文档中的配置规则来自以下实现(路径相对于 buildroot-overlay/):
文件 |
实际作用 |
|---|---|
|
从 slot0 开始,按“ |
|
|
|
解析 |
|
定义每路 MP、SP1、SP2 对应的 |
|
MCM 模式按 |
|
使用 |
|
定义 GC2093 的 |
|
使用 |
因此配置时不要用 /dev/videoN 的 N 推导逻辑端口或物理 CSI。推荐顺序是:
先用
mipi.N确定第几路逻辑摄像头。再用
id和整套 CSI 资源确定物理接口。用同编号的
devN-sensor-*配置 Sensor 控制信息。启动后根据
vvcam-video.0.Kentity 名称查找实际/dev/videoN。
