cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
kampi
Explorer
Explorer
648 Views
Registered: ‎02-18-2013

Sending data from one VDMA to another

Jump to solution

I have a design with one read direction VDMA and one write direction VDMA and I want to transmit some data over AXI-Stream from one VDMA to another VDMA (I want to test the setup before I can use it for my final project).

VDMA.png

My code looks as shown below:

#include "xaxivdma.h"
#include "xparameters.h"

#define WORDS								8

XAxiVdma_Config* ReadVDMA_ConfigPtr;
XAxiVdma ReadVDMA;
XAxiVdma_DmaSetup ReadCfg;

XAxiVdma_Config* WriteVDMA_ConfigPtr;
XAxiVdma WriteVDMA;
XAxiVdma_DmaSetup WriteCfg;

int Status;
unsigned int Source[WORDS] __attribute__((aligned(0x20)));
unsigned int Dest[WORDS] __attribute__((aligned(0x20)));

int main(void)
{
	xil_printf("--- OV7670 interface test ---- \n\r");

	// Fill the transmit buffer
	for(int i = 0x00; i < WORDS; i++)
	{
		Source[i] = i;
	}

	ReadVDMA_ConfigPtr = XAxiVdma_LookupConfig(XPAR_AXIVDMA_0_DEVICE_ID);
	if(ReadVDMA_ConfigPtr == NULL)
	{
		xil_printf("[ERROR] Invalid VDMA configuration!\n\r");
		return XST_FAILURE;
	}
	XAxiVdma_CfgInitialize(&ReadVDMA, ReadVDMA_ConfigPtr, ReadVDMA_ConfigPtr->BaseAddress);

	WriteVDMA_ConfigPtr = XAxiVdma_LookupConfig(XPAR_AXIVDMA_1_DEVICE_ID);
	if(WriteVDMA_ConfigPtr == NULL)
	{
		xil_printf("[ERROR] Invalid VDMA write configuration!\n\r");
		return XST_FAILURE;
	}
	XAxiVdma_CfgInitialize(&WriteVDMA, WriteVDMA_ConfigPtr, WriteVDMA_ConfigPtr->BaseAddress);

	WriteCfg.VertSizeInput = 1;
	WriteCfg.HoriSizeInput = 8 * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
	WriteCfg.Stride = 8 * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
	WriteCfg.FrameDelay = 0;
	WriteCfg.EnableCircularBuf = 1;
	WriteCfg.EnableSync = 1;
	WriteCfg.PointNum = 0;
	WriteCfg.EnableFrameCounter = 0;
	WriteCfg.FrameStoreStartAddr[0] = (int)Dest;

	ReadCfg.VertSizeInput = 1;
	ReadCfg.HoriSizeInput = 8 * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
	ReadCfg.Stride = 8 * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
	ReadCfg.FrameDelay = 0;
	ReadCfg.EnableCircularBuf = 1;
	ReadCfg.EnableSync = 1;
	ReadCfg.PointNum = 0;
	ReadCfg.EnableFrameCounter = 0;
	ReadCfg.FrameStoreStartAddr[0] = (int)Source;

	Status = XAxiVdma_DmaConfig(&ReadVDMA, XAXIVDMA_WRITE, &ReadCfg);
	if(Status != XST_SUCCESS)
	{
		xil_printf("READ channel configuration failed: %d\r\n", Status);

		return Status;
	}

	Status = XAxiVdma_DmaConfig(&WriteVDMA, XAXIVDMA_READ, &WriteCfg);
	if(Status != XST_SUCCESS)
	{
		xil_printf("WRITE channel configuration failed: %d\r\n", Status);
		return XST_FAILURE;
	}

	Status = XAxiVdma_DmaSetBufferAddr(&ReadVDMA, XAXIVDMA_WRITE, Source);
	if(Status != XST_SUCCESS)
	{
		xil_printf("READ channel set buffer address failed: %d\r\n", Status);

		return XST_FAILURE;
	}

	Status = XAxiVdma_DmaSetBufferAddr(&WriteVDMA, XAXIVDMA_READ, Dest);
	if(Status != XST_SUCCESS)
	{
		xil_printf("WRITE channel set buffer address failed: %d\r\n", Status);

		return XST_FAILURE;
	}

	Status = XAxiVdma_DmaStart(&ReadVDMA, XAXIVDMA_WRITE);
	if(Status != XST_SUCCESS)
	{
		xil_printf("Start READ transfer failed: %d\r\n", Status);

		return XST_FAILURE;
	}

	Status = XAxiVdma_DmaStart(&WriteVDMA, XAXIVDMA_READ);
	if(Status != XST_SUCCESS)
	{
		xil_printf("Start WRITE transfer failed: %d\r\n", Status);

		return XST_FAILURE;
	}

	while((!XAxiVdma_IsBusy(&WriteVDMA,XAXIVDMA_READ)) | (!XAxiVdma_IsBusy(&ReadVDMA, XAXIVDMA_WRITE)));

	xil_printf("Transmitted:\n\r");
	for(int i = 0x00; i < WORDS; i++)
	{
		xil_printf("Pixel %lu: %lu\n\r", i, Source[i]);
	}

	xil_printf("Received:\n\r");
	for(int i = 0x00; i < WORDS; i++)
	{
		xil_printf("Pixel %lu: %lu\n\r", i, Dest[i]);
	}


	while(1)
	{
	}

	return XST_SUCCESS;
}

 But it seems that no data were transmitted:

