嵌入式裝置按下電源到看見畫面/服務就緒,中間其實經過好幾個獨立的階段,各自有不同的除錯方式。這篇筆記把整條開機流程拆開來看。

開機流程總覽

Power On
  └─ ROM Code / BootROM
       └─ SPL (Secondary Program Loader)
            └─ U-Boot(或其他 Bootloader)
                 └─ Linux Kernel
                      └─ initramfs / initrd
                           └─ systemd (PID 1)
                                └─ 使用者服務

1. ROM Code:不能被更新的第一段程式

晶片出廠就燒錄好的一小段程式碼,負責找到下一階段的載入器(通常在 eMMC、SPI NOR 或 SD 卡的固定位址)。這段程式無法透過韌體更新修改,出問題基本上等於磚。

2. Bootloader:初始化硬體、載入 Kernel

U-Boot 這類 Bootloader 主要做三件事:

  • 初始化 DRAM、時脈、基本周邊
  • 從儲存裝置讀出 Kernel image、Device Tree、initramfs
  • 把控制權交給 Kernel,並透過 command line 傳遞開機參數(如 console=root=

除錯技巧:接 UART console,觀察 U-Boot 印出的 log;printenv 可以檢查目前的環境變數是否指向正確的 kernel/dtb 位置。

3. Kernel 初始化

Kernel 解壓縮後開始跑,依序完成:

  1. 架構相關初始化(MMU、cache)
  2. Device Tree 解析,掛載對應的 driver
  3. 掛載根檔案系統(依 root= 參數)
  4. 執行 /sbin/init(通常就是 systemd)

如果卡在這個階段,常見原因是 Device Tree 與實際硬體對不上,或是 root 檔案系統的路徑/檔案系統型別設錯。

4. systemd:使用者空間的起點

systemd 接手後依照 target 之間的相依關係平行啟動服務,取代傳統 init script 的序列式啟動,這也是開機時間能明顯縮短的原因。

常用除錯指令:

指令 用途
systemd-analyze 列出開機總耗時
systemd-analyze blame 列出各服務啟動耗時排行
systemd-analyze critical-chain 找出開機時間的關鍵路徑
journalctl -b 檢視這次開機的完整 log

小結

嵌入式開機問題排查的第一步,永遠是先判斷「卡在哪一階段」——UART 看不到任何輸出通常是 ROM Code / SPL 沒吃到;能看到 U-Boot 但進不了 Kernel,多半是 image 或 DTB 有問題;能進 Kernel 但服務起不來,就該把矛頭轉向 systemd 跟你自己寫的 service unit。