From ca425d75c98e863af076b0df25aff719e12849c0 Mon Sep 17 00:00:00 2001 From: FallenSigh Date: Sun, 12 Apr 2026 22:28:38 +0800 Subject: [PATCH] test(dma): add C example to test CDMA IP --- sdk/software/examples/dma/Makefile | 11 +++ sdk/software/examples/dma/main.c | 104 +++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 sdk/software/examples/dma/Makefile create mode 100644 sdk/software/examples/dma/main.c diff --git a/sdk/software/examples/dma/Makefile b/sdk/software/examples/dma/Makefile new file mode 100644 index 0000000..62a06cd --- /dev/null +++ b/sdk/software/examples/dma/Makefile @@ -0,0 +1,11 @@ +TARGET = dma + +CFLAGS += -O3 -g + +C_SRCS := $(wildcard ./*.c ) + +OBJDIR = obj +COMMON_DIR = ../../bsp +GCC_DIR=../../../toolchains/loongson-gnu-toolchain-8.3-x86_64-loongarch32r-linux-gnusf-v2.0 +PICOLIBC_DIR=../../../toolchains/picolibc +include ../../bsp/common.mk diff --git a/sdk/software/examples/dma/main.c b/sdk/software/examples/dma/main.c new file mode 100644 index 0000000..9bc1f92 --- /dev/null +++ b/sdk/software/examples/dma/main.c @@ -0,0 +1,104 @@ +#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; + +#define FFT_BASE 0xbf400000 +#define FFT_IN_RE_BASE (FFT_BASE + 0x1000) +#define FFT_IN_IM_BASE (FFT_BASE + 0x2000) +#define FFT_OUT_RE_BASE (FFT_BASE + 0x3000) +#define FFT_OUT_IM_BASE (FFT_BASE + 0x4000) +#define FFT_CSR_REG (FFT_BASE + 0xF000) +#define FFT_CTRL_START (1 << 4) +#define FFT_STAT_DONE (1 << 1) +#define FFT_STAT_BUSY (1 << 0) +#define FFT_POINT_NUM 1024 + +#define DMA_BASE 0xbf300000 +#define DMA_CTRL (DMA_BASE + 0x0000) +#define DMA_LEN (DMA_BASE + 0x0004) +#define DMA_SRC_ADDR (DMA_BASE + 0x0008) +#define DMA_DST_ADDR (DMA_BASE + 0x000c) +#define DMA_STATUS (DMA_BASE + 0x0010) + +const float PI = 3.14159265358979323846; + +// 加上 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) +{ + unsigned int dma_status = RegRead(DMA_STATUS); + printf("dma_status init = %x\n", dma_status); + + 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 只需要最纯粹的物理地址 + RegWrite(DMA_SRC_ADDR, phys_src_addr); + RegWrite(DMA_DST_ADDR, phys_dst_addr); + RegWrite(DMA_LEN, byte_len); + + // burst_len = 15(16拍), burst_size = 2(4字节) + uint32_t burst_len = 15; + uint32_t burst_size = 2; + uint32_t ctrl_val = (burst_len << 6) | (burst_size << 3) | 0x01; + RegWrite(DMA_CTRL, ctrl_val); + + // 等待 DMA 完成 + while ((RegRead(DMA_STATUS) & 0x01) == 0) { + printf("polling...\n"); + } + + 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) { + err++; + } + } + + if (err == 0) { + printf("\nSuccess! Array to Array DMA transfer verified.\n"); + } else { + printf("\nFailed! Found %d errors.\n", err); + } + + return 0; +} \ No newline at end of file