單元 6 · Sensor Bring-up 與除錯

serdes、register dump、決策樹

6.1 Bring-up 四件事

檢查項驗證工具
電源AVDD/DVDD 到位、時序示波器/電表
ClockMCLK 輸出、PLL 鎖定示波器 / dmesg
I2Ci2cdetect(GMSL 先打通 deserializer)i2c-tools
MIPIdmesg 無 CSI 錯誤、argus 列舉dmesg / argus

6.2 上電時序(工業模組通用)

AVDD/DVDD 穩定MCLKRESET 釋放I2C 可通(GMSL 經 serdes)MIPI 輸出
最常見錯誤:RESET 未釋放就下 I2C → register「看似能寫但沒生效」。Orin 上 GMSL 模組的 reset/電源由模組與 DTB 管理。

6.3 GMSL serdes 除錯(三步)

GMSL 三步:① deserializer(如 MAX96712)的 I2C 通道切到對的 link ② 確認 serdes lock(vendor 工具)③ 感測器 I2C 才可通。先確認 lock,再談感測器——這是 GMSL 與 CSI 直連最大的不同。

6.4 用 dmesg 追線索

除錯指令
dmesg | grep -i -E "ov9281|tegra-camera|vi5|csi"
cat /sys/kernel/debug/bpmp/debug/clk/...   # 檢查 clock
dmesg 訊號意義
tegra-camera-rtcpu 正常載入相機 RTCPU 就緒
vi5: probe success影像單元就緒
csi: no data / timeoutMIPI 沒資料 → serdes/感測器

6.5 Register dump 實作

透過 tegracam controls
v4l2-ctl -d /dev/v4l-subdev0 -C exposure
v4l2-ctl -d /dev/v4l-subdev0 -C analogue_gain

6.6 Bring-up 決策樹

「argus 看不到相機」決策樹
1. dmesg 有 tegra-camera/感測器 probe?
   ├─ error ─→ DTB / 電源 / serdes
   └─ ok ─┐
2. (GMSL) serdes lock?
   ├─ 否 ─→ deserializer / 線材 / 通道
   └─ 是 ─┐
3. i2cdetect 讀到感測器 ID?
   ├─ 否 ─→ I2C 通道 / 位址
   └─ 是 ─┐
4. argus_camera 出圖 → ✅

6.7 深入:上電時序與 clock 驗證

電源穩定MCLK/XCLKRESET 釋放I2C 可通MIPI 輸出
最常見錯誤:RESET 未釋放就下 I2C → register「看似能寫但沒生效」。先確認 GPIO/時序,再碰 register。
dmesg 追線索
dmesg | grep -i -E "ov9281|probe|csi|mipi|v4l2"

6.8 練習:完整 Bring-up 演練

  1. dmesg 確認 probe 成功、讀到 ID。
  2. media-ctl 確認管線。
  3. v4l2-ctl 取到幀。
看完這單元你應該能說出:
  • Bring-up 四件事。
  • GMSL serdes 三步。
  • register dump 實作。
  • 照決策樹排解。

6.9 深入原理:上電時序的寄存器層證據

感測器上電後照時序(電源穩定 → MCLK → RESET 釋放 → I2C 可用)運行。除了示波器,你可以用「行為」判斷到哪一步:

觀察代表下一步
i2cdetect 看到位址但讀 ID 全 0x00I2C 通但感測器還沒初始化完成檢查 RESET/MCLK
i2cdetect 完全看不到I2C 沒通電源/上拉/位址/remap
讀 ID 正確但無 MIPI 輸出感測器活了,CSI 端有問題檢查 lane/clock/DTB mode
有 MIPI 但 argus 不列舉VI/ISP 對接問題檢查 vi5/csi dmesg

6.10 Worked Example:GMSL 模組完整 bring-up

OV9281 經 MAX96712 的 bring-up
# 1. 確認 deserializer 存在
sudo i2cdetect -y 0
# 2. 確認 serdes lock(MAX96712 範例 register)
sudo i2cget -y 0 0x29 0x0012   # lock 應非 0x00(示意)
# 3. 切 I2C 通道到 link(vendor 工具 / regs)
# 4. 讀感測器 ID
sudo i2cget -y 0 0x36 0x300a   # 0x92
# 5. dmesg 確認 probe
dmesg | grep -i ov9281
# 6. 出圖
argus_camera --mode 0 --capture-auto 1 --duration 1
口訣:lock → channel → ID → probe → 出圖。每一步卡住就停在該層除錯,不要往下走。

6.11 疑難排解決策樹:GMSL「沒影像」

決策樹
1. serdes 有 lock?
   ├─ 無 ─┬─ 線材 / 接頭 / 電源
   │      └─ deserializer 設定 / 同軸端接
   └─ 有 ┐
