#include #include #include #include #include #include #include #include // BSP板级支持包所需全局变量 unsigned long UART_BASE = 0xbf000000; unsigned long CONFREG_TIMER_BASE = 0xbf20f100; unsigned long CONFREG_CLOCKS_PER_SEC = 50000000L; unsigned long CORE_CLOCKS_PER_SEC = 33000000L; // 加上 aligned(64) 是为了防止 DMA 突发传输时跨越缓存行或 AXI 非对齐边界 uint32_t src_array[64] __attribute__((aligned(64))); uint32_t dst_array[64] __attribute__((aligned(64))); int main(int argc, char** argv) { uint32_t data_len = 64; uint32_t byte_len = data_len * 4; // 虚拟地址转物理地址与无缓存地址 // 屏蔽掉高 3 位(& 0x1FFFFFFF)即可获得真实的物理地址 uint32_t phys_src_addr = ((uint32_t)src_array) & 0x1FFFFFFF; uint32_t phys_dst_addr = ((uint32_t)dst_array) & 0x1FFFFFFF; // 或上 0xA0000000 即可获得绕过 Cache 的无缓存(Uncached)指针 volatile uint32_t *uncached_src = (volatile uint32_t *)(phys_src_addr | 0xA0000000); volatile uint32_t *uncached_dst = (volatile uint32_t *)(phys_dst_addr | 0xA0000000); // CPU 必须通过无缓存指针写入 for (int i = 0; i < data_len; i++) { uncached_src[i] = i * i; // 填入 0~63 uncached_dst[i] = 0xDEADBEEF; // 目的数组填入垃圾值,方便验证是否真的被覆盖 } printf("src_array: %x\n", src_array); printf("dst_array: %x\n", dst_array); printf("phys_src_array: %x\n", phys_src_addr); printf("phys_dst_array: %x\n", phys_dst_addr); printf("uncached_src: %x\n", uncached_src); printf("uncached_dst: %x\n", uncached_dst); // 配置 DMA:DMA 只需要最纯粹的物理地址 dma_start_transfer(0, phys_src_addr, phys_dst_addr, byte_len); dma_wait_polling(0); printf("dma passed!\n"); // 校验数据:CPU 必须通过无缓存指针读取 int err = 0; for (int i = 0; i < data_len; i++) { uint32_t val = uncached_dst[i]; printf("%d: %d\n", i, val); if (val != i * i) { err++; } } if (err == 0) { printf("\nSuccess! Array to Array DMA transfer verified.\n"); } else { printf("\nFailed! Found %d errors.\n", err); } return 0; }