我正在为 32 位模式下运行的 ARMv8 (Cortex-A53) 实现缓存维护功能。当我尝试使用虚拟地址 (VA) 刷新内存区域时出现问题。DCacheFlushByRange
看起来像这样
// some init.
// kDCacheL1 = 0; kDCacheL2 = 2;
while (alignedVirtAddr < endAddr)
{
// Flushing L1
asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r"(kDCacheL1) :); // select cache
isb();
asm volatile("mcr p15, 0, %0, c7, c14, 1" : : "r"(alignedVirtAddr) :); // clean & invalidate
dsb();
// Flushing L2
asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r"(kDCacheL2) :); // select cache
isb();
asm volatile("mcr p15, 0, %0, c7, c14, 1" : : "r"(alignedVirtAddr) :); // clean & invalidate
dsb();
alignedVirtAddr += lineSize;
}
DMA 用于验证功能。DMA 将一个缓冲区复制到另一个缓冲区。源缓冲区在 DMA 之前刷新,目标缓冲区在 DMA 完成后无效。缓冲区是 64 字节对齐的。测试
for (uint32_t i = 0; i < kBufSize; i++)
buf1[i] = 0;
for (uint32_t i = 0; i < kBufSize; i++)
buf0[i] = kRefValue;
DCacheFlushByRange(buf0, sizeof(buf0));
// run DMA
while (1) // wait DMA completion;
DCacheInvalidateByRange(buf1, sizeof(buf1));
compare(buf0, buf1);
在转储中,我可以看到它buf1
仍然只包含零。当缓存关闭时,结果是正确的,因此 DMA 本身可以正常工作。
另一点是当整个 D 缓存被设置/方式刷新/无效时结果是正确的。
// loops th/ way & set for L1 & L2
asm volatile("mcr p15, 0, %0, c7, c14, 2" : : "r"(setway) :)
所以很快通过设置/方式刷新/无效工作正常。使用 VA 闪烁/无效也是如此。可能是什么问题?
PS:,kBufSize=4096;
总缓冲区大小为4096 * sizeof(uint32_t) == 16KB