tegracam、DTB overlay
NVIDIA 用 tegracam 承接感測器驅動,統一曝光/增益 controls,讓 Argus 能列舉相機。
&ov9281_cam0 {
status = "okay";
reg = <0x36>; # I2C 位址
reset-gpios = ...;
mode0 { ... mclk_khz, pixel_phase ... };
};修改 DTB 需重編 device tree 並刷入(或 bootloader overlay)。
argus_camera --list-cameras v4l2-ctl --list-devices
tegracam 提供統一的 V4L2 controls(exposure、gain、white balance…),感測器驅動只要實作 init table 與 register 讀寫,就能把曝光/增益暴露給 userspace。這就是「Argus 設曝光 → 最後落到感測器 register」的橋樑。
| 層 | 角色 | 除錯時看什麼 |
|---|---|---|
| 感測器驅動 | I2C 讀寫 + init table | probe 訊息、ID 讀取 |
| tegracam | 統整 V4L2 controls | v4l2-ctl -C 列表 |
| VI5 | CSI 收 frame | dmesg 的 vi5/csi 錯誤 |
| Argus | 會話式相機 API | argus_camera 出圖 |
每個感測器在 DTB 宣告一個 camera 節點,內含 mode0/mode1…,每個 mode 定義解析度、幀率、CSI lane 數、Bayer order、曝光/增益範圍與 pixel_phase。
&ov9281_cam0 {
status = "okay";
reg = <0x36>; # I2C 位址
mode0 {
mclk_khz = <24000>; # MCLK 24 MHz
num_lanes = <2>; # CSI lane 數
tegra_sinterface = "serial_a";
phy_mode = "DPHY";
pixel_phase = "bggr"; # Bayer 起點
active_w = <1280>; active_h = <800>;
min_framerate = <1>; max_framerate = <120>;
min_exp_time = <1>; max_exp_time = <33333>;
};
};# 1. 確認 overlay 已套用 dmesg | grep -i "camera|tegra-camera|ov9281" # 2. 檢查 media 管線拓撲 media-ctl -p -d /dev/media0 # 3. 檢查 subdev 與 controls v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls # 4. Argus 列舉 argus_camera --list-cameras
若 1、2 有、3、4 沒有 → controls/Argus 對接問題;若 1 就沒有 → 回到 DTB/電源/serdes。
tegracam 的多個 subdev(感測器 → CSI → VI)以「連結」串成 media graph。V4L2 userspace 要出圖前,這些連結與格式(sink/source pad 的 fourcc、尺寸)必須一致。
# 印出拓撲與格式 media-ctl -p -d /dev/media0 # 設定感測器 source pad 格式(範例) media-ctl -d /dev/media0 --set-v4l2 '"ov9281 0-0036":0[fmt:SRGGB10_1X10/1280x800]'
| 檢查 | 指令 | 通過標準 |
|---|---|---|
| probe | dmesg | grep -i ov9281 | 有 probe/ID 訊息 |
| 拓撲 | media-ctl -p | 感測器→CSI→VI 完整 |
| controls | v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls | exposure/gain 在列 |
| 列舉 | argus_camera --list-cameras | 看得到相機 |
# 1. 重建 DTB 並刷入(bootloader / overlay 方式) # 2. 重開機,確認 overlay 有套 dmesg | grep -i "camera|ov9281" # 3. 檢查新 mode 是否列得出來 argus_camera --list-cameras v4l2-ctl -d /dev/video0 --list-formats-ext # 4. 取一幀,驗證尺寸與格式符合新 mode v4l2-ctl -d /dev/video0 --stream-mmap=1 --stream-count=1 --stream-to=t.raw
場景:你有一顆非標準的 OmniVision 感測器(例如 OV2775),官方 DTB 沒有支援。你需要從 datasheet 出發,建立完整的 DTB overlay。
# 1. 從感測器 datasheet 取得:I2C 位址、lane 數、init register table # 2. 在 NVIDIA jetson-camera module 驅動目錄新增 OV2775 driver # 3. 建立 DT overlay(.dts) cat > ov2775-overlay.dts <<'EOF' /dts-v1/; /plugin/; / { overlay-name = "ov2775 camera"; fragment@0 { target = <&csi_i2c>; __overlay__ { ov2775@10 { compatible = "ovti,ov2775"; reg = <0x10>; clocks = <&clk_ext_cam 24000000>; clock-frequency = <24000000>; reset-gpios = <&gpio 100 0>; port { ov2775_out: endpoint { remote-endpoint = <&csi_in>; data-lanes = <1 2>; clock-lanes = <0>; link-frequencies = /bits/ 64 <360000000>; }; }; }; }; }; }; EOF # 4. 編譯 overlay dtc -@ -I dtb -O dtb -o ov2775.dtbo ov2775-overlay.dts # 5. 套用 sudo cp ov2775.dtbo /boot/dtb/overlays/ sudo reboot
設計決策:DTB overlay 是「可插拔」的——不動原始 DTB,只在開機時動態加入。這讓同一張板子能支援不同感測器,只要切換 overlay 檔案。
tegracam 是 NVIDIA 對 V4L2 subdev 框架的擴充。probe 鏈路:DTB 解析 → I2C client 匹配 → 驅動 probe → media entity 註冊 → /dev/videoN 產生。
| 階段 | 驅動動作 | 除錯工具 |
|---|---|---|
| DTB 解析 | kernel 讀取 overlay,建立 i2c_client | dtc -I dtb -O dts 檢查 |
| I2C 匹配 | compatible string 匹配驅動 | dmesg | grep probe |
| media 註冊 | tegracam_device_register → 建立 entity graph | media-ctl -p |
| video device | vb2 queue 建立 → /dev/videoN | v4l2-ctl --list-devices |
| 症狀 | 可能原因 | 解決方案 |
|---|---|---|
| dmesg 有 probe 成功但 /dev/videoN 不存在 | media entity 未正確註冊 或 vb2 queue 建立失敗 | media-ctl -p 檢查 pipeline;確認驅動中 v4l2_device_register 呼叫 |
| DTB overlay 套用後 dmesg 出現 "of_device_alloc failed" | overlay 中某屬性值超出 kernel 限制(例如 clock-frequency 過大) | 簡化 overlay 屬性;逐一註釋定位問題屬性 |
| 多個 DTB overlay 同時套用時衝突 | 兩個 overlay 修改了同一個節點的同一個屬性 | 確保每個 overlay 針對不同節點;或合併為單一 overlay |
| 感測器驅動 probe 時 "camera module not detected" | I2C 匯流排未初始化 或 感測器 reset pin 狀態不對 | 檢查 DTB 中 reset-gpios 和 clocks 節點;用示波器量 reset pin 時序 |
| overlay 套用後需要重開機才生效 | 部分 overlay 不支持 hot-plug(DTB 載入時序限制) | 確認 overlay 是否標記為 "reboot required";用 dtoverlay 動態套用測試 |
場景:一顆非官方感測器(假設 OV2775,I2C 0x10、4-lane、RAW10)要在 Orin 上跑起來。專案目標:從驅動 stub → DTB overlay → probe → argus 列舉,端到端整合,並把流程文件化。
# M1 · 驅動骨架(依 tegracam 慣例,OV9281 為藍本) # - 建立 ov2775.c:init table + get/set controls # - compatible = "ovti,ov2775" # M2 · DTB overlay(回顧 4.12 流程) # - fragment target = csi_i2c bus,reg = 0x10 # - mode0:4-lane、RAW10、active_w/h、pixel_phase # M3 · 編譯 + 套用 + 重開機 dtc -@ -I dts -O dtb -o ov2775.dtbo ov2775.dts sudo cp ov2775.dtbo /boot/dtb/overlays/ && sudo reboot # M4 · 驗證鏈路(逐層確認) dmesg | grep -i ov2775 # probe success + ID media-ctl -p -d /dev/media0 # ov2775 出現在拓撲 v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls # exposure/gain 在列 argus_camera --list-cameras # 看得到 ov2775 argus_camera --mode 0 --capture-auto 1 --duration 1 # 出圖
專案驗收:四個里程碑全過 = 整合完成。若 M4 卡住,依 4.15 挑戰題 3 的方法做系統化排查(dmesg "Unable to match" → compatible string 對不上)。
dmesg | grep -i "camera|tegra-camera" → 無 error。dmesg | grep -i <sensor> → probe success + 讀到 ID。media-ctl -p → 感測器→CSI→VI 完整。v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls → exposure/gain 範圍符合 mode。argus_camera --list-cameras → 相機出現。argus_camera --mode 0 --capture-auto 1 --duration 1 + 取 RAW 驗證尺寸/格式。| 面向 | Orin Nano | RPi5 | Orange Pi | Thor |
|---|---|---|---|---|
| 感測器框架 | tegracam | libcamera IPA | V4L2 subdev | tegracam + Holoscan |
| 設定介面 | DTB mode + overlay | dtoverlay + 核心 patch | overlay / 核心 | DTB + Holoscan |
| controls 來源 | tegracam 統一 | libcamera 控制 | V4L2 原生 | tegracam |
| 自寫驅動難度 | 中(tegracam 慣例) | 中(libcamera pipeline) | 低(原生 V4L2) | 高(需 Holoscan 對接) |
| 調校介面 | NVIDIA tuning | tuning file(JSON) | 無 / 陽春 | NVIDIA tuning |
| 步驟 | 操作 | 驗證目標 | 預期輸出 |
|---|---|---|---|
| 1. dmesg probe | dmesg | grep ov9281 | 驅動 probe 成功 | probe success + chip ID |
| 2. media 拓撲 | media-ctl -p | entity 鏈路完整 | ov9281→csi→vi 完整路徑 |
| 3. subdev controls | v4l2-ctl -d subdev0 --list-ctrls | exposure/gain 範圍 | min/max 與 DTB mode 一致 |
| 4. format 確認 | v4l2-ctl -d video0 --list-formats-ext | 支援的 fourcc | SRGGB10 + 尺寸 + 幀率 |
| 5. Argus 列舉 | argus_camera --list-cameras | 相機可見 | camera ID 出現 |
| 6. 取幀驗證 | v4l2-ctl --stream-mmap=1 --stream-count=1 | 幀大小正確 | W × H × 2 bytes |
#!/bin/bash
echo "=== Phase 1: Overlay 套用確認 ==="
dmesg | grep -i "camera|ov9281" | tail -5
echo ""
echo "=== Phase 2: Media 拓撲 ==="
media-ctl -p -d /dev/media0 2>/dev/null || echo "WARN: no media0"
echo ""
echo "=== Phase 3: Controls ==="
v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls 2>/dev/null | head -20
echo ""
echo "=== Phase 4: Formats ==="
v4l2-ctl -d /dev/video0 --list-formats-ext 2>/dev/null
echo ""
echo "=== Phase 5: Argus ==="
argus_camera --list-cameras 2>/dev/null || echo "WARN: argus failed"
echo ""
echo "=== Phase 6: Capture ==="
v4l2-ctl -d /dev/video0 --stream-mmap=1 --stream-count=1 --stream-to=dtb_test.raw 2>/dev/null
ls -l dtb_test.raw 2>/dev/null1. "of_device_alloc failed"? ├─ 是 → overlay 屬性超出 kernel 限制 │ 簡化 overlay:逐一註釋定位問題屬性 └─ 否 ┐ 2. "Unable to match"? ├─ 是 → compatible string 與驅動不匹配 │ 確認驅動模組已載入(lsmod | grep ov) └─ 否 ┐ 3. "probe failed: -12"(ENOMEM)? ├─ 是 → kernel 記憶體不足 │ 減少不必要的 overlay / module └─ 否 ┐ 4. probe 成功但無 /dev/videoN? ├─ 是 → media entity 註冊失敗 │ media-ctl -p 檢查 pipeline └─ 否 → ✅ probe 正常
1. 兩個 overlay 同時套用後異常? ├─ 是 ┐ │ 2. 是否修改了同一節點的同一屬性? │ ├─ 是 → 合併為單一 overlay │ └─ 否 → 調整 fragment target 避開衝突 └─ 否 → 逐一移除 overlay 定位問題源
dmesg | grep -i "camera|tegra-camera" → 無 error。dmesg | grep -i <sensor> → probe success + 讀到 ID。media-ctl -p → 感測器→CSI→VI 完整路徑。v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls → exposure/gain 範圍符合 mode。v4l2-ctl -d /dev/video0 --list-formats-ext → fourcc、尺寸、幀率。argus_camera --list-cameras → 相機出現。argus_camera --mode 0 --capture-auto 1 --duration 1 + 取 RAW 驗證尺寸。| 面向 | Orin Nano | RPi5 | Orange Pi | Thor | 推薦 |
|---|---|---|---|---|---|
| 感測器框架 | tegracam | libcamera IPA | V4L2 subdev | tegracam + Holoscan | 各有慣例 |
| 設定介面 | DTB mode + overlay | dtoverlay + 核心 patch | overlay / 核心 | DTB + Holoscan | DTB 為主 |
| controls 來源 | tegracam 統一 | libcamera 控制 | V4L2 原生 | tegracam | 框架統整 |
| 自寫驅動難度 | 中 | 中 | 低 | 高 | DIY → Orange Pi |
| 調校介面 | NVIDIA tuning | tuning file (JSON) | 無 / 陽春 | NVIDIA tuning | 量產 → Orin |
| Overlay 熱插拔 | 需 reboot | 支援 dtoverlay 動態 | 需 reboot | 需 reboot | RPi5 最靈活 |
| Probe 驗證 | dmesg + media-ctl + v4l2-ctl 全平台相同 | 統一流程 | |||