2. 感測器 ID 讀得到?
   ├─ 否 ─→ remap / 通道 / 位址
   └─ 是 ┐
3. dmesg probe 成功?
   ├─ 否 ─→ DTB mode / 電源 / MCLK
   └─ 是 ┐
4. 出圖 → ✅

6.12 常見錯誤 / 陷阱

陷阱 ①:上電後立刻下 I2C——感測器還在 reset,register「寫了但沒生效」。帶一段等待再讀回驗證。
陷阱 ②:GMSL 把「感測器沒輸出」誤判成 CSI 問題——先確認 serdes 真的在傳資料(lock + 回傳計數)。
陷阱 ③:只信 dmesg 的 probe success——那只代表 I2C 通,不代表 MIPI 在傳;要以「取到一幀」為準。

6.13 練習

  1. 對你的平台完整跑一次「四件事 → dmesg → 出圖」。
  2. 做一次「寫入 → 回讀」確認感測器真的接受控制。
  3. 若用 GMSL,把 lock 驗證指令寫進你的 SOP。

6.14 進階:RTCPU 與相機韌體的角色

Orin 的相機處理由 RTCPU(realtime CPU)上的韌體驅動——它負責 CSI 收 frame 的即時時序,而 Linux 驅動只是「配置它」。所以 dmesg 的 tegra-camera-rtcpu 訊息很關鍵:RTCPU 韌體沒載好,即使感測器正常也出不了圖。

實務檢查:開機後 dmesg | grep -i rtcpu,確認相機 RTCPU 正常載入。刷寫 JetPack 版本不一致或 DT overlay 缺料,常導致 RTCPU 靜默失敗。

6.15 快速參考:Bring-up 小抄

步驟驗證工具
電源AVDD/DVDD 時序示波器/電表
ClockMCLK 到位示波器 / dmesg
I2CID 讀得到i2ctransfer
Serdes(GMSL)lockvendor 工具
RTCPU正常載入dmesg
MIPI無 CSI errordmesg
出圖取到一幀argus / v4l2-ctl

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

上電 → clock → reset → I2C → MIPI,順序不可亂。
GMSL 先 lock、再感測器,這是鐵則。
「probe 成功」≠「出圖成功」——以取到幀為準。

延伸閱讀

6.14 進階真實情境 Worked Example:GMSL 模組的完整 bring-up 除錯

場景:新的 GMSL 模組(MAX96712 + OV9281)接上 Orin Nano 後,dmesg 沒有任何感測器 probe 訊息。你需要從零開始除錯。

系統化 bring-up 除錯流程
# Phase 1: 硬體層
# 1a. 確認 deserializer 有電(量 MAX96712 VCC 引腳)
# 1b. 確認 I2C 匯流排可用
i2cdetect -y 0 | grep -E "48|36"
# 期望看到 0x48(MAX96712)和 0x36(OV9281 remap)
# 1c. 若只看到 0x48:link 可能沒 lock
i2cget -y 0 0x48 0x0013  # 讀 link0 lock bit

# Phase 2: 驅動層
# 2a. 檢查 dmesg 有無 max96712 或 ov9281 相關訊息
dmesg | grep -i -E "max96712|ov9281|tegra-camera"
# 2b. 若出現 "i2c: slave addressed but no driver" → DTB overlay 未載入
# 2c. 檢查模組是否編譯進 kernel
lsmod | grep -i "max96712\|ov9281"

# Phase 3: 出圖層
# 3a. 確認 /dev/videoN 存在
ls /dev/video*
# 3b. 用 v4l2-ctl 嘗試取幀
v4l2-ctl -d /dev/video0 --stream-mmap=1 --stream-count=1 --stream-to=test.raw

設計決策:除錯永遠從「最底層」往上走:硬體(電源/連接)→ I2C(通訊)→ 驅動(probe)→ 出圖(串流)。很多人從「出圖失敗」開始猜,浪費時間。

6.15 深入原理擴充:Register Dump 的正確方法

「dump 所有 register」是常見的除錯手法,但方法錯誤會導致感測器狀態改變

方法風險正確做法
i2cget 逐 register 讀低風險(唯讀)用迴圈讀指定範圍(如 0x0000-0x01FF)
i2cget 同時讀+寫(測試功能)中風險(可能觸發 reset)先備份值,改完後恢復
透過 GMSL tunnel 讀高風險(tunnel 延遲 + 超時)降低 I2C 時脈;用 vendor 工具(較穩定)
kernel 調試(dev_dbg)低風險在驅動的 probe 函數中加入 dev_dbg 輸出
陷阱:「讀 register 0x3000~0x30FF 看初始化是否成功」——某些 register 是 write-only 的(例如 OV9281 的 streaming control register),read 回來可能是 0x00,不代表沒設定成功。

