【发布时间】:2021-03-13 14:53:44
【问题描述】:
我正在为树莓派编写一个操作系统。 我的自定义 sdhost 控制器 (emmc2) 的 sdcard 驱动程序有问题 树莓派 4(Cortex-A72、ARMv8-A、bcm2711 芯片组)。 不使用 sdma 一切正常。用sdma,读可以,但是写扇区后,sdcard上的数据有时会包含无效数据。
对于 sdma 数据传输,我使用具有设备类型内存属性 (nGnRnE) 的传输缓冲区。当我使用新的数据缓冲区进行 dma 写入传输时,sdcard 上的数据是正确的。但是当我在下次写入时重复使用相同的缓冲区时,sdcard 上的扇区会部分包含来自前一个缓冲区内容的数据。
也许这是一个缓存一致性问题。我已启用所有缓存(I 和 D)。 ARM手册里有讲SCU(snoop control unit),不知道有没有对SCU有过困扰。
我的问题是:
- 是否需要在 Cortex-A72 上启用 SCU?如何做到这一点?
- 使用 dma 访问设备时还需要注意哪些其他事项?
【问题讨论】:
-
SCU 只是为了保持内核之间的数据一致。它不适用于 DMA。 DMA 设备不访问 L1/L2 缓存,它们总是进行“内存到设备”传输。您必须确保在激活写入 DMA 命令之前刷新缓冲区,或者将驱动程序内存标记为不可缓存。
-
缓冲区不可缓存。页的内存类型是Device-nGnRnE(Device non-Gathering, non-Reordering, No Early write acknowledgement。相当于早期版本架构中的Strongly-ordered内存类型)。我转储了页面的 L2 转换表条目的值,它是 0x1279033。这个 L2 描述符的元素是: nG,non 全局位(第 11 位)为 0; S,可共享位(bit 10)为0; TEX[2:0](第 8-6 位)为 0; C(第 3 位)为 0; B(第 2 位)为 0。所以 TEX[2:0],C,B 为 000000,这意味着 Device-nGnRnE。 TEX 重映射被禁用(SCTLR.TRE 为 0)。
-
由于您对这个问题没有其他意见,我建议您尝试冲洗。表可能没有正确设置。很难让所有位都正确。我同意如果表格正确,则不需要冲洗。但是,同花顺会告诉您表格是否正确。
-
我刷新了缓存。没有成功。然后我用另一个 virt.addr 创建了第二个映射。和phys.addr。在 dma 缓冲区中,我从第二个 virt.addr 读回数据。并且数据是正确的。所以我认为数据到达了内存。结论是sdhci控制器没有从内存中读取所有数据,也许它有自己的缓存?对我来说似乎不太可能。有一点值得注意:一个错误的 512 字节扇区包含 3 个 32 字节的正确数据块(16 字节对齐),所有其他数据都是旧数据。 l2-cache 的 line-size 是 16 字节。也许这表明与 l2-cache 有关系。
标签: raspberry-pi arm osdev bare-metal armv8