--- OV7670 interface test ----
Transmitted:
Pixel 0: 0
Pixel 1: 1
Pixel 2: 2
Pixel 3: 3
Pixel 4: 4
Pixel 5: 5
Pixel 6: 6
Pixel 7: 7
Received:
Pixel 0: 0
Pixel 1: 0
Pixel 2: 0
Pixel 3: 0
Pixel 4: 0
Pixel 5: 0
Pixel 6: 0
Pixel 7: 0

What is wrong with this code?

Thank you!

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
florentw
Moderator
Moderator
496 Views
Registered: ‎11-09-2015

HI @kampi 

As per my article (Debugging the VDMA), there can be some errors flagged while starting the AXI VDMA.

I would say that when you are working from one AXI VDMA to another, it is unlikely to have EOL or SOF error as you should be using the same configuration.

Maybe what you can do is to start the write channel before the read channel. This is how it is mentioned in the PG020 and in my article (Using the AXI VDMA in Triple Buffer Mode):

https://forums.xilinx.com/t5/Design-and-Debug-Techniques-Blog/Video-Series-24-Using-the-AXI-VDMA-in-Triple-Buffer-Mode/ba-p/938327 


Florent
Product Application Engineer - Xilinx Technical Support EMEA
**~ Don't forget to reply, give kudos, and accept as solution.~**

View solution in original post

0 Kudos
6 Replies
florentw
Moderator
Moderator
582 Views
Registered: ‎11-09-2015

HI @kampi 

  1. Make sure you are not reading/writing in the cache memory. I would suggest you disable the cache.
  2.  Add an ILA and check what is happening in HW

Florent
Product Application Engineer - Xilinx Technical Support EMEA
**~ Don't forget to reply, give kudos, and accept as solution.~**
kampi
Explorer
Explorer
562 Views
Registered: ‎02-18-2013

I have updated the code to continue sending.

#include "xil_cache.h"
#include "xaxivdma.h"
#include "xparameters.h"

#define WORDS								1024

XAxiVdma_Config* WriteVDMA_ConfigPtr;
XAxiVdma WriteVDMA;

XAxiVdma_DmaSetup ReadCfg;
XAxiVdma_DmaSetup WriteCfg;

int Status;
unsigned int Source[1024] __attribute__((aligned(0x20)));
unsigned int Dest[1024] __attribute__((aligned(0x20)));