6.16 診斷式疑難排解表

症狀可能原因解決方案
i2cdetect 顯示所有位址都是 0x00(bus 沒反應)I2C 匯流排 SDA/SCL 被拉低(短路 或 某裝置 hang)斷電後量 SDA/SCL 對地電阻;逐顆拔除裝置找出問題源
dmesg 有 "probe failed: -12"(ENOMEM)kernel 記憶體不足(太多 overlay 或 module)減少不必要的 DTB overlay;檢查是否有記憶體洩漏的 module
感測器 probe 成功但 v4l2-ctl 出圖全黑streaming 尚未啟用(需先設定 streaming register)確認 OV9281 的 streaming control register(0x0100)已設為 1
GMSL 模組在冷開機時正常,熱開機後找不到serializer/deserializer 在 reset 後未重新初始化在 DTB 中設定 GPIO reset 時序;或在驅動中加入 re-init 邏輯
dmesg 出現 " tegra-camera-rtcpu: firmware not ready"RTCPU firmware 損壞 或 版本不匹配重新刷入 JetPack(確保 firmware 與 kernel 版本一致)

6.17 進階挑戰題

  1. 撰寫一個「三階段 bring-up 自動化腳本」:Phase 1 檢查 I2C 硬體、Phase 2 檢查驅動 probe、Phase 3 嘗試串流。每階段失敗時自動輸出建議的下一步。
  2. 設計一個 register dump + diff 的方法:先 dump 正常工作時的 register 值,再 dump 異常時的值,自動比對差異並標記可疑 register。
  3. 若你的 GMSL 系統在「高溫環境」下偶爾 probe 失敗,設計一個溫度-成功率的測試方案。

6.18 專案級端到端 Worked Example:三階段 bring-up 自動化專案

場景:公司有多種載板 + 多種感測器組合,每次 bring-up 都是人工逐步確認,耗時且易漏。專案目標:把單元 6 的四件事(電源 / clock / I2C / MIPI)與決策樹做成自動化的三階段 bring-up 腳本,一鍵輸出「目前卡在哪一層」。

bringup.sh(三階段骨架)
#!/bin/bash
echo "== Phase 1 · 硬體 / I2C 層 =="
sudo i2cdetect -y 0                      # 看得到 0x36(或 remap 位址)?
sudo i2cget -y 0 0x36 0x300a             # 讀到 0x92?
if [ $? -ne 0 ]; then echo "卡在 Phase 1 → 查電源 / clock / reset / 位址"; exit 1; fi

echo "== Phase 2 · 驅動層 =="
dmesg | grep -i -E "ov9281|tegra-camera|vi5"   # probe success?
ls /dev/video* 2>/dev/null || { echo "卡在 Phase 2 → 查 DTB / 驅動"; exit 1; }

echo "== Phase 3 · 出圖層 =="
v4l2-ctl -d /dev/video0 --stream-mmap=1 --stream-count=1 --stream-to=t.raw
if [ $? -ne 0 ]; then echo "卡在 Phase 3 → 查 media 管線 / 格式"; exit 1; fi
echo "✅ Bring-up 完成"

專案輸出:bringup.sh(單一感測器)+ bringup_all.sh(迴圈處理多顆)。每階段失敗輸出「建議下一步」——把單元 6 的決策樹變成程式碼。

6.19 量測/驗證 SOP:Sensor Bring-up 驗證

  1. 電源:電表 / 示波器確認 AVDD / DVDD 電壓與時序(依 datasheet)。
  2. Clock:示波器量 MCLK;或看 dmesg 的 clock 錯誤。
  3. Reset:確認 reset GPIO 依時序釋放(太早下 I2C → 寫入無效)。
  4. I2C:i2cdetect + 讀 ID(GMSL 先驗 lock)。
  5. Serdes(GMSL):vendor 工具確認每條 link lock。
  6. MIPI / 出圖:dmesg 無 CSI error + 取到一幀。
口訣:lock → channel → ID → probe → 出圖。每一步卡住就停在該層,不要往下走。

6.20 平台間對照:Bring-up 流程

面向Orin NanoRPi5Orange PiThor
上電時序管理DTB + 模組設計硬體固定硬體固定DTB + 模組設計
SerdesGMSL(需 lock)無(CSI 直連)GMSL(HSB)
RTCPU 韌體✅ 需確認✅ 需確認
驅動載入tegracam + DTB核心 patch核心 patchtegracam + DTB
除錯工具dmesg / i2c-tools / media-ctl / v4l2-ctl 全平台相同
重點:Orin / Thor 多兩層(GMSL + RTCPU),RPi5 / Orange Pi 較單純;但「逐層向上、先底層後高層」的哲學完全一致。

