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