單元 4 · 平台相機框架與驅動

tegracam、DTB overlay

tegracam 驅動框架

NVIDIA 用 tegracam 承接感測器驅動,統一曝光/增益 controls,讓 Argus 能列舉相機。

DTB 感測器節點

camera 節點(示意)
&ov9281_cam0 {
    status = "okay";
    reg = <0x36>;        # I2C 位址
    reset-gpios = ...;
    mode0 { ... mclk_khz, pixel_phase ... };
};

修改 DTB 需重編 device tree 並刷入(或 bootloader overlay)。

Argus 如何看到相機

列出相機
argus_camera --list-cameras
v4l2-ctl --list-devices
調校關鍵:驅動註冊正確,Argus 才看得到相機;看得到才能控制與調校。
看完這單元你應該能說出:
  • tegracam 角色。
  • DTB 感測器節點宣告。
  • Argus 列舉相機。
  • 驅動→Argus→ISP 關係。

4.4 深入原理:tegracam 在 Linux 相機棧的位置

感測器驅動tegracam 框架tegra-camera(V4L2 subdev)VI5(video capture)Argus / V4L2 userspace

tegracam 提供統一的 V4L2 controls(exposure、gain、white balance…),感測器驅動只要實作 init table 與 register 讀寫,就能把曝光/增益暴露給 userspace。這就是「Argus 設曝光 → 最後落到感測器 register」的橋樑。

角色除錯時看什麼
感測器驅動I2C 讀寫 + init tableprobe 訊息、ID 讀取
tegracam統整 V4L2 controlsv4l2-ctl -C 列表
VI5CSI 收 framedmesg 的 vi5/csi 錯誤
Argus會話式相機 APIargus_camera 出圖

4.5 深入原理:DTB camera 節點與 mode

每個感測器在 DTB 宣告一個 camera 節點,內含 mode0/mode1…,每個 mode 定義解析度、幀率、CSI lane 數、Bayer order、曝光/增益範圍與 pixel_phase

OV9281 camera 節點(模式重點)
&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>;
    };
};
mode 對不上的後果:Argus 列出的解析度/幀率/曝光範圍來自 mode——mode 寫錯,userspace 就「看不到」正確選項,甚至 probe 直接失敗。改 DTB 需重編 device tree 並刷入。

4.6 Worked Example:從 DTB 到 Argus 列舉

逐步驗證
# 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。

4.7 常見錯誤 / 陷阱

陷阱 ①:改了 DTB 卻沒重新產生 DTB 並刷入 bootloader——「改了但沒生效」最常見。
陷阱 ②:pixel_phase 與感測器實際 Bayer 起點不符——色彩全錯,而且 V4L2 不會報錯。
陷阱 ③:mode 的 max_framerate/曝光範圍設定太窄——AE 自動收斂會卡住(回顧單元 10)。

4.8 練習

  1. 用 media-ctl 畫出你的 media 管線拓撲並記錄。
  2. 列出 v4l-subdev0 的 exposure / gain 範圍。
  3. 解釋「改 DTB 後看不到相機」的除錯順序。

4.9 進階:media-ctl 管線與格式設定

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]'
格式不連貫的後果:感測器輸出 RAW10、VI 卻設成 NV12 → 出圖失敗或花屏。每個 pad 的格式都要「沿著管線連貫」。

4.10 快速參考:驅動層除錯小抄

檢查指令通過標準
probedmesg | grep -i ov9281有 probe/ID 訊息
拓撲media-ctl -p感測器→CSI→VI 完整
controlsv4l2-ctl -d /dev/v4l-subdev0 --list-ctrlsexposure/gain 在列
列舉argus_camera --list-cameras看得到相機

4.11 看完本單元該記住的三件事

tegracam 把感測器控制統整成 V4L2 controls,Argus 才用得上。
DTB 的 camera 節點 + mode 定義了「userspace 看得到的選項」。
改 DTB 要重編並刷入,改完要驗證(probe + media + argus)。

4.12 Worked Example:改 DTB 後的完整驗證流程

改 mode 後驗證
# 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
陷阱:「dmesg 沒 error」不代表新 mode 生效——以「列得出 + 取得到 + 尺寸對」三項為準。

4.13 看完本單元該記住的三件事

tegracam 是感測器控制與 Argus 的橋樑。
DTB mode 定義 userspace 看得到的選項。
改完 DTB 要「重編 → 刷入 → 列舉 → 取幀」驗證。

延伸閱讀

4.12 進階真實情境 Worked Example:從零建立客製感測器的 DTB overlay

場景:你有一顆非標準的 OmniVision 感測器(例如 OV2775),官方 DTB 沒有支援。你需要從 datasheet 出發,建立完整的 DTB overlay。

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 檔案。

4.13 深入原理擴充:tegracam 框架的 probe 鏈路

tegracam 是 NVIDIA 對 V4L2 subdev 框架的擴充。probe 鏈路:DTB 解析 → I2C client 匹配 → 驅動 probe → media entity 註冊 → /dev/videoN 產生。

階段驅動動作除錯工具
DTB 解析kernel 讀取 overlay,建立 i2c_clientdtc -I dtb -O dts 檢查
I2C 匹配compatible string 匹配驅動dmesg | grep probe
media 註冊tegracam_device_register → 建立 entity graphmedia-ctl -p
video devicevb2 queue 建立 → /dev/videoNv4l2-ctl --list-devices
陷阱:「DTB 正確 + I2C probe 成功」不代表一切正常——media pipeline 可能沒接好。例如:DTB 宣告了 2 lane 但實體只接了 1 lane,probe 不會失敗(I2C 通就好),但出圖時 CSI 收不到資料。