6.21 互動式檢核清單:Bring-up 驗收

6.22 Register 位元級完整工作流:I2C Remap + 位址衝突解法

步驟暫存器(MAX96712)說明
1. 複製0x00100x01把 link0 資料複製到 link1
2. link1 alias0x00110x37link1 感測器映射到 I2C 0x37
3. link2 alias0x00120x38link2 感測器映射到 I2C 0x38
4. link3 alias0x00130x39link3 感測器映射到 I2C 0x39
I2C 位址衝突完整解法:逐路 remap
# 四顆 OV9281(均 0x36)→ 分別映到 0x36/0x37/0x38/0x39
DESER_ADDR=0x48

# 逐路設定 alias(高頻傳輸資料則切換)
for i in 0 1 2 3; do
  case $i in
    0) alias=0x36; base=0x36;;
    1) alias=0x37; base=0x36;;
    2) alias=0x38; base=0x36;;
    3) alias=0x39; base=0x36;;
  esac
  
  # 設定:第 i 路的 remote 0x36 → local alias
  i2cset -y 0 $DESER_ADDR $((0x0010 + i)) $alias
  
  echo "link$i: remote 0x36 → local 0x$(printf '%x' $alias)"
done

# 驗證:各路可讀
for alias in 0x36 0x37 0x38 0x39; do
  val=$(i2ctransfer -y 0 w2@0x$alias 0x30 0x0a r1 2>/dev/null)
  [ "0x$val" = "0x92" ] && echo "0x$alias: OK" || echo "0x$alias: FAIL"
done
鐵則:GMSL 多路感測器 I2C remap 是唯一解法。若不同型號同位址,不需要 remap;若同型號(同 default ID),一定要 remap。

6.23 多層疑難排解決策樹

決策樹 A:mode 列出但帶寬不足
1. dmesg 有 "bandwidth exceeded"?
   ├─ 是 ┐
   │   2. 計算當前模式實際需求:
   │      BW = W × H × bits × fps / 1e6
   │      ├─ > 1.5Gbps → 降解析度或幀率
   │      │              或切換到 8-bit mode(減半)
   │      └─ < 1.5Gbps → 檢查 ISP pipeline 其他佔用
   └─ 否 → 非帶寬問題
決策樹 B:v4l2-ctl 有 video0 但 argus 沒相機
1. v4l2-ctl --list-devices 有 /dev/video0?
   ├─ 否 → 驅動問題
   └─ 是 ┐
2. argus_camera --list-cameras 出相機?
   ├─ 否 → argus 四件事缺一:
   │   ├─ 採集器(reg) → dmesg 有错误?
   │   ├─ 描述器(=) → media-ctl -p 正常?
   │   ├─ 物件(O) → 四大物件齊全?
   │   └─ 工廠(F) → v4l2 media pipeline 完整?
   └─ 是 → argus 設定問題(mode/camera-id)

6.24 量測驗證完整 SOP

  1. GMSL locki2cget -y 0 0x48 0x0013 → bit 0-3 有 1。
  2. I2C remap:設定 alias → i2ctransfer -y 0 w2@0x37 0x30 0x0a r1 → 0x92。
  3. dmesg probedmesg | grep -i "probe\|tegra-camera" → 無 error。
  4. mode 限定測試:逐一測可用 mode,記錄每個的字元組數/幀率。
  5. 調整優先序:解析度 → 位元深 → 幀率 → 執行緒數 → ISP bypass。
  6. 單路 bring-up:只開 link0 確認出圖 → 再逐路加。
  7. 多路同時:記錄 VI/ISP bandwidth(v4l2-ctl stats),定義上限。
判讀標準:GMSL lock ✓、I2C remap ✓、逐路出圖 ✓、多路穩定 ✓ = sensor bring-up 完成。

6.25 四平台终极對照

面向Orin NanoRPi5Orange PiThor推薦
GMSL 支援MAX96712 外掛❌ 無❌ 無內建 GMSLGMSL → Orin/Thor
最大輸入路數4 路(MAX96712)2 路(22-pin)1 路8 路多路 → Orin/Thor
ISP bandwidth1.5 Gbps~800 Mbps~400 Mbps>3 Gbps高幀率 → Orin/Thor
I2C remap✅ 必要❌ 不需要❌ 不需要✅ 必要GMSL 專用
除錯工具tegracam/arguslibcamerav4l2-ctlargus + Holoscanv4l2-ctl 通用
mode 限制除錯ISP bandwidthISP bandwidthGPIO / MCLKISP bandwidth各有瓶頸
GMSL 鎖定除錯MAX96712 regN/AN/A內建 regGMSL → Orin/Thor

6.26 完整 Bring-up 專案 Checklist