UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor atndech
Visitor
407 Views
Registered: ‎05-23-2019

working on #AR 57562 tlast stays on even when tvalid goes off.

vivado 2016.1

board: zynq 7z030-  xc7Z030fbg676-2.

I started trying the AXI DMA #AR 57562 - Example Design - Using the AXI DMA in interrupt mode to transfer data to memory.

Downloaded the project,

1. I have changed the component in project manager and DDR memory part in ZYNQ PS custom design in the project to suit my board accordingly.

DDR_memoryinfo.PNG

 

 

 

 

2. I the updated the components under Report IP status.

3. In the SDK,

  • - i created a fsbl project.
  • - i then changed it to run on JTAG mode from QSPI mode.
  • - i then created helloworld project and added ps7_post_config.
  • The source code in SDK :-It has minor changes, with addition of ps7 initialisation files and calling ps7_post_config.

The problem:

I can transmit data from PS to PL but i cannot seem to receive data from PL to PS.

  1. AXI DMA MM2S_introut sets, but AXI DMA S2MM_introut (Interrupt from PL to PS side) does not set.
  2. Further Tlast from S_AXIS_S2MM stays on in ILA even after Tvalid goes down.

         As seen in discussions, like in this discussion here

         TLAST could very well be the problem.

But this is the example project, such a mistake  may not be there and the problem could be elsewhere??

- Anyone tried this example and came across the same problem?

- If this is not the problem then what could be?

 

 

Thanks a lot for trying to help!!!

 

#include <stdio.h>
#include "platform.h"

#include <xil_io.h>
#include "ps7_init.h"

/***************************** Include Files *********************************/

#include "xaxidma.h"
#include "xparameters.h"
#include "xil_exception.h"
#include "xdebug.h"

#ifdef XPAR_UARTNS550_0_BASEADDR
#include "xuartns550_l.h" /* to use uartns550 */
#endif


#ifdef XPAR_INTC_0_DEVICE_ID
#include "xintc.h"
#else
#include "xscugic.h"
#endif

/************************** Constant Definitions *****************************/

/*
* Device hardware build related constants.
*/

#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID

#ifdef XPAR_AXI_7SDDR_0_S_AXI_BASEADDR
#define DDR_BASE_ADDR XPAR_AXI_7SDDR_0_S_AXI_BASEADDR
#elif XPAR_MIG7SERIES_0_BASEADDR
#define DDR_BASE_ADDR XPAR_MIG7SERIES_0_BASEADDR
#elif XPAR_MIG_0_BASEADDR
#define DDR_BASE_ADDR XPAR_MIG_0_BASEADDR
#elif XPAR_PSU_DDR_0_S_AXI_BASEADDR
#define DDR_BASE_ADDR XPAR_PSU_DDR_0_S_AXI_BASEADDR
#endif

#ifndef DDR_BASE_ADDR
/*#warning CHECK FOR THE VALID DDR ADDRESS IN XPARAMETERS.H, \
*
* DEFAULT SET TO 0x01000000
*/
#define MEM_BASE_ADDR 0x00100000
#else
#define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x1000000)
#endif

#ifdef XPAR_INTC_0_DEVICE_ID
#define RX_INTR_ID XPAR_INTC_0_AXIDMA_0_S2MM_INTROUT_VEC_ID
#define TX_INTR_ID XPAR_INTC_0_AXIDMA_0_MM2S_INTROUT_VEC_ID
#else
#define RX_INTR_ID XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR
#define TX_INTR_ID XPAR_FABRIC_AXI_DMA_0_MM2S_INTROUT_INTR
#endif

#define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000)
#define RX_BUFFER_BASE (MEM_BASE_ADDR + 0x00300000)
#define RX_BUFFER_HIGH (MEM_BASE_ADDR + 0x004FFFFF)

#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#else
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#endif

#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC XIntc
#define INTC_HANDLER XIntc_InterruptHandler
#else
#define INTC XScuGic
#define INTC_HANDLER XScuGic_InterruptHandler
#endif