4.14 診斷式疑難排解表

症狀可能原因解決方案
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 動態套用測試

4.15 進階挑戰題

  1. 為一顆你手邊的感測器(或假設 OV2775)撰寫完整的 DT overlay,包含:I2C 節點、clock、reset、port/endpoint。用 dtc 驗證語法正確。
  2. 畫出 tegracam probe 鏈路的流程圖:從「開機讀取 DTB」到「/dev/videoN 產生」的每一步,標出每步可能失敗的原因。
  3. 若你的 DTB overlay 套用後 dmesg 出現 "Unable to match" 錯誤,設計一個系統化的排查流程找出根本原因。

4.16 專案級端到端 Worked Example:客製感測器驅動整合專案

場景:一顆非官方感測器(假設 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 對不上)。

4.17 量測/驗證 SOP:DTB/驅動修改驗證

  1. 套用確認dmesg | grep -i "camera|tegra-camera" → 無 error。
  2. probe 確認dmesg | grep -i <sensor> → probe success + 讀到 ID。
  3. 拓撲確認media-ctl -p → 感測器→CSI→VI 完整。
  4. controls 確認v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls → exposure/gain 範圍符合 mode。
  5. 列舉確認argus_camera --list-cameras → 相機出現。
  6. 出圖確認argus_camera --mode 0 --capture-auto 1 --duration 1 + 取 RAW 驗證尺寸/格式。
陷阱提醒:「dmesg 沒 error」≠ 生效——以「列得出 + 取得到 + 尺寸對」三項為準(回顧 4.12)。

4.18 平台間對照:驅動框架

面向Orin NanoRPi5Orange PiThor
感測器框架tegracamlibcamera IPAV4L2 subdevtegracam + Holoscan
設定介面DTB mode + overlaydtoverlay + 核心 patchoverlay / 核心DTB + Holoscan
controls 來源tegracam 統一libcamera 控制V4L2 原生tegracam
自寫驅動難度中(tegracam 慣例)中(libcamera pipeline)低(原生 V4L2)高(需 Holoscan 對接)
調校介面NVIDIA tuningtuning file(JSON)無 / 陽春NVIDIA tuning
重點:Orin / RPi5 都有「框架層」幫你統一 controls;Orange Pi 最接近底層;Thor 與 Orin 同框架但加上 Holoscan 應用層。

4.19 互動式檢核清單:驅動 / DTB 驗收

4.20 Register 位元級完整工作流:DTB Camera 節點 Mode 驗證

步驟操作驗證目標預期輸出
1. dmesg probedmesg | grep ov9281驅動 probe 成功probe success + chip ID
2. media 拓撲media-ctl -pentity 鏈路完整ov9281→csi→vi 完整路徑
3. subdev controlsv4l2-ctl -d subdev0 --list-ctrlsexposure/gain 範圍min/max 與 DTB mode 一致
4. format 確認v4l2-ctl -d video0 --list-formats-ext支援的 fourccSRGGB10 + 尺寸 + 幀率
5. Argus 列舉argus_camera --list-cameras相機可見camera ID 出現
6. 取幀驗證v4l2-ctl --stream-mmap=1 --stream-count=1幀大小正確W × H × 2 bytes
DTB overlay 套用 → 完整驗證腳本
#!/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/null

4.21 多層疑難排解決策樹

決策樹 A:DTB overlay 套用後 dmesg 出 error
1. "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 正常
決策樹 B:多個 overlay 衝突
1. 兩個 overlay 同時套用後異常?
   ├─ 是 ┐
   │   2. 是否修改了同一節點的同一屬性?
   │      ├─ 是 → 合併為單一 overlay
   │      └─ 否 → 調整 fragment target 避開衝突
   └─ 否 → 逐一移除 overlay 定位問題源

4.22 量測驗證完整 SOP

  1. Overlay 套用dmesg | grep -i "camera|tegra-camera" → 無 error。
  2. Probe 確認dmesg | grep -i <sensor> → probe success + 讀到 ID。
  3. 拓撲確認media-ctl -p → 感測器→CSI→VI 完整路徑。
  4. Controls 確認v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls → exposure/gain 範圍符合 mode。
  5. Formats 確認v4l2-ctl -d /dev/video0 --list-formats-ext → fourcc、尺寸、幀率。
  6. Argus 列舉argus_camera --list-cameras → 相機出現。
  7. 出圖確認argus_camera --mode 0 --capture-auto 1 --duration 1 + 取 RAW 驗證尺寸。
  8. 改動回歸:每次改 DTB 後重跑 Step 1-7;「dmesg 沒 error」≠ 生效——以「列得出 + 取得到 + 尺寸對」三項為準。
判讀標準:Step 1-6 全 pass + Step 7 幀大小正確 + Step 8 每次改動後回歸通過。

4.23 四平台终极對照

面向Orin NanoRPi5Orange PiThor推薦
感測器框架tegracamlibcamera IPAV4L2 subdevtegracam + Holoscan各有慣例
設定介面DTB mode + overlaydtoverlay + 核心 patchoverlay / 核心DTB + HoloscanDTB 為主
controls 來源tegracam 統一libcamera 控制V4L2 原生tegracam框架統整
自寫驅動難度DIY → Orange Pi
調校介面NVIDIA tuningtuning file (JSON)無 / 陽春NVIDIA tuning量產 → Orin
Overlay 熱插拔需 reboot支援 dtoverlay 動態需 reboot需 rebootRPi5 最靈活
Probe 驗證dmesg + media-ctl + v4l2-ctl 全平台相同統一流程

4.24 完整 Bring-up 專案 Checklist