int main(void)
{
	xil_printf("--- OV7670 interface test ---- \n\r");

	Xil_ICacheDisable();
	Xil_DCacheDisable();

	// Fill the transmit buffer
	for(int i = 0x00; i < WORDS; i++)
	{
		Source[i] = i;
	}

	while(1)
	{
		WriteVDMA_ConfigPtr = XAxiVdma_LookupConfig(XPAR_AXIVDMA_0_DEVICE_ID);
		if(WriteVDMA_ConfigPtr == NULL)
		{
			xil_printf("[ERROR] Invalid VDMA write configuration!\n\r");
			return XST_FAILURE;
		}
		XAxiVdma_CfgInitialize(&WriteVDMA, WriteVDMA_ConfigPtr, WriteVDMA_ConfigPtr->BaseAddress);

		xil_printf("Stream width: %d\n\r", WriteVDMA_ConfigPtr->Mm2SStreamWidth);

		WriteCfg.VertSizeInput = 2;
		WriteCfg.HoriSizeInput = 512 * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
		WriteCfg.Stride = 512 * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
		WriteCfg.FrameDelay = 0;
		WriteCfg.EnableCircularBuf = 1;
		WriteCfg.EnableSync = 1;
		WriteCfg.PointNum = 0;
		WriteCfg.EnableFrameCounter = 0;
		WriteCfg.FrameStoreStartAddr[0] = (int)Dest;

		ReadCfg.VertSizeInput = 2;
		ReadCfg.HoriSizeInput = 512 * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
		ReadCfg.Stride = 512 * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
		ReadCfg.FrameDelay = 0;
		ReadCfg.EnableCircularBuf = 1;
		ReadCfg.EnableSync = 1;
		ReadCfg.PointNum = 0;
		ReadCfg.EnableFrameCounter = 0;
		ReadCfg.FrameStoreStartAddr[0] = (int)Source;

		Status = XAxiVdma_DmaConfig(&WriteVDMA, XAXIVDMA_READ, &ReadCfg);
		if(Status != XST_SUCCESS)
		{
			xil_printf("READ channel configuration failed: %d\r\n", Status);

			return Status;
		}

		Status = XAxiVdma_DmaConfig(&WriteVDMA, XAXIVDMA_WRITE, &WriteCfg);
		if(Status != XST_SUCCESS)
		{
			xil_printf("WRITE channel configuration failed: %d\r\n", Status);
			return XST_FAILURE;
		}

		Status = XAxiVdma_DmaSetBufferAddr(&WriteVDMA, XAXIVDMA_WRITE, WriteCfg.FrameStoreStartAddr);
		if(Status != XST_SUCCESS)
		{
			xil_printf("WRITE channel set buffer address failed: %d\r\n", Status);

			return XST_FAILURE;
		}

		Status = XAxiVdma_DmaStart(&WriteVDMA, XAXIVDMA_WRITE);
		if(Status != XST_SUCCESS)
		{
			xil_printf("Start WRITE transfer failed: %d\r\n", Status);

			return XST_FAILURE;
		}

		while(!XAxiVdma_IsBusy(&WriteVDMA, XAXIVDMA_WRITE));

		xil_printf("Transmitted:\n\r");
		for(int i = 0x00; i < 8; i++)
		{
			xil_printf("Pixel %lu: %lu\n\r", i, Source[i]);
		}

		xil_printf("Received:\n\r");
		for(int i = 0x00; i < 8; i++)
		{
			xil_printf("Pixel %lu: %lu\n\r", i, Dest[i]);
		}

		for(u32 i = 0x00; i < 0xFFFFF; i++);
	}

	return XST_SUCCESS;
}

And it seems that no transmission occurs.

ILA.png

0 Kudos
florentw
Moderator
Moderator
532 Views
Registered: ‎11-09-2015

HI @kampi 

What do you get in the UART?

What are the values of the status register?

One thing you might want to read is my article around debugging the AXI VDMA:

