这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【EEPW-Let'sdesign】MicrochipSAMA7D65-V/7E

共1条 1/1 1 跳转至页

【EEPW-Let'sdesign】MicrochipSAMA7D65-V/7EW-07-2|自己写机器模型(下)

菜鸟
2026-11-11 22:54:17     打赏

上篇结束时,模型能进 shell 了。但接下来接 SD 卡,卡了两天。

现象:访问停了,CPU 却在睡觉

SD 控制器接上去,内核启动到一半不动了。抓 QEMU 的寄存器访问日志,最后几笔是这样的:

[glue] rd8 off=0x204
[glue] wr8 off=0x204 val=0x40
[glue] wr8 off=0x204 val=0x0

之后就什么都没有了——不是继续访问别的寄存器,是彻底没有访问。

再看 CPU 停在哪。用 monitor 读寄存器:

(qemu) info registers
R13=c0d01f78  R14=c098392c  R15=c0110468  PSR=60000093

拿 System.map 反查:

PC=0xc0110468 -> cpu_v7_do_idle + 0x8
LR=0xc098392c -> default_idle_call + 0x20

CPU 在 idle。 不是死循环,是在睡觉。

这就矛盾了:如果是等某个中断,中断应该还在来;如果是死循环,CPU 不该 idle。

用最笨的办法验一下

不猜了,直接在 shell 里敲:

~ # sleep 3

卡死。三秒永远不到。

定时器根本不工作。 之前所有测试都没碰到需要 sleep 的路径,所以一直没暴露。

追到 GIC 接线

内核里跟时间有关的中断只有一处来源:ARM 架构定时器。它的中断线要从 CPU 连到 GIC,代码是我写的,但显然接错了。

QEMU 的 GIC 输入数组不是按中断号排的:

07_04_GIC输入数组.png【07_04_GIC输入数组】

前面是 SPI,后面才是每个 CPU 的 PPI。所以 PPI 的输入线号是:

输入线 = (num_irq - 32) + INTID

num_irq 是 128,所以基址是 96。设备树里写的是 <1 13>、<1 14> 这种 PPI 号,换算成 INTID 是 29、30,输入线应该是 125 和 126。

我一开始接的是 29——那是 SPI 的索引,打不到 PPI 上。后来改成直接接 13,又撞上断言:

qemu-system-arm: ../hw/intc/arm_gic.c:406:
  gic_set_irq: Assertion `irq >= GIC_NR_SGIS' failed.

因为块内偏移 0 到 15 是 SGI 区,PPI 必须从 16 起。

改成 96 + 29 = 125 之后:

~ # sleep 3
~ # echo SLEEP_OK
SLEEP_OK

这个 bug 的影响面

它不止挡住 SD。

在此之前,模型里任何需要 sleep 的路径都是死路——只是之前的测试恰好都没碰到。串口 shell 能用,是因为它靠中断驱动,不走定时等待。

所以修完之后,不只是 SD 能往下走了,整个模型的时间语义才算成立。

07_05_排查路径.png【07_05_排查路径】

回头看,怎么才能更快找到

有两条经验。

第一,别只看"卡在哪",要看"卡的状态"。 寄存器访问停了,很容易判断成"死循环"或"崩了"。但 CPU 在 idle 这个事实,直接把"死循环"排除了,范围一下缩到"在等什么东西"。

第二,找一个最小可判定的实验。 sleep 3 这条命令,比读一万行驱动代码都快。它把"定时器是否工作"这个问题,变成了一个二值判断。





关键词: Microchip     SAMA7D65-V     shel    

共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]