/* Timeout loop counter for reset
*/
#define RESET_TIMEOUT_COUNTER 10000

#define TEST_START_VALUE 0xC
/*
* Buffer and Buffer Descriptor related constant definition
*/
#define MAX_PKT_LEN 0x100

#define NUMBER_OF_TRANSFERS 10

/* The interrupt coalescing threshold and delay timer threshold
* Valid range is 1 to 255
*
* We set the coalescing threshold to be the total number of packets.
* The receive side will only get one completion interrupt for this example.
*/

/**************************** Type Definitions *******************************/


/***************** Macros (Inline Functions) Definitions *********************/


/************************** Function Prototypes ******************************/
#ifndef DEBUG
extern void xil_printf(const char *format, ...);
#endif

#ifdef XPAR_UARTNS550_0_BASEADDR
static void Uart550_Setup(void);
#endif

static int CheckData(int Length, u8 StartValue);
static void TxIntrHandler(void *Callback);
static void RxIntrHandler(void *Callback);



static int SetupIntrSystem(INTC * IntcInstancePtr,
XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId);
static void DisableIntrSystem(INTC * IntcInstancePtr,
u16 TxIntrId, u16 RxIntrId);


/************************** Variable Definitions *****************************/
/*
* Device instance definitions
*/


static XAxiDma AxiDma; /* Instance of the XAxiDma */

static INTC Intc; /* Instance of the Interrupt Controller */

/*
* Flags interrupt handlers use to notify the application context the events.
*/
volatile int TxDone;
volatile int RxDone;
volatile int Error;

int simpleDMA(void);
int main()
{
init_platform();

Xil_ICacheEnable();
Xil_DCacheEnable();
//enable the PS
ps7_post_config();

//xil_printf("Hello World\n\r");
simpleDMA();

Xil_DCacheDisable();
Xil_ICacheDisable();

cleanup_platform();
return 0;
}


/*****************************************************************************/
/**
*
* Main function
*
* This function is the main entry of the interrupt test. It does the following:
* Set up the output terminal if UART16550 is in the hardware build
* Initialize the DMA engine
* Set up Tx and Rx channels
* Set up the interrupt system for the Tx and Rx interrupts
* Submit a transfer
* Wait for the transfer to finish
* Check transfer status
* Disable Tx and Rx interrupts
* Print test status and exit
*
* @param None
*
* @return
* - XST_SUCCESS if example finishes successfully
* - XST_FAILURE if example fails.
*
* @note None.
*
******************************************************************************/
int simpleDMA(void)
{
int Status;
XAxiDma_Config *Config;
int Tries = NUMBER_OF_TRANSFERS;
int Index;
u8 *TxBufferPtr;
u8 *RxBufferPtr;
u8 Value;

TxBufferPtr = (u8 *)TX_BUFFER_BASE ;
RxBufferPtr = (u8 *)RX_BUFFER_BASE;
/* Initial setup for Uart16550 */
#ifdef XPAR_UARTNS550_0_BASEADDR

Uart550_Setup();

#endif

xil_printf("\r\n--- Entering main() --- \r\n");

Config = XAxiDma_LookupConfig(DMA_DEV_ID);
if (!Config) {
xil_printf("No config found for %d\r\n", DMA_DEV_ID);

return XST_FAILURE;
}

/* Initialize DMA engine */
Status = XAxiDma_CfgInitialize(&AxiDma, Config);

if (Status != XST_SUCCESS) {
xil_printf("Initialization failed %d\r\n", Status);
return XST_FAILURE;
}

if(XAxiDma_HasSg(&AxiDma)){
xil_printf("Device configured as SG mode \r\n");
return XST_FAILURE;
}

/* Set up Interrupt system */
Status = SetupIntrSystem(&Intc, &AxiDma, TX_INTR_ID, RX_INTR_ID);
if (Status != XST_SUCCESS) {

xil_printf("Failed intr setup\r\n");
return XST_FAILURE;
}

/* Disable all interrupts before setup */

XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DMA_TO_DEVICE);

XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DEVICE_TO_DMA);

