ARGroup Aleš Ruda

AXI VDMA on ZedBoard

by Administrator 20. March 2013 09:07

I use AXI VDMA IP for store data from stereoscopic camera to the memory. I search example how to use xilinx_dma.c driver. I found information about xvdma.c driver who works as bridge between base VDMA kernel driver and user application, but I am not able to compile it.

Here is my simple solution. I use mmap to access VDMA IP registers and program it. Frame buffers is allocated on end of DDR memory. To prevent use this memory by kernel add mem option to bootargs in devicetree.dts.

  1. Changes in devicetree.dts
    bootargs = "consoleblank=0 root=/dev/mmcblk0p2 rw rootwait earlyprintk mem=224M";
    
  2. main.c
    #include 
    #include 
    #include 
    #include 
    
    #include "VDMA.h"
    
    #define VDMAWidth 752
    #define VDMAHeight 480
    #define VDMAPixelWidth 8
    #define VDMAFB1Adr 0x1e000000
    #define VDMAFB2Adr 0x1f000000
    #define VDMABaseAddr 0x43000000
    
    
    int main()
    {
    	VDMA_info vdma;
    
    	VDMA_Init(&vdma, VDMABaseAddr, VDMAWidth, VDMAHeight, VDMAPixelWidth, VDMAFB1Adr, VDMAFB2Adr);
    
    	VDMA_Start(&vdma, VDMAFB1Adr);
    
    	printf("Waiting for end...\n");
    	while(VDMA_IsDone(&vdma)==0);
    
    	VDMA_UnInit(&vdma);
    }
    
    
  3. VDMA.c
    /*
     * VDMA.h
     *
     *  Created on: 16.3.2013
     *      Author: Ales
     */
    
    #ifndef VDMA_H_
    #define VDMA_H_
    
    #include
    
    #define VDMACount 64
    #define VDMAMapLen VDMACount*4
    
    typedef struct
    {
        unsigned int baseAddr;
        int vdmaHandler;
        int width;
        int height;
        int pixelLength;
        int fbLength;
        unsigned int* vdmaVirtualAddress;
        unsigned int* fb1VirtualAddress;
        unsigned int* fb2VirtualAddress;
    
        pthread_mutex_t lock;
    } VDMA_info;
    
    int VDMA_Init(VDMA_info *info, unsigned int baseAddr, int width, int height, int pixelLength, unsigned int fb1Addr, unsigned int fb2Addr);
    void VDMA_UnInit(VDMA_info *info);
    unsigned int VDMA_Get(VDMA_info *info, int num);
    void VDMA_Set(VDMA_info *info, int num, unsigned int val);
    void VDMA_Start(VDMA_info *info, unsigned int adr);
    void VDMA_OutStart(VDMA_info *info, unsigned int adr, int circular);
    int VDMA_IsRunning(VDMA_info *info);
    int VDMA_IsDone(VDMA_info *info);
    void VDMA_Disp(VDMA_info *info, char *str, int num);
    
    
    #endif /* VDMA_H_ */
    
    
  4. VDMA.c
    /*
     * VDMA.c
     *
     *  Created on: 17.3.2013
     *      Author: Ales Ruda
     *      web: www.arbot.cz
     */
    
    #include "VDMA.h"
    #include 
    #include 
    #include 
    #include <sys/mman.h>
    
    int VDMA_Init(VDMA_info *info, unsigned int baseAddr, int width, int height, int pixelLength, unsigned int fb1Addr, unsigned int fb2Addr)
    {
    	info->baseAddr=baseAddr;
    	info->width=width;
    	info->height=height;
    	info->pixelLength=pixelLength;
    	info->fbLength=pixelLength*width*height;
        info->vdmaHandler = open("/dev/mem", O_RDWR);
        info->vdmaVirtualAddress = (unsigned int*)mmap(NULL, VDMAMapLen, PROT_READ | PROT_WRITE, MAP_SHARED, info->vdmaHandler, (off_t)info->baseAddr);
        if(info->vdmaVirtualAddress == MAP_FAILED)
        {
         perror("vdmaVirtualAddress mapping for absolute memory access failed.\n");
         return -1;
        }
        info->fb1VirtualAddress = (unsigned int*)mmap(NULL, info->fbLength, PROT_READ | PROT_WRITE, MAP_SHARED, info->vdmaHandler, (off_t)fb1Addr);
        if(info->fb1VirtualAddress == MAP_FAILED)
        {
         perror("fb1VirtualAddress mapping for absolute memory access failed.\n");
         return -2;
        }
        info->fb2VirtualAddress = (unsigned int*)mmap(NULL, info->fbLength, PROT_READ | PROT_WRITE, MAP_SHARED, info->vdmaHandler, (off_t)fb2Addr);
        if(info->fb2VirtualAddress == MAP_FAILED)
        {
         perror("fb2VirtualAddress mapping for absolute memory access failed.\n");
         return -3;
        }
    
        return 0;
    }
    
    void VDMA_UnInit(VDMA_info *info)
    {
        munmap((void *)info->vdmaVirtualAddress, VDMAMapLen);
        munmap((void *)info->fb1VirtualAddress, info->fbLength);
        munmap((void *)info->fb2VirtualAddress, info->fbLength);
        close(info->vdmaHandler);
    }
    
    unsigned int VDMA_Get(VDMA_info *info, int num)
    {
    	if(num>=0 && num<VDMACount)
    	{
    		return info->vdmaVirtualAddress[num];
    	}
    	return 0;
    }
    
    void VDMA_Set(VDMA_info *info, int num, unsigned int val)
    {
    	if(num>=0 && num<VDMACount)
    	{
    		info->vdmaVirtualAddress[num]=val;
    	}
    }
    
    void VDMA_OutStart(VDMA_info *info, unsigned int adr, int circular)
    {
    	VDMA_Disp(info, "status ", 0x04/4);
    	VDMA_Disp(info, "control ", 0x00/4);
    
    	VDMA_Set(info, 0x00/4, circular==1?4+2:4);  // MM2S_DMACR: reset
    
    	while((VDMA_Get(info, 0x00/4)&4)==4); // wait for reset end
    
    	VDMA_Disp(info, "status ", 0x04/4);
    	VDMA_Set(info, 0x04/4, 0xffffffff);  // S2MM_DMASR: remove errors
    	VDMA_Disp(info, "status ", 0004/4);
    
    	usleep(100000);
    
    	VDMA_Set(info, 0x18/4, 1);  // MM2S_FRMSTORE: 1
    
    	VDMA_Set(info, 0x00/4, circular==1?2+1:1);  // S2MM_DMACR: RS
    	// wait for run
    	while((VDMA_Get(info, 0x00/4)&1)==0 || (VDMA_Get(info, 0x04/4)&1)==1)
    	{
    		VDMA_Disp(info, "status ", 0004/4);
    		VDMA_Disp(info, "control ", 0x00/4);
    	}
    
    	VDMA_Set(info, 0x28/4, 0); // this alters s2mm park ptr
    
    	VDMA_Set(info, 0x5C/4, adr); //adr1
    //	VDMA_Set(info, 0x60/4, adr); //adr2
    
    	VDMA_Set(info, 0x58/4, info->pixelLength*info->width);  // stride length in bytes
    
    	VDMA_Set(info, 0x54/4, info->pixelLength*info->width);  // length in bytes
    
        VDMA_Set(info, 0x50/4, info->height);  // height and start
    
        VDMA_Disp(info, "status ", 0x04/4);
    	VDMA_Disp(info, "control ", 0x00/4);
    	VDMA_Disp(info, "Park", 0x28/4);
    }
    
    void VDMA_Start(VDMA_info *info, unsigned int adr)
    {
    	VDMA_Set(info, 0x30/4, 64+4);  // S2MM_DMACR: sof=tuser, reset
    
    	while((VDMA_Get(info, 0x30/4)&4)==4); // wait for reset end
    
    	VDMA_Disp(info, "status ", 0x34/4);
    	VDMA_Set(info, 0x34/4, 0xffffffff);  // S2MM_DMASR: remove errors
    	VDMA_Disp(info, "status ", 0x34/4);
    
    
    	VDMA_Set(info, 0x30/4, 64+1);  // S2MM_DMACR: sof=tuser, RS
    // wait for run
    	while((VDMA_Get(info, 0x30/4)&1)==0 || (VDMA_Get(info, 0x34/4)&1)==1)
    	{
    		VDMA_Disp(info, "status ", 0x34/4);
    		VDMA_Disp(info, "control ", 0x30/4);
    	}
    
    	VDMA_Set(info, 0xAC/4, adr);
    	VDMA_Set(info, 0x28/4, 0);
    
    	VDMA_Set(info, 0xA8/4, info->pixelLength*info->width);  // stride length in bytes
    
    	VDMA_Set(info, 0xA4/4, info->pixelLength*info->width);  // length in bytes
    
        VDMA_Set(info, 0xA0/4, info->height);  // height and start
    	VDMA_Disp(info, "status ", 0x34/4);
    	VDMA_Disp(info, "control ", 0x30/4);
    }
    
    int VDMA_IsRunning(VDMA_info *info)
    {
    	return (VDMA_Get(info, 0x34/4)&1)==1;
    }
    
    int VDMA_IsDone(VDMA_info *info)
    {
    	return (VDMA_Get(info, 0x34/4)&0x01000)!=0;
    }
    
    void VDMA_Disp(VDMA_info *info, char *str, int num)
    {
    	printf("%s(%02x)=%08x\n", str, num, VDMA_Get(info, num));
    }
    
    

Source files vdma.rar (2,01 kb)

Tags:

ZedBoard

Month List