2020.5.20 Xilinx FPGA Zynq DMA驱动

5 篇文章 0 订阅
5 篇文章 0 订阅

PL端参考本文:
http://www.fpgadeveloper.com/2014/08/using-the-axi-dma-in-vivado.html
https://blog.csdn.net/qq_20091945/article/details/70194026
github:
*使用 vivado2018.2 ,linaro15.4,设备树卡一半内存,设置一半留给操作系统,一半留给FPGA做共享内存,参考微博: https://blog.csdn.net/weixin_40604731/article/details/88751053
*本文为在linux操作系统下的DMA操作,裸机可直接调用API。如有错误之处还请不吝赐教!
1、PL端连接图(参考PL端参考文本)
在这里插入图片描述
2、DMA驱动
*本文DDR为1G,卡一本内存512MB,所以从物理基地址 0x20000000 开始,到0x40000000 为FPGA共享内存。

驱动程序,需要在vivado sdk中创建新的linux 应用,生成./elf,直接在linux系统中运行。

#define AXIDMA_MM2S_BASEADDR 0x20000000
#define AXIDMA_S2MM_BASEADDR 0x20001000
//AXI DMA Simple
#define MM2S_DMACR 0x00
#define MM2S_DMASR 0x04
#define MM2S_SA 0x18
#define MM2S_LENGTH 0x28
#define S2MM_DMACR 0x30
#define S2MM_DMASR 0x34
#define S2MM_DA 0x48
#define S2MM_LENGTH 0x58
//Reset AXI DMA MM2S 
void DMA_MM2S_Reset()
{
	int map_len = 0x60;
	int fd = open("/dev/mem", O_RDWR);

	unsigned char *dma_base_address;
	dma_base_address = (unsigned char *)mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)AXIDMA_MM2S_BASEADDR);
	if(dma_base_address == MAP_FAILED)
	{
		perror("DMA MM2S Reset Mapping memory for absolute memory access failed.\n");
		return;
	}

	REG_WRITE(dma_base_address, MM2S_DMACR,  0x04);
	printf("MM2S_DMACR = %x\n", REG_READ(dma_base_address, MM2S_DMACR));
	munmap((void *)dma_base_address, map_len);
	close(fd);	
}

//Reset AXI DMA S2MM
void DMA_S2MM_Reset()
{
	int map_len = 0x60;
	int fd = open("/dev/mem", O_RDWR);

	unsigned char *dma_base_address;
	dma_base_address = (unsigned char *)mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)AXIDMA_S2MM_BASEADDR);
	if(dma_base_address == MAP_FAILED)
	{
		perror("DMA Reset Mapping memory for absolute memory access failed.\n");
		return;
	}

	REG_WRITE(dma_base_address, S2MM_DMACR , 0x04);
	printf("S2MM_DMACR = %x\n", REG_READ(dma_base_address, S2MM_DMACR));

	munmap((void *)dma_base_address, map_len);
	close(fd);
}


//Init AXI DMA MM2S (Simple Mode)
void DMA_MM2S_Init(unsigned int mm2s_sa_addr)
{
	int map_len = 0x60;
	int fd = open("/dev/mem", O_RDWR);

	unsigned char *dma_base_address;
	dma_base_address = (unsigned char *)mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)AXIDMA_MM2S_BASEADDR);
	if(dma_base_address == MAP_FAILED)
	{
		perror("DMA Reset Mapping memory for absolute memory access failed.\n");
		return;
	}

	REG_WRITE(dma_base_address, MM2S_DMACR,  0x5001);
	REG_WRITE(dma_base_address, MM2S_SA,  mm2s_sa_addr);
	

	printf("MM2S_DMACR = %x\n", REG_READ(dma_base_address, MM2S_DMACR));
	printf("MM2S_SA = %x\n", REG_READ(dma_base_address, MM2S_SA));

	munmap((void *)dma_base_address, map_len);
	close(fd);
}


