中断修好之后,SD 控制器是第一个真正接上去的外设。这篇记三个坑,和一次里程碑。
坑一:驱动要访问 0x204
SDHCI 是标准 IP,QEMU 自带通用模型,映射大小是 SDHC_REGISTERS_MAP_SIZE = 0x100。
但 AT91 在这个标准之上加了私有寄存器,比如 SDMMC_MC1R 在 0x204。驱动一过去就挂:
Unhandled fault: external abort on non-linefetch (0x008) at 0xe0887204
外部总线错误,地址 0xe0887204——比映射区大了 0x104。
修法是加一块"胶水区",覆盖 0x100 到 0x3FF,优先级设低(memory_region_add_subregion_overlap 传 -1),这样它只兜住标准区之外的部分,不遮挡 SDHCI 自己那 0x100。
【08_01_寄存器映射】
坑二:抄错的 capareg
一开始照着 zynq 的配置抄了个 capareg=0x69ec0080,QEMU 直接报:
SDHCI: unknown CAPAB mask: 0x0000000068040000
这个能力寄存器里有些位是 QEMU 8.2 不认识的。删掉显式设置,用默认值就好了。
教训是:不同 SoC 的 SDHCI 能力位不一样,别照抄别家的参数。
坑三:卡容量必须是 2 的幂
我手上那张 wic 镜像 121 MB。直接挂上去,QEMU 拒绝启动。
QEMU 的 SD 卡模型要求容量是 2 的幂。扩到 128 MB 能用,但用户后来说要 1 GB,就扩到了 1073741824 字节。
$ qemu-img resize sd1g.img 1G
扩完之后原来那两个分区还在,p1 是 boot(20.8 MB),p2 是 rootfs(100.7 MB)。
启动到登录
【08_02_分区表】
把卡接上,直接指定 root:
qemu-system-arm -M sama7d65 -cpu cortex-a7 -m 512 \\ -kernel zImage -dtb sama7d65-sim-sd.dtb \\ -append "root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait console=ttyS0,115200" \\ -drive file=sd1g.img,format=raw,if=sd \\ -display none -monitor none \\ -chardev stdio,id=char0,signal=off -serial chardev:char0
日志一路走下来:
【08_03_启动到登录】
mmc0: SDHCI controller on e1208000.mmc [e1208000.mmc] using ADMA mmcblk0: mmc0:4567 QEMU! 1.00 GiB mmcblk0: p1 p2 EXT4-fs (mmcblk0p2): mounted filesystem ec2476ff-… r/w with ordered data mode Run /sbin/init as init process … sama7d65-curiosity-sd login:
注意 mmcblk0: mmc0:4567 QEMU! 1.00 GiB 这一行——SD 卡的产品名字面就是 QEMU!,这是模型上报的。
这一步的意义
之前 shell 能进,但用的是 initramfs,本质还是内存里跑。
这次不一样:rootfs 是那块真实的 wic 镜像里的 ext4 分区,systemd 一路起到多用户模式,给出登录提示符。
模型从"能启动"变成了"能跑真实发行版"。
我要赚赏金
