ZYNQ DDR读写实验 与 简单的双核共享内存通信(LINUX + BARE METAL)
时间:2025-11-09 21:16:46
手机看文章
扫描二维码
随时随地手机看文章
裸机下,读写DDR
测试代码如下:
void WRITE_DDR(u8 ddr_value){ xil_printf("\r\nwrite data\r\n"); u32 addr=TEST_ADDR; u32 i; for(i=0;i<10;i++) { Xil_Out8(addr++,ddr_value); xil_printf("ddr_value=0x%X,",ddr_value); } xil_printf("\r\n");} void READ_DDR(void){ xil_printf("\r\nraed data\r\n"); u32 addr=TEST_ADDR; u32 i; u8 ddr_value; for(i=0;i<10;i++) { ddr_value=Xil_In8(addr++); xil_printf("ddr_value=0x%X,",ddr_value); } xil_printf("\r\n");} void soft_delay(u32 count){ for(;count>0;count--);} int main(){ print("Hello World\n\r"); Xil_SetTlbAttributes(TEST_ADDR,0x14de2); //关闭cache READ_DDR(); u8 value=0x0; while(1) { READ_DDR(); WRITE_DDR(value++); READ_DDR(); soft_delay(0xfffffff); } return 0;}
LINUX下,读写DDR
1.涉及到一个工具:devmem。其用法如下:
root@zedboard:~# devmemBusyBox v1.24.1 (2019-11-28 16:33:01 CST) multi-call binary. Usage: devmem ADDRESS [WIDTH [VALUE]] Read/write from physical address ADDRESS Address to act upon WIDTH Width (8/16/...) VALUE Data to be written
实验效果如下:
root@zedboard:~# devmem 0x10000000 80xD0root@zedboard:~# devmem 0x10000000 8 0x63root@zedboard:~# devmem 0x10000000 80x63
2.LINUX应用程序调用函数
/* * ddr read linux application interface */ /*****************************************************************************/ __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0) /*****************************************************************************/ /*****************************************************************************/ /*** @brief 从实际物理地址读取数据。* @details 通过 mmap 映射关系,找到对应的实际物理地址对应的虚拟地址,然后读取数据。* 读取长度,每次最低4字节。* @param[in] readAddr, unsigned long, 需要操作的物理地址。* @param[out] buf,unsigned char *, 读取数据的buf地址。* @param[in] bufLen,unsigned long , buf 参数的容量,4字节为单位,如 unsigned long buf[100],那么最大能接收100个4字节。* 用于避免因为buf容量不足,导致素组越界之类的软件崩溃问题。* @return len,unsigned long, 读取的数据长度,字节为单位。如果读取出错,则返回0,如果正确,则返回对应的长度。*/static int Devmem_Read(unsigned long readAddr, unsigned long* buf, unsigned long len){ int i = 0; int fd,ret; int offset_len = 0; void *map_base, *virt_addr; off_t addr = readAddr; unsigned long littleEndianLength = 0; if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); return 0; } /* Map one page */ //将内核空间映射到用户空间 map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr & ~MAP_MASK); if(map_base == (void *) -1) { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); close(fd); return 0; } for (i = 0; i < len; i++) { // 翻页处理 if(offset_len >= MAP_MASK) { offset_len = 0; if(munmap(map_base, MAP_SIZE) == -1) { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); close(fd); return 0; } map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr & ~MAP_MASK); if(map_base == (void *) -1) { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); close(fd); return 0; } } virt_addr = map_base + (addr & MAP_MASK); // 将内核空间映射到用户空间操作 buf[i] = *((unsigned long *) virt_addr); // 读取数据 addr += 4; offset_len += 4; } if(munmap(map_base, MAP_SIZE) == -1) { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); close(fd); return 0; } close(fd); return i;} /* * test sample */int main(void){ unsigned long len = 2; unsigned long readData[1024*1024]; //1MB unsigned long addr = TEST_ADDR; unsigned long i = 0; while(1) { printf("read data\n"); memset(readData, 0, len); Devmem_Read(addr, readData, len); // 读取数据 for (i = 0; i < len; i++) { printf("address = 0x%08x, data = 0x%08x\n", (addr + i * 4), readData[i]); } sleep(1); }}
简单的核间通信
按照《ZYNQ下LINUX+FREERTOS同时运行》这篇文章编译CPU0程序,生成BOOT.BIN文件。运行。
注意要禁止掉cache缓存!如下,0x1F00 0000 是被禁止cache的内存地址,要根据实际情况修改。
Xil_SetTlbAttributes(0x1F000000,0x14de2); //关闭cache
本实验实现了CPU1裸核向DDR写入数据,CPU0 LINUX应用程序读取出刚写入DDR的数据。
实验效果:
CPU1(裸机)效果:
write dataddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6, raed dataddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6, raed dataddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6,ddr_value=0xC6, write dataddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7, raed dataddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7, raed dataddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7,ddr_value=0xC7, write dataddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8, raed dataddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8, raed dataddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,ddr_value=0xC8,
CPU0(LINUX),DEVMEM工具效果:
root@zedboard:~# devmem 0x1F000000 80xC6root@zedboard:~# devmem 0x1F000000 80xC7root@zedboard:~# devmem 0x1F000000 80xC8root@zedboard:~# devmem 0x1F000000 80xC8root@zedboard:~# devmem 0x1F000000 80xC9
CPU0(LINUX),APP效果:
read dataaddress = 0x1f000000, data = 0xcecececeaddress = 0x1f000004, data = 0xcecececeread dataaddress = 0x1f000000, data = 0xcecececeaddress = 0x1f000004, data = 0xcecececeread dataaddress = 0x1f000000, data = 0xcfcfcfcfaddress = 0x1f000004, data = 0xcfcfcfcf
文章知识点与官方知识档案匹配,可进一步学习相关知识
https://blog.csdn.net/weixin_41922484/article/details/103700465