//Init AXI DMA S2MM  (Simple Mode)
void DMA_S2MM_Init(unsigned int s2mm_da_addr)
{
	int map_len = 0x60;
	int fd = open("/dev/mem", O_RDWR);

	unsigned char *dma_base_address;
	dma_base_address = (unsigned char *)mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)AXIDMA_S2MM_BASEADDR);
	if(dma_base_address == MAP_FAILED)
	{
		perror("DMA Reset Mapping memory for absolute memory access failed.\n");
		return;
	}

	REG_WRITE(dma_base_address, S2MM_DMACR , 0x5001);

	REG_WRITE(dma_base_address, S2MM_DA , s2mm_da_addr);

	printf("S2MM_DMACR = %x\n", REG_READ(dma_base_address, S2MM_DMACR));

	printf("S2MM_DA = %x\n", REG_READ(dma_base_address, S2MM_DA));

	munmap((void *)dma_base_address, map_len);
	close(fd);
}

//Start AXI DMA MM2S (Simple Mode)
void DMA_MM2S_Start(unsigned int mm2s_len)
{
	int map_len = 0x60;
	int fd = open("/dev/mem", O_RDWR);

	unsigned char *dma_base_address;
	dma_base_address = (unsigned char *)mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)AXIDMA_MM2S_BASEADDR);
	if(dma_base_address == MAP_FAILED)
	{
		perror("DMA Reset Mapping memory for absolute memory access failed.\n");
		return;
	}

	REG_WRITE(dma_base_address, MM2S_LENGTH,  mm2s_len);

	printf("MM2S_LENGTH = %x\n", REG_READ(dma_base_address, MM2S_LENGTH));

	munmap((void *)dma_base_address, map_len);
	close(fd);
}

//Start AXI DMA S2MM (Simple Mode)
void DMA_S2MM_Start(unsigned int s2mm_len)
{
	int map_len = 0x60;
	int fd = open("/dev/mem", O_RDWR);

	unsigned char *dma_base_address;
	dma_base_address = (unsigned char *)mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)AXIDMA_S2MM_BASEADDR);
	if(dma_base_address == MAP_FAILED)
	{
		perror("DMA Reset Mapping memory for absolute memory access failed.\n");
		return;
	}

	REG_WRITE(dma_base_address, S2MM_LENGTH , s2mm_len);

	printf("S2MM_LENGTH = %x\n", REG_READ(dma_base_address, S2MM_LENGTH));

	munmap((void *)dma_base_address, map_len);
	close(fd);
}


//AXI DMA Control Bus MM2S Channel Wait (Simple Mode)
void DMA_MM2S_Wait()
{
	int map_len = 0x60;
	int fd = open("/dev/mem", O_RDWR);

	unsigned char *dma_base_address;
	dma_base_address = (unsigned char *)mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)AXIDMA_MM2S_BASEADDR);
	if(dma_base_address == MAP_FAILED)
	{
		perror("DMA Reset Mapping memory for absolute memory access failed.\n");
		return;
	}
	while(!(REG_READ(dma_base_address, MM2S_DMASR)&0x1000));

	munmap((void *)dma_base_address, map_len);
	close(fd);
}

//AXI DMA Control Bus S2MM Channel Wait (Simple Mode)
void DMA_S2MM_Wait()
{
	int map_len = 0x60;
	int fd = open("/dev/mem", O_RDWR);

	unsigned char *dma_base_address;
	dma_base_address = (unsigned char *)mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)AXIDMA_S2MM_BASEADDR);
	if(dma_base_address == MAP_FAILED)
	{
		perror("DMA Reset Mapping memory for absolute memory access failed.\n");
		return;
	}
	while(!(REG_READ(dma_base_address, S2MM_DMASR)&0x1000));

	munmap((void *)dma_base_address, map_len);
	close(fd);
}

3、测试程序可以参考:https://blog.csdn.net/weixin_40604731/article/details/92700634
或者自己写一下吧 balabala

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值