dSPACE VEOS QEMU Coupling:
Yocto 鏡像製作與雙模式配置實務
以 VEOS 2026-A 的 QEMU Coupling(dsQEMU)為基礎,說明如何在 Build Server 上把一份 Yocto core-image-minimal 做成可用的 POSIX-Based V-ECU:icount 與 idle-detect 兩種時間同步模式各自需要的編譯環境設定、鏡像產出後在模擬環境端的配置,以及每個步驟的手動操作指令與對應驗證方法。
dSPACE VEOS 的 QEMU Coupling(本文簡稱 dsQEMU)讓一顆完整的 Linux 系統以 POSIX-Based V-ECU 的形式加入 VEOS 的模擬時間軸,與 Plant FMU、Classic AUTOSAR vECU 及 Restbus 容器在同一個 OSA 內協同運作。對於採用 Yocto 作為量產 Linux 發行版基礎的專案而言,這代表 SoC 端的應用可以在硬體到位之前,就與 MCU 端的 ECU 軟體一起進入整合驗證。
本文承接同系列的 Buildroot 篇,改以 Yocto Project(poky/scarthgap) 為對象。兩者的目標一致,但達成路徑差異相當大:Yocto 的 core-image-minimal 使用 sysvinit 與 eudev、預設 /dev 為空目錄、並帶有數支對虛擬 ECU 有害的開機腳本。這些差異在原生 QEMU 上完全不會顯現,卻會在 VEOS 環境下造成無任何錯誤訊息的開機停滯。以下把整段工作拆為「Build Server 端的編譯環境配置」與「鏡像產出後的模擬環境配置」兩個階段,逐步標示操作與驗證。
本文適用環境
| 模擬主機 | Ubuntu 24.04 LTS + dSPACE VEOS 2026-A(Simulator Console 26.1)、veos-qemu 26.1(QEMU 9.2.3 基礎) |
| Build Server | Ubuntu 24.04 LTS、poky scarthgap(DISTRO_VERSION 5.0.19)、MACHINE = qemux86-64、image recipe core-image-minimal |
| Guest | x86_64、linux-yocto 6.6.142(icount 模式使用)、sysvinit、rootfs 為單一 raw ext4 映像 |
| idle-detect 專用 | Guest kernel 由 VEOS 強制替換為 veos-linux 6.6.119;模擬主機需具備 /dev/kvm |
文中路徑以 $HOME/poky、$HOME/meta-veos(Build Server)與 ~/dsqemu(模擬主機)表示;主機位址、帳號、IP 請替換為您自身環境的值。所有指令均為一般使用者權限,不需要 sudo。
1. 為什麼原始 core-image-minimal 不能直接使用
這個問題必須分兩種模式回答,因為兩者的失敗性質完全不同。以未經調整的原始鏡像實測:
| 項目 | icount 模式 | idle-detect 模式 |
|---|---|---|
| 能開機嗎 | ✅ 能,可開到 runlevel 5 | ❌ 完全不能——整場開機連一行 INIT: 都不會出現 |
| 能執行測試嗎 | ❌ 不能:沒有受測應用、eth0 沒有位址且會嘗試 DHCP | ❌ 不能(尚未進入可觀測的 userspace) |
| 問題性質 | 缺少測試載具與網路配置 | 結構性:開機路徑與鏡像的內建假設不符 |
1.1 idle-detect 模式的開機路徑差異
idle-detect 是 hypervisor 模式,VEOS 會強制指定自己的 guest kernel,並經由該 kernel 內建的 initramfs 進入您的 rootfs。實測到的關鍵事實是:它使用 chroot() 而非 switch_root,且僅建立了一個裝置節點。
Linux kernel 的 CONFIG_DEVTMPFS_MOUNT 自動掛載 /dev 只在「kernel 自行掛載 root 檔案系統」時觸發,走 initramfs + chroot 這條路徑不會發生。Yocto 在這裡的處境比 Buildroot 更嚴重:poky 的 USE_DEVFS 預設值為 1,語意是「讓 /dev 保持空目錄,因為 devtmpfs 會處理」。
1.2 為什麼「一行 INIT: 都沒有」
這是 Yocto 篇最重要的一個因果鏈,也是實務上最難自行診斷的症狀:
sysvinit 在讀取 /etc/inittab 之前,就先開啟 /dev/console 作為自己的標準輸出入。當該節點不存在時,init 及其後所有 rc 腳本的輸出全部落空——但 kernel 的 printk 仍然正常顯示,因為它走 console driver、不需要 /dev 節點。結果是一份「kernel 訊息完整、userspace 完全靜默」的 log,看起來像是 kernel 卡住,實際上 init 早已在執行。
關鍵推論:從 /etc/inittab 或 /etc/fstab 掛載 devtmpfs 都太晚。必須讓鏡像內本來就存在靜態的 /dev/console,這正是 §3 STEP 4 中 USE_DEVFS = "0" 這一行的意義。
1.3 Yocto 特有的三個障礙
越過 /dev 之後,還有三項在 Buildroot 上不存在、Yocto 專有的阻礙。三者的共同特徵是:都不會產生錯誤訊息,只會讓開機停在某一行不動。
| 障礙 | 實測症狀 | 成因與對策 |
|---|---|---|
| eudev(udevd) | 停在 udevd[71]: starting version 3.2.14;300 秒實時只推進 2.55 秒 guest 時間——是死結,不是慢 |
並非缺少 kernel 功能(SIGNALFD/TIMERFD/EPOLL/INOTIFY_USER/DEVTMPFS 在 veos-linux 皆為 y),而是裝置列舉流程與 veos-clock 推進協定的互動問題。對策:VIRTUAL-RUNTIME_dev_manager = "",改用純 devtmpfs |
| 熵源缺失 | Initializing random number generator... 永不繼續;移除該腳本後改停在 Waiting for kernel randomness to be initialised...(dropbear) |
veos-linux 沒有 CONFIG_RANDOM_TRUST_CPU,veos-qemu 預設也不提供 rng 裝置;決定性模擬環境沒有中斷抖動,熵池永遠填不滿。在 kernel 命令列加 random.trust_cpu=on 實測無效。對策:在 JSON 補上 virtio-rng 裝置(治本),並移除熵消費者 |
| bootlogd / hwclock | 通過前兩關後,停在 checkroot 之後完全沒有輸出 | bootlogd 會配置 pty 並接管 /dev/console 直到開機結束——而 console 正是 VEOS 擷取 log 的通道;hwclock 會讀 RTC 覆寫系統時鐘,而該時鐘就是 VEOS 模擬時鐘。對策:於 image 後處理移除兩者的 rc link |
1.4 一句話總結
core-image-minimal 是「能在 QEMU 裡開機的最小 Linux」;而 dsQEMU 需要的是「能在 VEOS 的時間軸上、透過虛擬 Ethernet 與其他模擬參與者交換資料、且不與模擬時鐘與 console 通道衝突的 V-ECU」。本文其餘篇幅就是在填補這段差距。
2. 兩種同步模式如何決定配置策略
在動手改任何設定之前,必須先理解兩種模式對鏡像的支配關係,否則很容易把「該改 JSON 的事」改進鏡像裡,付出不必要的重建成本。
| 面向 | icount(CPU 模擬) | idle-detect(Hypervisor) |
|---|---|---|
| Guest kernel | 您自己編譯的 linux-yocto 6.6.142 |
VEOS 的 veos-linux 6.6.119,由 VEOS 以 -kernel 指定,您的 bzImage 不會被使用 |
| KVM | 不需要 | 必須具備 /dev/kvm |
| 時間同步程度 | 部分同步(按指令數截斷) | 完全同步(偵測 idle 才推進時間) |
| rootfs 的角色 | 與自家 kernel 搭配,行為與原生 QEMU 一致 | rootfs 必須能被「別人的 kernel」以 chroot 方式帶起來——這是所有額外配置的來源 |
Guest /lib/modules |
可用(版本相符) | 不可用(為 6.6.142 編譯,kernel 為 6.6.119)。非致命,virtio 驅動皆為 built-in |
| init 系統選擇 | 不受限 | 建議維持 sysvinit:veos-linux 沒有 CONFIG_MEMCG,systemd 的 memory cgroup controller 不可用 |
| 典型加速比 | 約 0.95–0.98 | 約 1.000(多節點時可達 lockstep) |
單一鏡像同時支援兩種模式是可行且建議的做法。本文的 Build Server 配置對 icount 完全無害(多出來的靜態 /dev 節點與 devtmpfs 掛載不影響自家 kernel),因此不需要維護兩份 rootfs——差異全部集中在兩份 JSON 配置檔。
2.1 這五件事不要改鏡像——改 JSON 就好
下列項目經常被誤認為「鏡像要改」,實際上都屬於模擬環境端的配置:
| 情況 | 在 JSON 的處理方式 |
|---|---|
Yocto qemuboot 建議 -smp 4 | 寫 -smp 1。idle-detect 下 VEOS 會強制為 1;icount 下維持 1 可獲得較佳重現性 |
| 網卡型號預設為 e1000 | 寫 model=virtio-net-pci。veos-linux kernel 沒有 e1000 驅動,用錯型號時 guest 內看不到網卡 |
| idle-detect 下 console 全黑 | 加 -serial stdio。VEOS 在該模式追加 -nodefaults,取消了預設 serial 裝置 |
| 熵源不足導致開機停滯 | 加 -object rng-random,... + -device virtio-rng-pci。veos-linux 具備 CONFIG_HW_RANDOM_VIRTIO=y |
| 需要臨時切換 IP 或啟用 gdbserver | 以 kernel 命令列參數傳遞(例如 veos.gdb=1),由 init 腳本讀取 /proc/cmdline。改 JSON 即可,不需重建鏡像 |
3. Build Server 端:編譯環境配置
本節目標產物為兩個檔案:tmp/deploy/images/qemux86-64/bzImage-qemux86-64.bin 與 tmp/deploy/images/qemux86-64/core-image-minimal-qemux86-64.rootfs.ext4。所有變更收斂在一個獨立 layer(meta-veos)與 local.conf 的一個設定區塊,不修改 poky 樹內任何檔案,以確保上游可隨時更新。以下每個步驟都分為操作與驗證兩部分。
取得 Yocto 原始碼、建立基準線並備份組態
在加入任何客製內容之前,先把 poky 取得到一個已知版本、確認未修改的狀態能完成一次建置,並保留 local.conf 與 bblayers.conf 的原始版本。這一步讓後續每一項變更都可回溯、可還原,也是日後判斷「問題出在我方客製還是上游」的基準。
(a) 建置主機的一次性前置需求
Yocto 對建置主機有明確的套件需求。以下為 Ubuntu 24.04 LTS 的清單,這是整份流程中唯一需要 sudo 的動作,且只需執行一次。
三項常見的環境陷阱:① 不可以 root 身分建置,bitbake 會直接拒絕;② 建置目錄不要放在 NFS/SMB 等網路磁碟或大小寫不敏感的檔案系統上,會出現難以診斷的失敗;③ 若主機透過 Proxy 連外,需另行設定 git 與 bitbake 的 Proxy,否則 do_fetch 會逾時。
(b) 取得 poky 原始碼並固定版本
poky 是 Yocto Project 的參考發行版,內含 bitbake、meta、meta-poky 與 meta-yocto-bsp。本文使用 scarthgap 分支(Yocto 5.0 LTS)。
請記錄此處的版本代號(本文為 scarthgap)——STEP 2 的 LAYERSERIES_COMPAT_veos 必須與它一致,否則 bitbake 會拒絕解析 meta-veos。日後升級 poky 時,這兩處要一併更新。
(c) 初始化建置環境
oe-init-build-env 會建立 build/ 並產生預設的 local.conf 與 bblayers.conf,同時把 bitbake 加入 PATH。
(d) 設定 MACHINE 與建置資源
預設的 local.conf 已將 MACHINE 設為 qemux86-64,正是本文所需;平行度與快取目錄則建議依主機資源明確指定。
(e) 建立基準線:先建一次未客製的鏡像
這一次建置不加入任何 VEOS 客製。目的是確認工具鏈、網路與主機資源都正常——若此時就失敗,問題與本文後續配置無關。首次完整建置在 16 核心機器上約需 1–2 小時。
此時可順手記錄一項對照數據:以 debugfs -R 'ls -l /dev' <rootfs.ext4> 檢視基準鏡像的 /dev,應該只有 . 與 ..(見 §1.1)。這是 USE_DEVFS 預設值造成的結果,也是 STEP 4 第一行設定要解決的問題——先看過「改之前」的樣子,後續的驗證才有比較基準。
(f) 備份組態
在加入任何客製之前保留原始組態,使整個變更集可回溯、可還原。
建立 meta-veos layer 骨架
所有 VEOS 專用內容集中於一個獨立 layer,與 poky 樹完全隔離。這是本配置能長期維護的基礎。
conf/layer.conf 的內容:
LAYERSERIES_COMPAT_veos 的值必須與 poky 版本代號一致,否則 bitbake 會直接拒絕解析此 layer。升級 poky 時務必同步更新此行。
註冊 layer
將 meta-veos 加入 bblayers.conf。
local.conf:七個關鍵賦值
這個區塊是整份配置中影響最大的部分。每一行都對應一個實測到的具體失敗,並非預防性寫法。
| 設定 | 理由 |
|---|---|
USE_DEVFS = "0" |
最關鍵的一項。改用 makedevs 依 IMAGE_DEVICE_TABLES(預設 meta/files/device_table-minimal.txt)產生靜態節點,其中包含 /dev/console(5:1) 與 /dev/null(1:3)。這是讓 sysvinit 能寫出 console 輸出的前提(見 §1.2) |
VIRTUAL-RUNTIME_dev_manager = "" |
移除 eudev,改用純 devtmpfs。V-ECU 的虛擬硬體組成固定,不需要動態裝置管理;此配置與已驗證可行的 Buildroot 組態一致。副作用:套件數自 131 降至 78 |
EXTRA_IMAGE_FEATURES:append = " tools-debug" |
帶入 gdb/strace 等除錯工具。刻意不加 dbg-pkgs:實測會使 rootfs 自 40 MB 暴增至 1.27 GB,且遠端 GDB 所需的符號應置於 GDB host 的 sysroot 而非 target |
IMAGE_INSTALL:append |
受測應用與診斷工具。除 veos-sut 為自建 recipe 外,其餘六項 poky 本身即具備,不需要額外 layer |
IMAGE_ROOTFS_EXTRA_SPACE = "131072" |
額外 128 MB(單位為 KB)。最終 rootfs 約 242 MB |
IMAGE_FSTYPES = "ext4 tar.bz2" |
ext4 為 dsQEMU 使用的磁碟映像;保留 tar.bz2 便於在不使用 debugfs 或 loop mount 的情況下檢視內容 |
SERIAL_CONSOLES = "115200;ttyS0" |
原值含 ttyS1。VEOS 會加上 -nographic,guest 僅有一個 serial port,ttyS1 上的 getty 會不斷 respawn 直到被停用(INIT: Id "S1" respawning too fast),純粹浪費模擬指令 |
受測應用 recipe:veos-sut_1.0.bb
沒有受測應用,dsQEMU 就只是一台會開機的虛擬機。這支 recipe 負責編譯應用、安裝設定檔,並註冊為 sysvinit 服務。
recipes-veos/veos-sut/veos-sut_1.0.bb對應的 files/veos-sut.conf(節點參數,與位址規劃一致):
files/veos-sut-init 為 LSB 格式的 sysvinit 腳本,設計上有三個要點:
- 輸出導向
/dev/console,且不使用--background——後者會把輸出丟進/dev/null,導致應用在執行卻看不到任何輸出。 - 先確保
sysfs已掛載,這是 VEOS pre-start 初始化機制的前提。 - 可選功能以 kernel 命令列開關(例如
veos.gdb=1啟用 gdbserver),使測試情境切換不需重建鏡像。
修改 veos-sut.c 之後必須執行 bitbake -c cleansstate veos-sut。否則 sstate 快取會沿用舊的二進位檔並回報建置成功——這是一個不會產生任何錯誤訊息的陷阱,實測曾導致以兩個不同版本的應用進行比較。
五個 recipes-core 覆寫
這五個檔案處理網路位址、/dev、開機可觀測性,以及移除對 V-ECU 有害的 init 腳本。
(a) 靜態 IP — init-ifupdown_%.bbappend
VEOS 的 Ethernet cluster 內沒有 DHCP server,而 core-image-minimal 預設會以 busybox-udhcpc 嘗試 DHCP 並等到逾時。在 icount 模式下,這段等待是實際消耗的實時成本。
(b) fstab 加入 devtmpfs — base-files_%.bbappend
由 rcS 的 S03mountall.sh 掛載。此項單獨並不足夠——sysvinit 開啟 /dev/console 的時機比它更早,因此仍需 USE_DEVFS = "0" 作為主要修法;本項的作用是讓執行期的 /dev 是真正的 devtmpfs,而非靜態快照。
(c) 更早掛載 devtmpfs — sysvinit-inittab_%.bbappend
(d) 開機可觀測性 — sysvinit_%.bbappend
在 veos-linux kernel 下,guest console 是唯一的診斷通道:沒有 shell、網路啟動前沒有 SSH、也無法附加到停滯的開機流程。VERBOSE=no(poky 預設)時,一支阻塞的腳本完全不留痕跡,log 的最後一行會屬於前一支腳本,使診斷指向錯誤的位置。
/etc/default/rcS 由 sysvinit 提供,不是 initscripts。寫成 initscripts_%.bbappend 會在建置時失敗(sed: can't read .../etc/default/rcS)。查證方式:find $HOME/poky/meta -name 'rcS*' -path '*default*'。
(e) 移除三支 init 腳本 — core-image-minimal.bbappend
三支腳本來自三個不同套件(sysvinit、initscripts、busybox),在 image 後處理一次移除比撰寫三個 bbappend 簡潔。各自的問題已列於 §1.3。
此段必須寫在 recipe 內,不能寫進 local.conf。local.conf 由 bitbake 的 ConfHandler 解析,只接受賦值,不能定義 shell function,寫錯會直接造成解析錯誤。
執行建置
由於 STEP 1(e) 已完成一次基準線建置,此處多數產物可自 sstate 快取重用,通常只需數分鐘至十餘分鐘;若跳過基準線而直接建置,則與首次建置同樣需要約 1–2 小時。
鏡像內容驗證(不需開機)
這是整份流程中投資報酬率最高的一個步驟。以 debugfs 在進入模擬環境之前確認鏡像內容,可將「配置沒進鏡像」與「模擬環境配置錯誤」兩類問題徹底分離。
4. 鏡像產出後:模擬環境端的配置
本節以 icount 模式為主軸——它不需要 KVM,是導入時的第一階段目標,也是日常回歸測試的主要模式。idle-detect 的差異部分另於 §4.6 說明。
在非互動式 SSH 工作階段中,veos-env.sh 不會生效。請一律使用絕對路徑,或於腳本開頭設定:V=/opt/dspace/veos2026a/bin/veos。本節指令均採此寫法。
部署鏡像並保留乾淨母版
guest 會以 rw 掛載 rootfs,每執行一次就會被寫入。因此必須保留一份 .golden 母版,並在每輪測試前還原,否則測試結果不可重現。
撰寫 icount 模式的 JSON 配置
dsQEMU 的 V-ECU 由一份 JSON 描述,經 veos model import 轉為 OSA 內的 VPU。以下為完整可用的配置。
configs/yocto-x86_64-icount.json| 欄位 | 說明 |
|---|---|
StepSize | 同步時間步(秒)。應與 vECU 的 base step size 及 veos sim config -e 三者一致,否則會出現封包遺失或額外抖動 |
ClusterName | 宣告相同名稱的多份 JSON,veos model import 會自動建立 cluster、channel 並完成接線,不需手動執行 model add 或 model connect |
MacAddress | 預設值為全零,多節點時必然衝突。每個節點都應指定唯一位址 |
Resources | 僅接受絕對路徑。列出的檔案會於匯入時嵌入 OSA,並以 ${Resource:<basename>} 引用 |
console=ttyS0,115200 | VEOS 會加上 -nographic;保留 tty1 沒有意義且可能造成 getty 阻塞 |
RedirectStdout/Stderr | both 表示同時寫入 VEOS log 與檔案,產生 <Name>.qemu.stdout.log,即後續讀取 guest console 的來源 |
清場
每一輪測試都應自相同的初始狀態開始。這一步能避免大量無法重現的疑難排解。
每一個 veos model 指令都必須附加 < /dev/null。Model Console 會讀取標準輸入以等待修改指令,在非互動環境下會一直阻塞至連線逾時——而且不會顯示任何提示。
匯入產生 OSA 並確認拓撲
將 JSON 轉為 OSA。若需要多節點聯測,重複匯入即可——相同 ClusterName 會自動接線。
OSA 會在匯入時把 rootfs 內嵌進去。重新部署鏡像之後若沒有重建 OSA,執行的仍是舊 guest,而且不會有任何警告。凡是重新部署鏡像,就必須重新執行本步驟。
載入、執行與觀察
sim load 需要解開內嵌的 rootfs,對於 242 MB 的映像通常需要數十秒,屬正常現象。
收工
釋放授權席次並還原鏡像,讓環境回到可重複的初始狀態。
未執行 sim down 時,授權席次會持續被占用。下一輪載入會出現 Error 212 / user maximum ... reached——這是席次未釋放,並非授權伺服器故障。
4.6 idle-detect 模式的配置差異
模擬環境端的流程完全相同,差異僅在 JSON。核心原則是:凡由 VEOS 管控的參數一律不要自行指定。
| 參數 | 在 idle-detect 下的處理 |
|---|---|
-kernel/-cpu/-smp/-enable-kvm/-rtc/-veos | 一律不可自行指定。VEOS 會自行加入;自訂會被拒絕。bzImage 也不需要列入 Resources |
-serial stdio | 必須自行加入。VEOS 在此模式追加 -nodefaults,取消了預設 serial 裝置;缺少此項時 console 完全空白 |
| virtio-rng | 建議加入,用以解決 §1.3 的熵源問題 |
| kernel 命令列 | VEOS 會自行追加 hpet=disable tsc=reliable nohz=off veos.clock_tick_ns=<StepSize>,不需重複設定 |
configs/yocto-x86_64-idle-detect.json(差異段)關於 rng-random 的取捨:它提供的是主機的隨機性,嚴格而言會使每次執行無法逐位元重現。若測試需要位元級可重現性,可改用 rng-builtin(QEMU 內建 PRNG),或維持「移除所有熵消費者」的做法(此時 dropbear 亦須移除)。
5. 驗證判準
本專案的判準遵循一項原則:判準必須在量測之前訂定,且必須是可由輸出直接判讀的具體條件,而非主觀印象。
5.1 icount 模式
| # | 判準 | 怎麼看 |
|---|---|---|
| 1 | rootfs 正確掛載 | console 出現 EXT4-fs (vda): mounted filesystem |
| 2 | userspace 確實啟動 | 出現 INIT: version 3.04 booting 與 Entering runlevel: 5。只有 kernel 訊息而無 INIT 行,即為 §1.2 的 /dev/console 問題 |
| 3 | 受測應用啟動 | 出現 veos-sut: start ... |
| 4 | 應用持續發送 | tx 隨 t= 單調遞增,且比例符合設定週期(10 ms → 每秒 100 筆) |
| 5 | 雙向通訊成立(多節點時) | rx 追平 tx,允許因兩節點開機時間差造成的固定落差 |
| 6 | 時間同步品質 | 加速比(SimulationTime / ElapsedTime)≥ 0.9 |
5.2 idle-detect 模式:額外的判準
5.3 沒有 KVM 也能先驗證 idle-detect 相容性
這是一個實務價值很高的技巧。idle-detect 對 rootfs 的唯一影響,是 VEOS 將 guest kernel 換成 veos-linux 並改由 initramfs 進入;而 icount 模式允許指定任意 kernel。
因此,只要在 icount 模式下以 veos-linux kernel 開機自家 rootfs,測到的正是 idle-detect 的鏡像條件。這能在尚未具備 KVM 的環境中,先把「鏡像相容性」與「主機能力」兩件事分離,避免把主機設定問題誤判為鏡像問題。
6. 失敗模式與判讀
Yocto 在 VEOS 環境下的失敗,絕大多數不會以錯誤訊息呈現,而是表現為「停在某一行不動」或「輸出憑空消失」。以下對照表可將症狀直接對應到成因。
| 觀察到的現象 | 成因與處理 |
|---|---|
kernel 訊息完整,但一行 INIT: 都沒有 |
鏡像內 /dev/console 不存在。檢查 USE_DEVFS 是否為 "0",並以 STEP 8 的 ③ 直接驗證鏡像 |
停在 udevd: starting version ... |
VIRTUAL-RUNTIME_dev_manager 未清空。判斷是「慢」還是「死結」的方法見下方 |
停在 Initializing random number generator... 或 Waiting for kernel randomness... |
熵源問題。於 JSON 補上 virtio-rng 裝置(治本),或確認 S38urandom 已被移除 |
| checkroot 之後完全沒有輸出 | bootlogd 接管了 console。確認 image bbappend 的移除動作已生效(STEP 8 的 ④) |
INIT: Id "S1" respawning too fast: disabled for 5 minutes |
SERIAL_CONSOLES 仍包含 ttyS1。不致命,但會白白消耗模擬指令 |
應用回報 tx 持續增加,但對端 rx 為 0 |
依序檢查:兩份 JSON 的 ClusterName 是否一致;MacAddress 是否重複;網卡型號是否為 virtio-net-pci;veos-sut.conf 的 PEER_IP 是否指向對端實際位址 |
| 明明改了設定,行為卻沒變 | 三個常見原因:① 修改 veos-sut.c 後未執行 cleansstate;② 重新部署鏡像後未重建 OSA;③ 未自 .golden 還原 rootfs。三者都不會產生錯誤訊息 |
6.1 如何區分「慢」與「死結」
在 icount 模式下,guest 執行速度本來就比實時慢,因此「停住」與「很慢」在觀感上難以區分。可靠的判斷依據是模擬時間的推進速率,而非牆鐘時間:
7. 回歸測試與工程化建議
組態即程式碼
layer、recipe、bbappend、JSON 與受測應用原始碼全部納入版本控管,並保留 local.conf/bblayers.conf 的原始備份。任何一項客製都應能說明它對應哪一個具體失敗。
先驗鏡像,再進模擬
以 debugfs 在開機前確認鏡像內容(STEP 8)。這能把「配置沒進鏡像」與「模擬環境配置錯誤」兩類問題徹底分離,省下大量診斷時間。
用 JSON 換行為
把 gdbserver 開關、對端位址、應用選項做成讀取 kernel 命令列的參數。切換測試情境只需改 JSON,不需重建鏡像——單次迭代由數十分鐘降到數秒。
每次變更鏡像設定或 JSON 之後,建議至少執行以下三項回歸:
-
配置檔驗證以原廠 schema 檢查所有 JSON,並加上專案自訂規則(名稱不含空白、網卡型號、MAC 非預設值、idle-detect 未自訂受管參數)。
-
雙節點 icount 聯測Yocto 與另一個 guest 掛入同一 Ethernet cluster,確認雙向通訊與封包計數關係成立——這一項同時涵蓋開機、應用、網路與拓撲四個面向。
-
rootfs × veos-linux kernel 相容性探測即 §5.3 的做法。它讓「鏡像是否具備 idle-detect 相容性」成為一項可在 CI 中日常執行的檢查,而非只能在具備 KVM 的機器上驗證。
結語
把 Yocto 鏡像帶進 VEOS QEMU Coupling,工作量並不在於「改很多設定」,而在於理解每個設定對應哪一個具體失敗。本文的配置清單並不長——local.conf 的七行、一個獨立 layer、六份 recipe 與 bbappend、兩份 JSON——但每一項都源自一個實測到的症狀。
與 Buildroot 相比,Yocto 的差異集中在發行版預設值的假設:USE_DEVFS 假設 devtmpfs 會自動掛載、eudev 假設可以自由地與 kernel 往返協商、bootlogd 假設 console 可以被獨占。這些假設在一般硬體或原生 QEMU 上都成立,在 VEOS 的模擬時間軸上則不然。而它們失效時不會拋出錯誤,只會安靜地停下來。
這也是為什麼本文堅持每個步驟都附上驗證方法:在虛擬 ECU 的整合環境裡,「沒有報錯」從來不等於「配置正確」。建立一套可重複執行、判準事前訂好的驗證流程,是讓 SIL 測試結果可信的前提。
需要導入協助?
捷策動能提供 dSPACE VEOS/SystemDesk 虛擬驗證平台的導入規劃、環境建置、鏡像客製與 SIL 測試流程設計服務,涵蓋 Yocto/Buildroot 客製 Linux、Classic AUTOSAR vECU、Restbus 模擬與 CI 整合。歡迎與我們的技術團隊討論您的專案需求。
本文技術內容基於 dSPACE VEOS 2026-A 實機環境驗證,所引用的行為與數值均為實測結果。相關原廠規範請參閱 dSPACE VEOS Manual「Basics on VEOS QEMU Coupling」與「How to Debug a POSIX-Based V-ECU Remotely with GDB」等章節;Yocto 相關設定請對照 Yocto Project Reference Manual 之 USE_DEVFS、VIRTUAL-RUNTIME_dev_manager、IMAGE_FSTYPES 等變數說明。文中路徑、位址與名稱請依實際環境調整。