Video Series 25: Debugging issues on the AXI VDMA IP


Florent
Product Application Engineer - Xilinx Technical Support EMEA
**~ Don't forget to reply, give kudos, and accept as solution.~**
0 Kudos
kampi
Explorer
Explorer
507 Views
Registered: ‎02-18-2013

I found one error where I accidentally remove the enable of the read channel. After adding the function call the VDMA starts his transmission, but I got some errors in the status register and in the error code.

 

---------------------------------
Stream width: 32
Transmitted:
Pixel 0: 0
Pixel 1: 1
Pixel 2: 2
Pixel 3: 3
Pixel 4: 4
Pixel 5: 5
Pixel 6: 6
Pixel 7: 7
Received:
Pixel 0: 2678656476
Pixel 1: 280655706
Pixel 2: 362380731
Pixel 3: 1809448975
Pixel 4: 4017420404
Pixel 5: 1550003985
Pixel 6: 324176514
Pixel 7: 87499473
Status S2MM (WRITE): 88080
Errors (WRITE): 2064
Status MM2S (READ): 69632
Errors (READ): 0
---------------------------------

 

I don´t understand the error. According to the datasheet I got a "SOFLateErr" error which occurs when the incoming frame size is greater than the programmed vsize value. But I use a buffer of 8 words with 4 byte each and I configure the write and the read channel for 1 line vertical and 8 * 32 bytes horizontal. So it seems that there is an issue with the data size, but I can not figure out which problem.

The current code is shown below:

 

#include "xil_cache.h"
#include "xaxivdma.h"
#include "xparameters.h"

#define WORDS								8

XAxiVdma_Config* WriteVDMA_ConfigPtr;
XAxiVdma WriteVDMA;

XAxiVdma_DmaSetup ReadCfg;
XAxiVdma_DmaSetup WriteCfg;

int Status;
u32 Source[WORDS] __attribute__((aligned(0x20)));
u32 Dest[WORDS] __attribute__((aligned(0x20)));

