# qemu_lesson_server **Repository Path**: kjfb/qemu_lesson_server ## Basic Information - **Project Name**: qemu_lesson_server - **Description**: qemu_lesson_server - **Primary Language**: C - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-11 - **Last Updated**: 2026-08-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RK3562 QEMU 全系统模拟 使用 QEMU `virt` 通用 ARM64 平台模拟 RK3562 完整启动链(U-Boot → Kernel → rootfs),用于台架功能测试。 ## 前置条件 ### 1. 安装 QEMU ```bash sudo apt-get install qemu-system-arm qemu-utils ``` 验证: ```bash qemu-system-aarch64 --version ``` ### 2. 初始化本地 SDK QEMU 目录使用本地 `sdk/` 目录存放内核源码、工具链和 rootfs,脱离外部 SDK 路径依赖。 ```bash cd tools/qemu # 收集编译产物到 output/ (每次编译后执行) bash setup_sdk.sh # 首次初始化: 从外部 SDK 复制源码到 sdk/ (仅首次使用) bash setup_sdk.sh --init /work/rk3562 ``` `setup_sdk.sh` 会复制以下内容: **sdk/ 目录** — 源码与工具链(git 跟踪,构建用): | 目录 | 内容 | 大小 | |------|------|------| | `sdk/kernel/` | 内核源码 | ~1.9G | | `sdk/toolchain/` | Buildroot 交叉工具链 (gcc, gdb, sysroot) | ~746M | | `sdk/rootfs/` | 根文件系统原始文件 | ~29M | | `sdk/uboot/` | U-Boot 源码 | ~236M | **output/ 目录** — 编译产物(运行 QEMU 用,已加入 `.gitignore`): | 目录 | 内容 | |------|------| | `output/kernel/` | 内核 Image, vmlinux | | `output/rootfs/` | rootfs.cpio.gz, rootfs.squashfs | | `output/uboot/` | u-boot.bin | | `output/dtb/` | 设备树 DTB 文件 | > **注意**: `output/` 目录已加入 `.gitignore`,不会提交到版本控制。`sdk/` 中的源码由 git 跟踪,编译中间产物通过 `.gitignore` 规则排除。 ### 3. 编译 U-Boot (可选,模式 B/C 需要) ```bash # 使用 sdk/ 本地 U-Boot 源码编译 bash build_uboot.sh # 或仅配置 bash build_uboot.sh -c ``` ## 快速启动 ### 模式 A — 内核直接启动(最快,跳过 U-Boot) ```bash ./run_qemu.sh -m kernel ``` 启动参数: - `-kernel Image` — 直接加载内核 - `-initrd rootfs.cpio.gz` — 加载 initrd - `console=ttyAMA0` — PL011 串口输出 ### 模式 B — U-Boot 交互模式 ```bash ./run_qemu.sh -m uboot ``` U-Boot 启动后可交互输入命令,测试 env、bootcmd 等。 ### 模式 C — U-Boot + 虚拟磁盘 ```bash # 先创建磁盘镜像 ./make_disk.sh # 启动 ./run_qemu.sh -m disk ``` 磁盘镜像包含 GPT 分区表和各分区数据,模拟真实 SD/eMMC。 ## 高级用法 ### GDB 调试 ```bash # 终端 1: 启动 QEMU 并等待 GDB ./run_qemu.sh -m kernel -S /tmp/share -e "-dtb output/dtb/qemu-virt-all.dtb" -g # 终端 2: 使用 kdbg.sh 启动 GDB (自动检测 GDB, 加载内核脚本) bash Lession/kernel_driver/L07_kdbg/kdbg.sh # 或手动启动 GDB aarch64-buildroot-linux-gnu-gdb -iex "add-auto-load-safe-path sdk/kernel/scripts/gdb" output/kernel/vmlinux (gdb) target remote :1234 ``` 详细调试教程见 [L07_kdbg/README.md](Lession/kernel_driver/L07_kdbg/README.md),实战经验见 [L07_kdbg/EXPERIENCE.md](Lession/kernel_driver/L07_kdbg/EXPERIENCE.md)。 ### 9p 共享目录(主机↔虚拟机文件传输) ```bash ./run_qemu.sh -m kernel -S /tmp/share ``` 虚拟机内挂载: ```bash mkdir -p /mnt/host mount -t 9p -o trans=virtio,version=9p2000.L hostshare /mnt/host ``` ### 网络端口转发 模式 A 和 C 默认转发 SSH 端口:`hostfwd=tcp::5555-:22` ```bash # 从主机 SSH 到虚拟机 ssh root@localhost -p 5555 ``` ### 自定义内存/CPU ```bash ./run_qemu.sh -m kernel -M 2G -s 2 # 2GB 内存, 2 核 ``` ## 内核驱动教程 (Lession) ### 目录结构 ``` Lession/kernel_driver/ ├── L01_hello_world/ # L01: 最简内核模块 (module_init/exit) ├── L02_ioremap_gpio/ # L02: ioremap GPIO 寄存器操作 ├── L03_gpio_subsys/ # L03: GPIO 子系统 (gpiod_* API) ├── L04_gpio_test/ # L04: GPIO 驱动测试脚本 ├── L05_dt_led/ # L05: 设备树 LED 驱动 ├── L06_virtual_devices/ # L06: 虚拟设备驱动集合 │ ├── venv_eeprom.c # L06a: 虚拟 I2C EEPROM (nvmem) │ ├── i2c_eeprom/ # L06a: I2C EEPROM 驱动 (完整) │ ├── spi_nand/ # L06b: 虚拟 SPI NAND Flash (MTD) │ ├── spi_nor/ # L06c: 虚拟 SPI NOR Flash │ ├── emmc/ # L06d: 虚拟 eMMC 存储 │ ├── sd/ # L06e: 虚拟 SD 卡 │ ├── lcd/ # L06f: 虚拟 LCD Framebuffer (fbdev) │ ├── camera/ # L06g: 虚拟摄像头 V4L2 (video capture) │ ├── rtc/ # L06h: 虚拟 RTC 实时时钟 (rtc子系统) │ ├── hwmon/ # L06i: 虚拟硬件监控 (hwmon子系统) │ ├── pwm/ # L06j: 虚拟 PWM 控制器 (pwm子系统) │ ├── input/ # L06k: 虚拟输入设备 (input子系统) │ ├── net/ # L06l: 虚拟以太网网卡 (netdev子系统) │ ├── can/ # L06m: 虚拟 CAN 控制器 (CAN子系统) │ ├── adc/ # L06n: 虚拟 IIO ADC 模数转换器 (IIO子系统) │ └── watchdog/ # L06o: 虚拟看门狗定时器 (watchdog子系统) └── L07_kdbg/ # L07: 内核驱动 GDB 调试 ├── README.md # GDB 调试完整教程 ├── EXPERIENCE.md # 调试实战经验 └── kdbg.sh # 一键启动脚本 ``` ### 驱动列表 | 编号 | 驱动 | 子系统 | 设备节点 | DTB | 说明 | |------|------|--------|---------|-----|------| | L01 | hello | module | — | — | 最简内核模块 | | L02 | ioremap_gpio | char | `/dev/gpio_demo` | — | ioremap 寄存器操作 | | L03 | gpio_subsys | gpio | `/sys/class/gpio/` | — | GPIO 子系统 API | | L05 | dt_led | leds | `/sys/class/leds/` | `qemu-virt-led.dtb` | 设备树 LED | | L06a | venv_eeprom | nvmem | `/sys/bus/nvmem/` | — | 虚拟 EEPROM | | L06b | v_spi_nand | mtd | `/dev/mtdX` | `qemu-virt-spi-nand.dtb` | 虚拟 SPI NAND | | L06f | v_lcd | fbdev | `/dev/fbX` | `qemu-virt-lcd.dtb` | 虚拟 LCD 帧缓冲 | | L06g | v_camera | v4l2 | `/dev/videoX` | `qemu-virt-camera.dtb` | 虚拟摄像头 | | L06h | v_rtc | rtc | `/dev/rtcX` | `qemu-virt-rtc.dtb` | 虚拟 RTC 实时时钟 | | L06i | v_hwmon | hwmon | `/sys/class/hwmon/` | `qemu-virt-hwmon.dtb` | 虚拟硬件监控 (温度/电压/风扇) | | L06j | v_pwm | pwm | `/sys/class/pwm/` | `qemu-virt-pwm.dtb` | 虚拟 PWM 控制器 (4通道) | | L06k | v_input | input | `/dev/input/eventX` | `qemu-virt-input.dtb` | 虚拟输入设备 (键盘+鼠标) | | L06l | v_net | netdev | `/sys/class/net/ethX` | `qemu-virt-net.dtb` | 虚拟以太网网卡 (回环) | | L06m | v_can | can | `/sys/class/net/canX` | `qemu-virt-can.dtb` | 虚拟 CAN 控制器 (回环) | | L06n | v_adc | iio | `/sys/bus/iio/devices/` | `qemu-virt-adc.dtb` | 虚拟 ADC 模数转换器 (4通道) | | L06o | v_wdt | watchdog | `/dev/watchdogX` | `qemu-virt-wdt.dtb` | 虚拟看门狗定时器 (hrtimer) | ### 通用测试流程 #### 1. 编译驱动 ```bash # 设置工具链 (所有驱动共用, 使用 sdk/ 本地工具链) export PATH=$(pwd)/sdk/toolchain/bin:$PATH # 进入驱动目录编译 cd Lession/kernel_driver/L06_virtual_devices/lcd # 或 camera/spi_nand/... make make dtb # 生成包含驱动节点的 DTB ``` #### 2. 启动 QEMU ```bash cd tools/qemu # 通用模式: 9p 共享 + 自定义 DTB ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-lcd.dtb" # 也可以同时加载多个 DTB (将节点合并到一个 DTB) # 使用 make_dtb.sh 中的合并脚本 ``` #### 3. 传入驱动到 Guest ```bash # 主机端: 复制 .ko 和测试脚本 cp build/v_lcd.ko /tmp/share/ cp test_lcd.sh /tmp/share/ # Guest 内: 挂载 9p 共享 mkdir -p /mnt/host mount -t 9p -o trans=virtio,version=9p2000.L hostshare /mnt/host ``` #### 4. 加载 & 测试 ```bash # 加载模块 insmod /mnt/host/v_lcd.ko # 验证设备 dmesg | tail -5 cat /sys/class/graphics/fb0/name # 运行测试脚本 sh /mnt/host/test_lcd.sh # 卸载模块 rmmod v_lcd ``` ### L06f: 虚拟 LCD Framebuffer **子系统**: fbdev | **设备节点**: `/dev/fbX` | **DTB**: `qemu-virt-lcd.dtb` ```bash # 编译 & DTB cd L06_virtual_devices/lcd && make && make dtb # 启动 QEMU ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-lcd.dtb" # Guest 内测试 insmod /mnt/host/v_lcd.ko cat /sys/class/graphics/fb0/name # → vlcd fbset -fb /dev/fb0 # → 640x480, 32bpp echo colorbars > /sys/bus/platform/devices/v_lcd0/draw_pattern echo gradient > /sys/bus/platform/devices/v_lcd0/draw_pattern sh /mnt/host/test_lcd.sh ``` **知识点**: fbdev 子系统, DMA 一致内存, fb_ops, 伪彩色调色板, 自定义 ioctl, sysfs 属性 ### L06g: 虚拟摄像头 V4L2 **子系统**: v4l2 | **设备节点**: `/dev/videoX` | **DTB**: `qemu-virt-camera.dtb` ```bash # 编译 & DTB cd L06_virtual_devices/camera && make && make dtb # 启动 QEMU ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-camera.dtb" # Guest 内测试 insmod /mnt/host/v_camera.ko cat /sys/class/video4linux/video0/name # → vcam v4l2-ctl --device=/dev/video0 --all # 查询设备信息 v4l2-ctl --device=/dev/video0 --list-formats # 列出支持的格式 echo gradient > /sys/bus/platform/devices/v_camera0/pattern v4l2-ctl --device=/dev/video0 --stream-mmap --stream-count=1 --stream-to=/tmp/frame.yuyv sh /mnt/host/test_camera.sh ``` **知识点**: V4L2 子系统, videobuf2 框架, 格式协商, 流式采集, 内核线程帧生成, sysfs 属性 ### L06h: 虚拟 RTC 实时时钟 **子系统**: rtc | **设备节点**: `/dev/rtcX` | **DTB**: `qemu-virt-rtc.dtb` ```bash cd L06_virtual_devices/rtc && make && make dtb ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-rtc.dtb" # Guest 内 insmod /mnt/host/v_rtc.ko cat /sys/class/rtc/rtc0/name # → v_rtc cat /sys/class/rtc/rtc0/time # → 当前时间 cat /sys/class/rtc/rtc0/date # → 当前日期 hwclock --rtc=/dev/rtc0 --show # 读取 RTC 时间 sh /mnt/host/test_rtc.sh ``` **知识点**: RTC 子系统, rtc_class_ops, time64_t, hrtimer 闹钟, rtc_update_irq, sysfs 属性 ### L06i: 虚拟硬件监控 **子系统**: hwmon | **设备节点**: `/sys/class/hwmon/` | **DTB**: `qemu-virt-hwmon.dtb` ```bash cd L06_virtual_devices/hwmon && make && make dtb ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-hwmon.dtb" # Guest 内 insmod /mnt/host/v_hwmon.ko cat /sys/class/hwmon/hwmon0/temp1_input # → CPU 温度 (~45000 = 45°C) cat /sys/class/hwmon/hwmon0/fan1_input # → 风扇转速 (~2400 RPM) cat /sys/class/hwmon/hwmon0/in0_input # → 3.3V 电压 (~3300 mV) sensors # 如果 lm-sensors 可用 sh /mnt/host/test_hwmon.sh ``` **知识点**: HWMON 子系统, hwmon_channel_info, hwmon_ops, 传感器通道配置, jiffies 波动模拟 ### L06j: 虚拟 PWM 控制器 **子系统**: pwm | **设备节点**: `/sys/class/pwm/` | **DTB**: `qemu-virt-pwm.dtb` ```bash cd L06_virtual_devices/pwm && make && make dtb ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-pwm.dtb" # Guest 内 insmod /mnt/host/v_pwm.ko cat /sys/class/pwm/pwmchip0/npwm # → 4 (4个通道) echo 0 > /sys/class/pwm/pwmchip0/export # 导出通道 0 echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period # 1ms 周期 echo 500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle # 50% 占空比 echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable # 使能 sh /mnt/host/test_pwm.sh ``` **知识点**: PWM 子系统, pwm_ops, pwm_state, apply/get_state 回调, sysfs 通道控制 ### L06k: 虚拟输入设备 **子系统**: input | **设备节点**: `/dev/input/eventX` | **DTB**: `qemu-virt-input.dtb` ```bash cd L06_virtual_devices/input && make && make dtb ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-input.dtb" # Guest 内 insmod /mnt/host/v_input.ko cat /sys/class/input/input0/name # → v_input echo 30 > /sys/bus/platform/devices/v_input0/inject_key # 注入按键 A echo "10,5" > /sys/bus/platform/devices/v_input0/inject_mouse # 注入鼠标移动 echo "left" > /sys/bus/platform/devices/v_input0/click # 注入鼠标左键点击 evtest /dev/input/event0 # 如果 evtest 可用 sh /mnt/host/test_input.sh ``` **知识点**: Input 子系统, input_dev, set_bit/事件类型, input_event/input_sync, 事件注入 ### L06b: 虚拟 SPI NAND Flash **子系统**: mtd | **设备节点**: `/dev/mtdX` | **DTB**: `qemu-virt-spi-nand.dtb` ```bash cd L06_virtual_devices/spi_nand && make && make dtb ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-spi-nand.dtb" # Guest 内 insmod /mnt/host/v_spi_nand.ko cat /sys/class/mtd/mtd0/name # → vspinand flash_erase /dev/mtd0 0 1 # 擦除块 0 nandwrite /dev/mtd0 /tmp/test.bin # 写入 sh /mnt/host/test_spi_nand.sh ``` ### L06l: 虚拟以太网网卡 **子系统**: netdev | **设备节点**: `/sys/class/net/ethX` | **DTB**: `qemu-virt-net.dtb` ```bash cd L06_virtual_devices/net && make && make dtb ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-net.dtb" # Guest 内 insmod /mnt/host/v_net.ko ip link set eth1 up # 启动网卡 ip addr add 10.0.0.1/24 dev eth1 # 配置 IP ping 10.0.0.1 # 回环 ping 测试 cat /sys/bus/platform/devices/v_net0/link_status # → up cat /sys/bus/platform/devices/v_net0/pkt_count # → 收发计数 echo down > /sys/bus/platform/devices/v_net0/link_status # 模拟链路断开 sh /mnt/host/test_net.sh ``` **知识点**: 网络子系统, alloc_etherdev/register_netdev, net_device_ops, netif_rx 回环, 工作队列, MAC 地址管理, sysfs 属性 ### L06m: 虚拟 CAN 控制器 **子系统**: can | **设备节点**: `/sys/class/net/canX` | **DTB**: `qemu-virt-can.dtb` ```bash cd L06_virtual_devices/can && make && make dtb ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-can.dtb" # Guest 内 insmod /mnt/host/v_can.ko ip link set can0 type can bitrate 500000 loopback on # 设置比特率+回环 ip link set can0 up # 启动 CAN cansend can0 123#DEADBEEF # 发送标准帧 (需 can-utils) candump can0 & # 接收 CAN 帧 cat /sys/bus/platform/devices/v_can0/bus_state # → ERROR-ACTIVE cat /sys/bus/platform/devices/v_can0/loopback # → 1 sh /mnt/host/test_can.sh ``` **知识点**: CAN 子系统, alloc_candev/register_candev, net_device_ops, do_set_mode 回调, can_put_echo_skb/can_get_echo_skb 发送回环, bittiming_const 位时序, CAN_CTRLMODE_LOOPBACK, sysfs 属性 ### L06n: 虚拟 IIO ADC 模数转换器 **子系统**: iio | **设备节点**: `/sys/bus/iio/devices/` | **DTB**: `qemu-virt-adc.dtb` ```bash cd L06_virtual_devices/adc && make && make dtb ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-adc.dtb" # Guest 内 insmod /mnt/host/v_adc.ko cat /sys/bus/iio/devices/iio:device0/in_temp_raw # → CH0 温度原始值 cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw # → CH1 电压原始值 cat /sys/bus/iio/devices/iio:device0/in_voltage0_scale # → 缩放因子 cat /sys/bus/iio/devices/iio:device0/ch1_mv # → CH1 当前毫伏值 sh /mnt/host/test_adc.sh ``` **知识点**: IIO 子系统, devm_iio_device_alloc/register, iio_chan_spec 通道定义, iio_info 回调, IIO_CHAN_INFO_RAW/SCALE, jiffies 波动模拟, IIO_DEVICE_ATTR_RO 自定义属性 ### L06o: 虚拟看门狗定时器 **子系统**: watchdog | **设备节点**: `/dev/watchdogX` | **DTB**: `qemu-virt-wdt.dtb` ```bash cd L06_virtual_devices/watchdog && make && make dtb ./run_qemu.sh -m kernel -S /tmp/share \ -e "-dtb output/dtb/qemu-virt-wdt.dtb" # Guest 内 insmod /mnt/host/v_wdt.ko cat /sys/class/watchdog/watchdog0/identity # → v_wdt (需 CONFIG_WATCHDOG_SYSFS) cat /sys/class/watchdog/watchdog0/timeout # → 30 (秒) cat /dev/watchdog0 & # 打开设备 (自动启动) echo 'V' > /dev/watchdog0 # magic close 停止看门狗 cat /sys/devices/platform/v_wdt0/reset_count # → 看门狗触发次数 sh /mnt/host/test_wdt.sh ``` **知识点**: watchdog 子系统, devm_watchdog_register_device, watchdog_ops (start/stop/ping/set_timeout/get_timeleft), watchdog_info, hrtimer 高精度定时器, watchdog_init_timeout DT 解析, WDIOF_MAGICCLOSE ## 目录结构 ``` tools/qemu/ ├── run_qemu.sh # 主启动脚本 ├── make_disk.sh # 创建虚拟磁盘镜像 ├── build_qemu_kernel.sh # 编译 QEMU 内核 ├── build_uboot.sh # 编译 QEMU U-Boot ├── setup_sdk.sh # 从 SDK 复制构建产物到 sdk/ + output/ ├── qemu-virt-config-fragment.config # 内核 virt 驱动配置 fragment ├── README.md # 本文档 ├── sdk/ # 源码 + 工具链 (setup_sdk.sh 生成) │ ├── kernel/ # 内核源码 │ ├── toolchain/ # Buildroot 交叉工具链 │ ├── rootfs/ # 根文件系统原始文件 │ └── uboot/ # U-Boot 源码 ├── output/ # 编译产物 (运行 QEMU 用) │ ├── kernel/ # Image, vmlinux │ ├── rootfs/ # rootfs.cpio.gz, rootfs.squashfs │ ├── uboot/ # u-boot.bin │ └── dtb/ # 设备树 DTB 文件 └── Lession/ # 驱动教程 └── kernel_driver/ ├── L01_hello_world/ ├── L02_ioremap_gpio/ ├── L03_gpio_subsys/ ├── L04_gpio_test/ ├── L05_dt_led/ ├── L06_virtual_devices/ │ ├── lcd/ │ ├── camera/ │ ├── rtc/ │ ├── hwmon/ │ ├── pwm/ │ ├── input/ │ ├── net/ │ ├── can/ │ ├── adc/ │ ├── watchdog/ │ ├── spi_nand/ │ ├── spi_nor/ │ ├── emmc/ │ ├── sd/ │ └── i2c_eeprom/ └── L07_kdbg/ # GDB 调试教程 ├── README.md ├── EXPERIENCE.md └── kdbg.sh ``` ## QEMU 快捷键 | 快捷键 | 功能 | |--------|------| | `Ctrl+A, X` | 退出 QEMU | | `Ctrl+A, C` | 切换串口/monitor | ## 局限性 | 项目 | 说明 | |------|------| | **硬件外设** | QEMU virt ≠ RK3562,Rockchip 专用外设无法测试 | | **U-Boot** | 使用 `qemu_arm64_defconfig`,RK3562 特有逻辑无法测试 | | **SPI NAND** | QEMU 无法模拟 SFC 控制器,用虚拟 platform device 替代 | | **LCD 显示** | 虚拟帧缓冲不输出到 QEMU 显示窗口 (除非启用 virtio-gpu) | | **摄像头** | 虚拟摄像头生成测试图案,不采集真实视频 | | **可测试** | 通用 U-Boot 命令、env 操作、内核启动、rootfs 挂载、分区表、网络、驱动子系统 | ## 常见问题 ### Q: 启动后无输出? 检查串口设备名是否正确: - QEMU virt 使用 `ttyAMA0`(PL011) - RK3562 真实硬件使用 `ttyS2`(DW 8250) - 内核启动参数需加 `console=ttyAMA0` ### Q: 内核 panic - VFS: Unable to mount root fs? 1. 确认 rootfs 格式匹配: - `cpio.gz` → `root=/dev/ram0` - `squashfs` → 需要 virtio-blk 磁盘,`root=/dev/vda1 rootfstype=squashfs` 2. 确认内核编译了对应的文件系统驱动 ### Q: U-Boot 启动后无法识别磁盘? QEMU virt 的 U-Boot 使用 virtio 设备,命令: ```bash => virtio scan => virtio devices => part list virtio 0 ``` ### Q: 驱动 insmod 后找不到设备节点? 1. 确认使用了正确的 DTB(`-e "-dtb xxx.dtb"`) 2. 检查 DTB 中是否包含驱动的 compatible 节点:`dtc -I dtb -O dts xxx.dtb | grep compatible` 3. 检查内核日志:`dmesg | grep -i "probe\|error\|fail"` ### Q: 图形窗口无法打开 (gtk initialization failed)? 运行环境没有 GTK 显示服务,去掉 `-G` 标志即可: ```bash ./run_qemu.sh -m kernel -S /tmp/share -e "-dtb xxx.dtb" # 不加 -G ``` 驱动功能不受影响,只是没有可视化窗口。 ### Q: v4l2-ctl 不可用? 在 Buildroot 中启用 `v4l2-ctl`: ``` BR2_PACKAGE_V4L_UTILS=y ``` 或使用 `dd` 读取 `/dev/videoX` 作为替代。