/* Enable all interrupts */
XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DMA_TO_DEVICE);


XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DEVICE_TO_DMA);

/* Initialize flags before start transfer test */
TxDone = 0;
RxDone = 0;
Error = 0;

Value = TEST_START_VALUE;

for(Index = 0; Index < MAX_PKT_LEN; Index ++) {
TxBufferPtr[Index] = Value;

Value = (Value + 1) & 0xFF;
}

/* Flush the SrcBuffer before the DMA transfer, in case the Data Cache
* is enabled
*/
Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN);
#ifdef __aarch64__
Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, MAX_PKT_LEN);
#endif

/* Send a packet */
for(Index = 0; Index < Tries; Index ++) {

Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) RxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);

if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) TxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);

if (Status != XST_SUCCESS) {
return XST_FAILURE;
}


/*
* Wait TX done and RX done
*/
while (!TxDone && !RxDone && !Error) {
/* NOP */
}

if (Error) {
xil_printf("Failed test transmit%s done, "
"receive%s done\r\n", TxDone? "":" not",
RxDone? "":" not");

goto Done;

}

/*
* Test finished, check data
*/
Status = CheckData(MAX_PKT_LEN, 0xC);
if (Status != XST_SUCCESS) {
xil_printf("Data check failed\r\n");
goto Done;
}
}


xil_printf("AXI DMA interrupt example test passed\r\n");


/* Disable TX and RX Ring interrupts and return success */

DisableIntrSystem(&Intc, TX_INTR_ID, RX_INTR_ID);

Done:
xil_printf("--- Exiting main() --- \r\n");

return XST_SUCCESS;
}

#ifdef XPAR_UARTNS550_0_BASEADDR
/*****************************************************************************/
/*
*
* Uart16550 setup routine, need to set baudrate to 9600 and data bits to 8
*
* @param None
*
* @return None
*
* @note None.
*
******************************************************************************/
static void Uart550_Setup(void)
{

XUartNs550_SetBaud(XPAR_UARTNS550_0_BASEADDR,
XPAR_XUARTNS550_CLOCK_HZ, 9600);

XUartNs550_SetLineControlReg(XPAR_UARTNS550_0_BASEADDR,
XUN_LCR_8_DATA_BITS);
}
#endif

/*****************************************************************************/
/*
*
* This function checks data buffer after the DMA transfer is finished.
*
* We use the static tx/rx buffers.
*
* @param Length is the length to check
* @param StartValue is the starting value of the first byte
*
* @return
* - XST_SUCCESS if validation is successful
* - XST_FAILURE if validation is failure.
*
* @note None.
*
******************************************************************************/
static int CheckData(int Length, u8 StartValue)
{
u8 *RxPacket;
int Index = 0;
u8 Value;

RxPacket = (u8 *) RX_BUFFER_BASE;
Value = StartValue;

/* Invalidate the DestBuffer before receiving the data, in case the
* Data Cache is enabled
*/
#ifndef __aarch64__
Xil_DCacheInvalidateRange((u32)RxPacket, Length);
#endif

for(Index = 0; Index < Length; Index++) {
if (RxPacket[Index] != Value) {
xil_printf("Data error %d: %x/%x\r\n",
Index, RxPacket[Index], Value);

return XST_FAILURE;
}
Value = (Value + 1) & 0xFF;
}

return XST_SUCCESS;
}

/*****************************************************************************/
/*
*
* This is the DMA TX Interrupt handler function.
*
* It gets the interrupt status from the hardware, acknowledges it, and if any
* error happens, it resets the hardware. Otherwise, if a completion interrupt
* is present, then sets the TxDone.flag
*
* @param Callback is a pointer to TX channel of the DMA engine.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void TxIntrHandler(void *Callback)
{

u32 IrqStatus;
int TimeOut;
XAxiDma *AxiDmaInst = (XAxiDma *)Callback;

/* Read pending interrupts */
IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DMA_TO_DEVICE);

/* Acknowledge pending interrupts */


XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DMA_TO_DEVICE);

