6.1 Bring-up 四件事
| 檢查項 | 驗證 | 工具 |
| 電源 | AVDD/DVDD/DOVDD 到位 | 示波器/電表 |
| Clock | XCLK/MCLK 有輸出 | 示波器 / dmesg |
| I2C | i2cdetect + 讀 ID | i2c-tools |
| MIPI | dmesg 無 CSI 錯誤、media 有資料 | dmesg / media-ctl |
6.2 上電時序(OV5640 需求)
AVDD/DOVDD 穩定→XCLK/MCLK→RESET 釋放→I2C 可通→MIPI 輸出
最常見錯誤:RESET 未釋放就下 I2C → register「看似能寫但沒生效」。Orange Pi 的 RESET/PWDN 腳位由板卡與驅動管理,先確認 GPIO 設定正確。
6.3 用 dmesg 追線索
常見除錯指令
dmesg | grep -i -E "ov5640|csi|mipi|v4l2|probe"
cat /sys/kernel/debug/gpio | grep -i reset
| dmesg 訊號 | 意義 |
ov5640 ... probe success | 驅動 probe 成功 |
probe failure / failed to read chip id | I2C/clock/電源問題 |
CSI: no data | MIPI 沒資料 → 感測器沒輸出 |
6.4 Register dump 實作
透過 controls 與 i2c 讀
v4l2-ctl -d /dev/v4l-subdev0 -C exposure # 讀曝光 control
v4l2-ctl -d /dev/v4l-subdev0 -C analogue_gain
for r in 0x3500 0x3501 0x3502 0x3503; do
echo -n "$r: "; sudo i2ctransfer -y 3 w2@0x3c ${r:2:2} ${r:4:2} r1
done
6.5 Bring-up 決策樹
「沒畫面」決策樹
1. dmesg 有 ov5640 probe?
├─ error ─→ 電源/clock/reset/位址(I2C 0x3c?)
└─ ok ─┐
2. i2cdetect 看到 0x3c?讀到 0x5640?
├─ 否 ─→ I2C 位址/上電問題
└─ 是 ─┐
3. v4l2-ctl 取到幀?
├─ 否 ─→ media 管線/格式(media-ctl 檢查)
└─ 是 ─→ 基本 bring-up ✅
Orange Pi 特別注意:各板卡 BSP 的節點/位址/格式都不同——先確認你板卡「已知可用組合」,否則決策樹第一步就會卡住。
6.7 深入:上電時序與 clock 驗證
電源穩定→MCLK/XCLK→RESET 釋放→I2C 可通→MIPI 輸出
最常見錯誤:RESET 未釋放就下 I2C → register「看似能寫但沒生效」。先確認 GPIO/時序,再碰 register。
dmesg 追線索
dmesg | grep -i -E "ov5640|probe|csi|mipi|v4l2"
6.9 深入原理:上電時序與 PLL/clock 的位元細節
Bring-up 最常卡在「register 能寫但影像不出」——通常不是 register 錯,而是 時序或 clock 沒到位。OV5640 的 clock 由 XCLK 輸入,內部經 PLL 產生感測器主時脈:
| Register | 欄位 | 意義 |
| 0x3035 | PLL 分頻設定 | MIPI 模式下的 clock 計算 |
| 0x3036 | PLL 倍頻 | 決定感測器內部時脈 |
| 0x3106 | clock 源開關 | 內部 clock 啟用 |
| 0x3108 | reset 控制 | 軟體 reset / 切模式 |
上電時序的位元級規則:① AVDD/DOVDD 先穩定 → ② XCLK 必須在 RESET 釋放「之前或同時」開始 → ③ RESET 釋放後要等 t_PW_UP(OV5640 datasheet 約數 ms)才能下 I2C → ④ 之後讀 ID。違反任一順序,感測器可能「不回應」或「回應但 register 寫不進去」。
驅動會幫你:mainline ov5640.c 的 s_power/__power_on 內已實作完整時序。手動 bring-up 只是為了理解「如果沒驅動,該怎麼自己來」。
6.10 完整 Worked Example:從零到有的一條龍 bring-up
步驟 1|確認電源與 clock 硬體
cat /sys/kernel/debug/gpio | grep -i -E "reset|pwdn" # GPIO 狀態
cat /sys/kernel/debug/clk/clk_summary | grep -i xclk # clock 有無 enable
步驟 2|確認 probe 與 ID
dmesg | grep -i ov5640
sudo i2cdetect -y 3
sudo i2cget -y 3 0x3c 0x300a # 0x56
步驟 3|讀 PLL 與上電狀態
for r in 0x3035 0x3036 0x3106 0x3108; do
echo -n "$r: "; sudo i2ctransfer -y 3 w2@0x3c ${r:2:2} ${r:4:2} r1
done
步驟 4|建管線取幀
media-ctl -d /dev/media0 -r
media-ctl -d /dev/media0 -l "'ov5640 3-003c':0->'csi2':0[1]"
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=YUYV \
--stream-mmap=3 --stream-count=1 --stream-to=f.yuv
完成標準:從 GPIO/clock 一路驗證到「取到一幀」。每一關都過才代表 bring-up 完成,不是「register 能寫」就結束。
6.11 疑難排解決策樹:深入版
| 節點 | 失敗點 | 追查 |
| 電源 | AVDD/DVDD/DOVDD 電壓不在規格 | 電表量模組 pin、看電源樹 DT |
| Clock | XCLK 無輸出或頻率錯 | 示波器量 XCLK;對照 DT 的 clock-frequency |
| Reset | RESET 沒釋放 | GPIO debug 檔、DT reset-gpios 高低電位 |
| I2C | ID 讀不到/讀錯 | 回單元 3 決策樹 |
| MIPI | dmesg 有 CSI no-data | 檢查 lane count / 對齊、感測器 MIPI 輸出 register |
| Media | 管線沒連 | media-ctl -p 對照 |
常見錯誤與陷阱:① 用錯 XCLK 頻率(OV5640 需要 6–27 MHz,通常 24 MHz)——PLL 算錯會整批時序不對;② RESET 腳高/低電位搞反(active-low 是常態);③ 誤以為「register 能讀」=「硬體全對」——讀寫只證明 I2C 通,不證明電源/clock/時序對;④ 換了板卡卻沿用舊 bus 編號。
6.12 練習
- 實作「GPIO→clock→ID→取幀」四步,輸出每一步的證據(指令輸出)。
- 讀取 PLL register 群,對照你板卡的 XCLK 頻率寫出計算過程。
- 模擬「RESET 未釋放」情境,記錄 register 讀寫的現象。
- 把 dmesg 的 probe 流程整理成一份檢查表,貼進你的 bring-up SOP。
6.13 回顧練習:完整 Bring-up 演練
- dmesg 確認 probe 成功、讀到 ID。
- media-ctl 確認管線。
- v4l2-ctl 取到幀。
6.14 進階真實情境 Worked Example:從 dmesg 追蹤到 PLL 計算錯誤
場景:Orange Pi Zero 3(Allwinner H618)接 OV5640,dmesg 有 probe 成功但取流時全黑。從 dmesg 追到 PLL 設定錯誤。
步驟 1|抓 dmesg 中的 clock 相關訊息
dmesg | grep -i -E "ov5640|clock|pll|xclk|rate"
# 找到: ov5640 3-003c: xclk (24000000 Hz) ...
步驟 2|讀 PLL register 並手算
for r in 0x3035 0x3036 0x3106; do
h=${r:2:2}; l=${r:4:2}
echo -n "$r: "; sudo i2ctransfer -y 3 w2@0x3c 0x$h 0x$l r1
done
步驟 3|對照 datasheet 計算 MIPI clock
# OV5640 PLL: PLL_multiplier / PLL_prediv / sys_divider
# 若算出 MIPI clock 超過 D-PHY 上限 → 全黑
設計決策:Allwinner H618 的 CSI 接收器對 MIPI clock 更敏感——RK3588 通常有更寬的容忍範圍。H618 上 PLL 設定稍偏就可能全黑,而 RK3588 可能只是幀率異常。
6.15 深入原理擴充:Allwinner CIF vs RK3588 ISP3 的上電時序差異
| 項目 | Allwinner CIF | RK3588 ISP3 |
| 上電序列 | AVDD → DOVDD → XCLK → RESET釋放 | AVDD → DOVDD → DVDD → XCLK → RESET釋放 |
| Clock 啟用 | DT clock-frequency 直接驅動 | 需額外設定 clock-output-names |
| Reset 極性 | 通常 active-low | 依 DT reset-gpios 設定 |
| probe 失敗後重試 | 需完整 power cycle | 可 unbind/bind driver |
容易忽略的邊界案例:RK3588 的 ISP3 支援「warm reset」(不重上電就重置感測器),但 Allwinner CIF 不支援——在 H618 上 probe 失敗後,必須完整斷電重來。這在量產環境的自動復位策略中會造成額外停機時間。
6.16 診斷式疑難排解表
| 症狀 | 可能原因 | 解決方案 |
| dmesg 有 probe success 但 i2cdetect 沒 0x3c | probe 時 I2C 通但之後 bus 被其他裝置佔用 | 重新掃描 I2C bus;檢查是否有其他驅動佔用同一 bus |
| XCLK 有輸出但 frequency 不對 | DT 的 clock-frequency 與實際不符 | 用示波器量 XCLK;對齊 DT 設定(OV5640 需 24MHz) |
| RESET GPIO 狀態正確但 probe 失敗 | RESET 釋放後未等 t_PW_UP 就下 I2C | 在驅動中加入 delay(OV5640 約需 5ms) |
| RK3588 ISP3 probe 成功但取流 EBUSY | ISP 被其他 process 佔用(如 GStreamer 殘留) | kill 所有 gst-launch 進程;檢查 fuser /dev/video0 |
| H618 probe 成功但全黑 | PLL 計算錯誤導致 MIPI clock 超限 | 讀 PLL register(0x3035/0x3036),對照 datasheet 計算 |
6.17 進階挑戰題
- 在 Allwinner H618 上模擬「RESET 未釋放」:用
gpio 工具手動拉低 reset GPIO,觀察 i2ctransfer 的回應變化。記錄每種症狀。
- 在 RK3588 上,用
media-ctl -p 找出 ISP3 的所有 pad,並手動設定 ISP 輸出格式為 NV12(而非 YUYV)。比較兩者的 sizeimage 差異。
- 設計一支 bring-up 自動化腳本:依序檢查電源→clock→I2C→ID→取流,每步回傳 pass/fail,最終產出一份 HTML 報告。
6.18 專案級 Worked Example:完整感光元件 bring-up 專案 — 從 DT overlay 到第一張圖
把單元 1–6 串成一個完整 bring-up 專案:從一片空白板卡開始,寫 DT overlay → probe → 建管線 → 取到第一張圖。這是「能獨立 bring-up 一顆感測器」的總驗收。
階段 1|硬體盤點(單元 1)
uname -a
sudo i2cdetect -l
ls /dev/video* /dev/v4l-subdev* 2>/dev/null
階段 2|寫 DT overlay(單元 6)
/dts-v1/;
/plugin/;
&i2c3 {
status = "okay";
ov5640: ov5640@3c {
compatible = "ovti,ov5640";
reg = <0x3c>;
clocks = <&clk_cam0>;
clock-frequency = <24000000>;
reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
pinctrl-0 = <&camera_pwr_en>;
};
};
階段 3|probe + 讀 ID(單元 3)
sudo dtoverlay ov5640.dtbo
sudo reboot
dmesg | grep -i -E "ov5640|probe"
sudo i2cget -y 3 0x3c 0x300a # 0x56
階段 4|建管線取第一張圖(單元 5)
media-ctl -d /dev/media0 -r
media-ctl -d /dev/media0 -l "'ov5640 3-003c':0->'csi2':0[1]"
media-ctl -d /dev/media0 -V "'ov5640 3-003c':0[fmt:UYVY8_2X8/1280x720]"
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=YUYV \
--stream-mmap=3 --stream-count=1 --stream-to=first.yuv
ls -l first.yuv # 1,843,200 bytes
專案完成標準:四階段全過 = 你已具備獨立 bring-up 能力。把每階段輸出存成 bringup_log.txt,這是你團隊「已知可用組合」文件的第一筆資料。
6.19 量測/驗證 SOP:bring-up 全流程驗收
| 階段 | 驗證項目 | 通過判據 |
| 1. 電源 | AVDD/DVDD/DOVDD 電壓 | 電表量測符合 datasheet(單元 6.1) |
| 2. Clock | XCLK 頻率 | 示波器量到 ~24 MHz |
| 3. Reset | RESET 極性與釋放 | GPIO debug 顯示 high(active-low) |
| 4. I2C | i2cdetect + 讀 ID | 0x3c 出現,讀回 0x56/0x40 |
| 5. Media | media-ctl entity 與 link | sensor+csi+video 齊全 |
| 6. 出圖 | v4l2-ctl 取幀 | 取得正確 sizeimage 的幀 |
SOP 紀律:bring-up 是「依序過關」,不是「找到一個就結束」。電源 → clock → reset → I2C → media → 出圖,每一關的證據(指令輸出)都要留存,才能讓下一個人複製你的成功。
6.20 平台間對照:Sensor Bring-up
| 面向 | Orange Pi | RPi5 | Orin Nano | Thor |
| overlay 機制 | dtbo + dtoverlay | config.txt dtoverlay | Device tree + board config | Device tree + Holoscan |
| XCLK 來源 | 板卡 clock 樹 | RPi 專屬 clock | 感測器電源板 | 感測器電源板 |
| probe 日誌 | dmesg(全開放) | dmesg + libcamera log | dmesg(部分封閉) | dmesg + Holoscan log |
| 錯誤重試 | unbind/bind 驅動 | 重載 libcamera | 重開 service | 重開 pipeline |
| 除錯深度 | 完全可見(register 層) | 高但被抽象 | 低(封閉) | 低(封閉) |
核心領悟:Orange Pi 的 bring-up 是最「裸露」的——所有失敗都看得見、也可全手動操作。這正是練習 bring-up 的最佳平台;在 NVIDIA 平台,這些細節被封裝起來,學習成本反而更高。
6.21 互動式檢核清單:本單元進階驗收
checklist
- [ ] 我能從零寫出一個 OV5640 的最小 DT overlay。
- [ ] 我能依序驗證電源 → clock → reset → I2C → media → 出圖。
- [ ] 我已產出帶指令輸出的 bringup_log.txt。
- [ ] 我能從 dmesg 分辨 probe 失敗的根因類別。
- [ ] 我理解 t_PW_UP 為何是「register 寫不進去」的隱藏殺手。
- [ ] 我能把 bring-up 知識應用於不同 SoC(RK3588 vs H618)。
6.22 Register 位元級完整工作流
Sensor bring-up 的「讀→改→寫→驗證」是驅動工程師的核心技能。以下是完整的位元級序列:
| 步驟 | 暫存器/位址 | 位元欄位 | 操作 | 預期值 |
| 1. 確認電源 | GPIO debug | AVDD/DVDD level | cat /sys/kernel/debug/gpio | grep power | high(已上電) |
| 2. 確認 reset | GPIO debug | reset level | cat /sys/kernel/debug/gpio | grep reset | high(已釋放) |
| 3. 讀 sensor ID | 0x300A + 0x300B | [7:0] | i2cget -y 3 0x3c 0x300a; i2cget ... 0x300b | 0x56 + 0x40 |
| 4. 驗證 PLL | 0x3035 | [7:4] | i2cget ... 0x3035 | 依 DT clock |
| 5. 建 media link | /dev/media0 | — | media-ctl -l "...:0->...:0[1]" | link active |
| 6. 設定 format | /dev/media0 | — | media-ctl -V "...:0[fmt:SRGGB10_1X10/1920x1080]" | 格式設定成功 |
| 7. 取流驗證 | /dev/video0 | — | v4l2-ctl --stream-mmap=1 --stream-count=1 | 成功產出檔案 |
位元級關鍵: bring-up 的每一步都有「通過/失敗」的明確判據。0x300A=0x56 是 I2C 通的鐵證;dmesg "probe success" 是驅動綁定的鐵證;sizeimage 正確是管線正常的鐵證。
6.23 多層疑難排解決策樹
決策樹 A:probe 失敗
決策樹 A
dmesg | grep "probe"
├─ "probe failed" → 依錯誤:
│ ├─ "no chip id" → I2C 通但 ID 錯
│ │ ├─ 嘗試其他 I2C 位址(0x3c/0x36)
│ │ └─ 確認感測器型號(OV5640 vs OV9281)
│ ├─ "clk prepare failed" → clock 未就緒
│ │ └─ 檢查 DT clock-frequency 設定
│ ├─ "reset" → reset GPIO 問題
│ │ └─ 檢查 reset-gpios 極性(active-low/high)
│ └─ "power" → 電源異常
│ └─ 量測 AVDD/DVDD/DVDD18 電壓
└─ "probe success" → 驅動綁定成功
└─ 檢查 /dev/video* 是否存在
決策樹 B:probe 成功但無圖
決策樹 B
v4l2-ctl --stream-mmap=1 --stream-count=1
├─ 無輸出 → media-ctl 未建 link
│ └─ 依序:media-ctl -l → media-ctl -V → v4l2-ctl
├─ 全黑 → sensor 無曝光
│ ├─ 手動曝光:v4l2-ctl --set-ctrl=exposure=500
│ └─ 驗證:i2cget 0x3500~0x3502
├─ 斜圖 → format 錯誤
│ └─ 檢查 bytesperline 與 Bayer order
└─ 全白 → 過曝
└─ 減少 analog gain:v4l2-ctl --set-ctrl=gain=16
6.24 量測驗證完整 SOP
| 步驟 | 指令 | 預期輸出 | 判讀標準 |
| 1. dmesg probe | dmesg | grep -i "ov5640\|probe" | "probe success" | 無 error/warning |
| 2. I2C 讀 ID | i2cget -y 3 0x3c 0x300a | 0x56 | 感測器正常 |
| 3. media graph | media-ctl -p | sensor → csi → video | 完整管線 |
| 4. 設定 format | media-ctl -V | SRGGB10/1920x1080 | 正確格式 |
| 5. 建 link | media-ctl -l | link active | 正確 pad |
| 6. 取一幀 | v4l2-ctl --stream-mmap=1 --stream-count=1 | 成功 | sizeimage 正確 |
| 7. 連續取流 | v4l2-ctl --stream-mmap=4 --stream-count=100 | 100 幀無 error | 穩定無掉幀 |
6.25 四平台終極對照
| 面向 | Orange Pi | RPi5 | Orin Nano | Thor | 推薦 |
| bring-up 難度 | 中(完全手動) | 低(libcamera) | 低(封裝好) | 低(封裝好) | 學習→Orange Pi |
| 除錯深度 | 完全可見 | 高 | 低(封閉) | 低(封閉) | 除錯→Orange Pi |
| DT overlay | dtbo + dtoverlay | config.txt | Board config | Holoscan | Orange Pi 最透明 |
| dmesg | 完全開放 | 完整 | 部分封閉 | 部分封閉 | Orange Pi 最佳 |
| probe 日誌 | dmesg | dmesg + libcamera | dmesg(部分) | dmesg + Holoscan | Orange Pi 最詳細 |
6.26 完整 Bring-up 專案 Checklist
checklist
- [ ] 確認 SoC 型號與 DT overlay
- [ ] 量測 AVDD/DVDD/DVDD18 電壓
- [ ] 確認 reset GPIO 極性與時序
- [ ] 讀取 0x300A + 0x300B 確認 ID
- [ ] dmesg 確認 "probe success"
- [ ] 用 media-ctl -p 確認完整管線
- [ ] 設定 format + 建 link
- [ ] v4l2-ctl 取一幀驗證 sizeimage
- [ ] 產出 bringup_log.txt(含所有指令輸出)
- [ ] 用「電源→clock→reset→I2C→media→出圖」序列除錯
- [ ] 確認 t_PW_UP 時序(reset 後等 10ms 再 I2C)
- [ ] 驗證 bring-up 可重現(重啟後複製流程)
看完這單元你應該能說出:
- Bring-up 四件事。
- 用 dmesg 追 probe/CSI 錯誤。
- 透過 controls 與 i2c 讀 register。
- 照決策樹排解。
延伸閱讀