10-02-2020 09:03 AM
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).
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!
10-07-2020 09:00 AM
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):
10-05-2020 02:11 AM
HI @kampi
10-05-2020 12:24 PM
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.
10-06-2020 01:30 AM
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
10-07-2020 06:07 AM
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;
}
10-07-2020 09:00 AM
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):
10-08-2020 03:33 AM
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.