/*
* If no interrupt is asserted, we do not do anything
*/
if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) {

return;
}

/*
* If error interrupt is asserted, raise error flag, reset the
* hardware to recover from the error, and return with no further
* processing.
*/
if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {

Error = 1;

/*
* Reset should never fail for transmit channel
*/
XAxiDma_Reset(AxiDmaInst);

TimeOut = RESET_TIMEOUT_COUNTER;

while (TimeOut) {
if (XAxiDma_ResetIsDone(AxiDmaInst)) {
break;
}

TimeOut -= 1;
}

return;
}

/*
* If Completion interrupt is asserted, then set the TxDone flag
*/
if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {

TxDone = 1;
}
}

/*****************************************************************************/
/*
*
* This is the DMA RX interrupt handler function
*
* It gets the interrupt status from the hardware, acknowledges it, and if any
* error happens, it resets the hardware. Otherwise, if a completion interrupt
* is present, then it sets the RxDone flag.
*
* @param Callback is a pointer to RX channel of the DMA engine.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void RxIntrHandler(void *Callback)
{
u32 IrqStatus;
int TimeOut;
XAxiDma *AxiDmaInst = (XAxiDma *)Callback;

/* Read pending interrupts */
IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DEVICE_TO_DMA);

/* Acknowledge pending interrupts */
XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DEVICE_TO_DMA);

/*
* If no interrupt is asserted, we do not do anything
*/
if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) {
return;
}

/*
* If error interrupt is asserted, raise error flag, reset the
* hardware to recover from the error, and return with no further
* processing.
*/
if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {

Error = 1;

/* Reset could fail and hang
* NEED a way to handle this or do not call it??
*/
XAxiDma_Reset(AxiDmaInst);

TimeOut = RESET_TIMEOUT_COUNTER;

while (TimeOut) {
if(XAxiDma_ResetIsDone(AxiDmaInst)) {
break;
}

TimeOut -= 1;
}

return;
}

/*
* If completion interrupt is asserted, then set RxDone flag
*/
if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {

RxDone = 1;
}
}

/*****************************************************************************/
/*
*
* This function setups the interrupt system so interrupts can occur for the
* DMA, it assumes INTC component exists in the hardware system.
*
* @param IntcInstancePtr is a pointer to the instance of the INTC.
* @param AxiDmaPtr is a pointer to the instance of the DMA engine
* @param TxIntrId is the TX channel Interrupt ID.
* @param RxIntrId is the RX channel Interrupt ID.
*
* @return
* - XST_SUCCESS if successful,
* - XST_FAILURE.if not succesful
*
* @note None.
*
******************************************************************************/
static int SetupIntrSystem(INTC * IntcInstancePtr,
XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId)
{
int Status;

#ifdef XPAR_INTC_0_DEVICE_ID

/* Initialize the interrupt controller and connect the ISRs */
Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {

xil_printf("Failed init intc\r\n");
return XST_FAILURE;
}

Status = XIntc_Connect(IntcInstancePtr, TxIntrId,
(XInterruptHandler) TxIntrHandler, AxiDmaPtr);
if (Status != XST_SUCCESS) {

xil_printf("Failed tx connect intc\r\n");
return XST_FAILURE;
}

Status = XIntc_Connect(IntcInstancePtr, RxIntrId,
(XInterruptHandler) RxIntrHandler, AxiDmaPtr);
if (Status != XST_SUCCESS) {

xil_printf("Failed rx connect intc\r\n");
return XST_FAILURE;
}

/* Start the interrupt controller */
Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
if (Status != XST_SUCCESS) {

xil_printf("Failed to start intc\r\n");
return XST_FAILURE;
}

XIntc_Enable(IntcInstancePtr, TxIntrId);
XIntc_Enable(IntcInstancePtr, RxIntrId);

#else

XScuGic_Config *IntcConfig;


/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}

Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}


XScuGic_SetPriorityTriggerType(IntcInstancePtr, TxIntrId, 0xA0, 0x3);