int main(void)
{
	xil_printf("--- OV7670 interface test ---- \n\r");

	Xil_ICacheDisable();
	Xil_DCacheDisable();

	// Fill the transmit buffer
	for(int i = 0x00; i < WORDS; i++)
	{
		Source[i] = i;
	}

	while(1)
	{

		WriteVDMA_ConfigPtr = XAxiVdma_LookupConfig(XPAR_AXIVDMA_0_DEVICE_ID);
		if(WriteVDMA_ConfigPtr == NULL)
		{
			xil_printf("[ERROR] Invalid VDMA write configuration!\n\r");
			return XST_FAILURE;
		}
		XAxiVdma_CfgInitialize(&WriteVDMA, WriteVDMA_ConfigPtr, WriteVDMA_ConfigPtr->BaseAddress);

		xil_printf("Stream width: %d\n\r", WriteVDMA_ConfigPtr->Mm2SStreamWidth);

		WriteCfg.VertSizeInput = 1;
		WriteCfg.HoriSizeInput = WORDS * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
		WriteCfg.Stride = WORDS * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
		WriteCfg.FrameDelay = 0;
		WriteCfg.EnableCircularBuf = 1;
		WriteCfg.EnableSync = 1;
		WriteCfg.PointNum = 0;
		WriteCfg.EnableFrameCounter = 0;
		WriteCfg.FrameStoreStartAddr[0] = (int)Dest;

		ReadCfg.VertSizeInput = 1;
		ReadCfg.HoriSizeInput = WORDS * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
		ReadCfg.Stride = WORDS * (WriteVDMA_ConfigPtr->Mm2SStreamWidth >> 3);
		ReadCfg.FrameDelay = 0;
		ReadCfg.EnableCircularBuf = 1;
		ReadCfg.EnableSync = 1;
		ReadCfg.PointNum = 0;
		ReadCfg.EnableFrameCounter = 0;
		ReadCfg.FrameStoreStartAddr[0] = (int)Source;

		Status = XAxiVdma_DmaConfig(&WriteVDMA, XAXIVDMA_READ, &ReadCfg);
		if(Status != XST_SUCCESS)
		{
			xil_printf("READ channel configuration failed: %d\r\n", Status);

			return Status;
		}

		Status = XAxiVdma_DmaConfig(&WriteVDMA, XAXIVDMA_WRITE, &WriteCfg);
		if(Status != XST_SUCCESS)
		{
			xil_printf("WRITE channel configuration failed: %d\r\n", Status);
			return XST_FAILURE;
		}

		Status = XAxiVdma_DmaSetBufferAddr(&WriteVDMA, XAXIVDMA_WRITE, WriteCfg.FrameStoreStartAddr);
		if(Status != XST_SUCCESS)
		{
			xil_printf("WRITE channel set buffer address failed: %d\r\n", Status);

			return XST_FAILURE;
		}

		Status = XAxiVdma_DmaStart(&WriteVDMA, XAXIVDMA_READ);
		if(Status != XST_SUCCESS)
		{
			xil_printf("Start WRITE transfer failed: %d\r\n", Status);

			return XST_FAILURE;
		}

		Status = XAxiVdma_DmaStart(&WriteVDMA, XAXIVDMA_WRITE);
		if(Status != XST_SUCCESS)
		{
			xil_printf("Start WRITE transfer failed: %d\r\n", Status);

			return XST_FAILURE;
		}

		while(!XAxiVdma_IsBusy(&WriteVDMA, XAXIVDMA_WRITE));

		xil_printf("Transmitted:\n\r");
		for(int i = 0x00; i < WORDS; i++)
		{
			xil_printf("Pixel %lu: %lu\n\r", i, Source[i]);
		}

		xil_printf("Received:\n\r");
		for(int i = 0x00; i < WORDS; i++)
		{
			xil_printf("Pixel %lu: %lu\n\r", i, Dest[i]);
		}

		xil_printf("Status S2MM (WRITE): %lu\n\r", XAxiVdma_GetStatus(&WriteVDMA, XAXIVDMA_WRITE));
		xil_printf("Errors (WRITE): %lu\n\r", XAxiVdma_GetDmaChannelErrors(&WriteVDMA, XAXIVDMA_WRITE));
		xil_printf("Status MM2S (READ): %lu\n\r", XAxiVdma_GetStatus(&WriteVDMA, XAXIVDMA_READ));
		xil_printf("Errors (READ): %lu\n\r", XAxiVdma_GetDmaChannelErrors(&WriteVDMA, XAXIVDMA_READ));
		xil_printf("---------------------------------\n\r");

		for(u32 i = 0x00; i < 0xFFFFFF; i++);
	}

	return XST_SUCCESS;
}

 

 

0 Kudos
florentw
Moderator
Moderator
497 Views
Registered: ‎11-09-2015

HI @kampi 

As per my article (Debugging the VDMA), there can be some errors flagged while starting the AXI VDMA.

I would say that when you are working from one AXI VDMA to another, it is unlikely to have EOL or SOF error as you should be using the same configuration.

Maybe what you can do is to start the write channel before the read channel. This is how it is mentioned in the PG020 and in my article (Using the AXI VDMA in Triple Buffer Mode):

https://forums.xilinx.com/t5/Design-and-Debug-Techniques-Blog/Video-Series-24-Using-the-AXI-VDMA-in-Triple-Buffer-Mode/ba-p/938327 


Florent
Product Application Engineer - Xilinx Technical Support EMEA
**~ Don't forget to reply, give kudos, and accept as solution.~**

View solution in original post

0 Kudos
kampi
Explorer
Explorer
470 Views
Registered: ‎02-18-2013

Hi @florentw,

okay I got the DMA running by using the code from your tutorial. Now I have to check the difference between your low level code and the driver based code.

 

DMA.png