XScuGic_SetPriorityTriggerType(IntcInstancePtr, RxIntrId, 0xA0, 0x3);
/*
* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device.
*/
Status = XScuGic_Connect(IntcInstancePtr, TxIntrId,
(Xil_InterruptHandler)TxIntrHandler,
AxiDmaPtr);
if (Status != XST_SUCCESS) {
return Status;
}

Status = XScuGic_Connect(IntcInstancePtr, RxIntrId,
(Xil_InterruptHandler)RxIntrHandler,
AxiDmaPtr);
if (Status != XST_SUCCESS) {
return Status;
}

XScuGic_Enable(IntcInstancePtr, TxIntrId);
XScuGic_Enable(IntcInstancePtr, RxIntrId);


#endif

/* Enable interrupts from the hardware */

Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)INTC_HANDLER,
(void *)IntcInstancePtr);

Xil_ExceptionEnable();

return XST_SUCCESS;
}

/*****************************************************************************/
/**
*
* This function disables the interrupts for DMA engine.
*
* @param IntcInstancePtr is the pointer to the INTC component instance
* @param TxIntrId is interrupt ID associated w/ DMA TX channel
* @param RxIntrId is interrupt ID associated w/ DMA RX channel
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void DisableIntrSystem(INTC * IntcInstancePtr,
u16 TxIntrId, u16 RxIntrId)
{
#ifdef XPAR_INTC_0_DEVICE_ID
/* Disconnect the interrupts for the DMA TX and RX channels */
XIntc_Disconnect(IntcInstancePtr, TxIntrId);
XIntc_Disconnect(IntcInstancePtr, RxIntrId);
#else
XScuGic_Disconnect(IntcInstancePtr, TxIntrId);
XScuGic_Disconnect(IntcInstancePtr, RxIntrId);
#endif
}

DMA_intr_HLS.PNG
0 Kudos
6 Replies
Highlighted
Visitor atndech
Visitor
364 Views
Registered: ‎05-23-2019

Re: working on #AR 57562 tlast stays on even when tvalid goes off.

here is the picture of the corresponding ILA signals

Thanks again

ILAinfo.PNG
0 Kudos
Scholar dgisselq
Scholar
351 Views
Registered: ‎05-21-2015

Re: working on #AR 57562 tlast stays on even when tvalid goes off.

Looking over your signal list, I'm not sure I see a problem.  TLAST is a don't care signal if TVALID is not also high.

Dan

0 Kudos
Visitor atndech
Visitor
346 Views
Registered: ‎05-23-2019

Re: working on #AR 57562 tlast stays on even when tvalid goes off.

firstly thanks for replying! glad that someone finally did take their time to do so ..

in this link, a reply from a xilinx employee seems to say so

"For reference TLAST must only be asserted at the end of a transfer of data, and only for that last data transfer (good practice would be to have 1 clock cycle of TLAST when the end of transfer is complete and equal to TVALID for that last beat of data)."

 

would it mean that i am reading too much into these lines?

but then i haven't got on to any other error either

0 Kudos
Scholar dgisselq
Scholar
337 Views
Registered: ‎05-21-2015

Re: working on #AR 57562 tlast stays on even when tvalid goes off.

Yeah, I think you might be reading too much into those lines.

I'm just working from the AXI stream specification.  If !TVALID, TLAST is a don't care.  If some core, Xilinx's or otherwise, treats this differently then the bug is in that core that doesn't treat TLAST as a don't care when !TVALID.

Dan

0 Kudos
Visitor atndech
Visitor
283 Views
Registered: ‎05-23-2019

Re: working on #AR 57562 tlast stays on even when tvalid goes off.

I will check into the Axi DMA core today then. I will check as to what does s2mm IOC depend on in order to be set.

In the meanwhile, could it be that there are some software configuration problem related to this? I.e some ps7_post_config usage or hardware platform related or debug configuration related?

Until then i will check my axi dma core
0 Kudos
Visitor atndech
Visitor
279 Views
Registered: ‎05-23-2019

Re: working on #AR 57562 tlast stays on even when tvalid goes off.

@calebd maybe you too know something that i could get some idea from..

0 Kudos