cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
889 Views
Registered: ‎05-08-2015

AXI DMA interrupt halted

hello I´ve implemented a system to write data in DDR of a zc702.

I have just the S2MM channel.

I send data throught a counter with axi stream interface. The counter is sending counts from 0 up to 1023, and asserts tlast=´1´ just when it gets 1023.

The max burst size of DMA is set to 16. (I suppose I can do 16 transfers of 32bit data for each stream cycle). The fact I will assert tlast = '1' after 1023 cycles is it correct? or do I have to assert tlast=1 every 16 transfers maximum?

 

because I got an error of halted DMA when I get the interrupt:

Xil_In32 (XPAR_AXI_DMA_0_BASEADDR + 0x34) gives me 5011 (halted error and DMA internal error)

 

I really cannot understand why. since I have a really easy design:1.jpg

 

2.jpg

3.jpg

 

 

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "ps7_init.h"
#include <xil_io.h>
#include "xscugic.h"
#include "xparameters.h"

//interrupt controller
// Interrupt controller initialization.
// Controller (GIC) instance, and the other for config information
// Declare 2 structs for the General Interrupt Controller INTInst:
// XScuGic INTCInst for the GIC instance
// XScuGic_Config *IntcConfig for config information
XScuGic INTCInst;
static XScuGic_Config *IntcConfig;
u32 global_frame_counter = 0;

int InitializeAXIDma (void){
	unsigned int tmpVal;
	// S2MM_DMACR.RS=1
	tmpVal = Xil_In32 (XPAR_AXI_DMA_0_BASEADDR + 0x30);
	tmpVal = tmpVal | 0x1001;
	Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR + 0x30, tmpVal);
	tmpVal = Xil_In32 (XPAR_AXI_DMA_0_BASEADDR + 0x30);
	xil_printf ( "value for dma control register : %x\n\r", tmpVal);
	return 0;
}

//////////////////////////////////////////////////////
//
// Start DMA Transfer
//
//////////////////////////////////////////////
void StartDMATransfer ( unsigned int dstAddress, unsigned int len){
	// write desitination address to S2MM_DA register
	Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR + 0x48, dstAddress);
	// write length to S2MM_length register in bytes
	Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR + 0x58, len);

}

void InterruptHandler ( void ){
	//disable interrupt for the moment
	u32 tmpValue;
	//clear interrupt. just perform a write to bit no 12 of S2MM_DMASR
	tmpValue = Xil_In32 (XPAR_AXI_DMA_0_BASEADDR + 0x34);
	tmpValue = tmpValue | 0x1000;
	Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR + 0x34 , tmpValue);
	tmpValue = Xil_In32 (XPAR_AXI_DMA_0_BASEADDR + 0x34);
	xil_printf ( "register 0x34 : %d \n\r", tmpValue);
	///////////////////////////////////////////////////////////////////
	//
	// Data is now in the DRAM (since it finished processing everything
	// that´s why we have interrupts
	//
	///////////////////////////////////////////////////////////////////

	global_frame_counter++;
	if (global_frame_counter >10){
		xil_printf ( "more than 10 interrupts! : %d \n\r", global_frame_counter);
		return;
	}

	xil_printf("-- first interrupt arrived --\r\n");
	xil_printf ( "frame number : %d \n\r", global_frame_counter);
	int pluto=0;
	int plutoout=0;
	xil_printf("-- do you wish to continue? --\r\n");

	getchar();
	unsigned int value;

	value = Xil_In32 (0xa000000);
	xil_printf ( "value zero register : %x\n\r", value);
	value = Xil_In32 (0xa000000+4);
	xil_printf ( "value first register : %x\n\r", value);
	value = Xil_In32 (0xa000000+8);
	xil_printf ( "value second register : %x\n\r", value);
	value = Xil_In32 (0xa000000+12);
	xil_printf ( "value third register : %x\n\r", value);
	value = Xil_In32 (0xa000000+16);
	xil_printf ( "value fourth register : %x\n\r", value);
	StartDMATransfer (0xa000008 , 32);


}

int InterruptSystemSetup(XScuGic *XScuGicInstancePtr)
{
	////////////////////////////////////////////////////////////////////
	//Connect the interrupt controller interrupt handler to the hardware
	//interrupt handling logic in the ARM processor.

	// Connect the supplied Xilinx general interrupt handler
	// to the interrupt handling logic in the processor.
	// All interrupts go through the interrupt controller, so the
	// ARM processor has to first "ask" the interrupt controller
	// which peripheral generated the interrupt.  The handler that
	// does this is supplied by Xilinx and is called "XScuGic_InterruptHandler"
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler) XScuGic_InterruptHandler,
			XScuGicInstancePtr);

	// Enable interrupts in the ARM
	Xil_ExceptionEnable();

	return XST_SUCCESS;

}

int IntcInitFunction(u16 DeviceId){
	//we have the DeviceId the location for the interrupt in the processor
	//we have *GpioInstancePtr the pointer to our instance BTNInst

	int status;
	///////////////////////////////////////////////////////////////////////
	//initialize the interrupt controller driver so that it is ready to use

	// Look up the config information for the GIC
	// DeviceId is the GIC in the processor,
	// it checks the hardware configuration for the GIC
	IntcConfig = XScuGic_LookupConfig(DeviceId);
	if ( NULL == IntcConfig ) {
		return XST_FAILURE;
	}

	// Initialise the GIC using the config information
	status = XScuGic_CfgInitialize(&INTCInst, IntcConfig,
			IntcConfig->CpuBaseAddress);
	if (status != XST_SUCCESS){
		return XST_FAILURE;
	}

	//////////////////////////////////////////
	// Setup the Interrupt SysteM

	// Call to interrupt setup
	status = InterruptSystemSetup(&INTCInst);
	if (status != XST_SUCCESS)
		return XST_FAILURE;

	//////////////////////////////////////////
	//connect here the different interrupts

	// Connect AXI DMA interrupt to handler
	status = XScuGic_Connect(&INTCInst, XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR,
			(Xil_ExceptionHandler) InterruptHandler, NULL);
	if (status != XST_SUCCESS){
		return XST_FAILURE;
	}
	// Enable GPIO and timer interrupts in the controller
	XScuGic_Enable(&INTCInst, XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR);

	return XST_SUCCESS;



}

int main()
{
    init_platform();

    //enable the pl
    ps7_post_config();

    xil_printf("initializing axi dma ... \n\r");

    InitializeAXIDma();
    int status;

    status = IntcInitFunction(XPAR_PS7_SCUGIC_0_DEVICE_ID);
    	if (status != XST_SUCCESS)
    		return XST_FAILURE;

	//start the first dma transfer
	xil_printf("-- performing the first dma transfer -\r\n");

    StartDMATransfer (0xa000000 , 1024);
    return 0;
}
void InterruptHandler ( void ){
	//disable interrupt for the moment
	u32 tmpValue;
	//clear interrupt. just perform a write to bit no 12 of S2MM_DMASR
	tmpValue = Xil_In32 (XPAR_AXI_DMA_0_BASEADDR + 0x34);
	tmpValue = tmpValue | 0x1000;
	Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR + 0x34 , tmpValue);
	tmpValue = Xil_In32 (XPAR_AXI_DMA_0_BASEADDR + 0x34);
	xil_printf ( "register 0x34 : %d \n\r", tmpValue);

I get the error here, If I avoid to reconfigure the 0x34 register, I get an infinite loop of interrupt, even if I don´t call any axi DMA transfer.

 

Could you help me figuring out the error please?

0 Kudos
1 Reply
Highlighted
Explorer
Explorer
641 Views
Registered: ‎04-19-2018

Re: AXI DMA interrupt halted

If you don't clear the interrupt flag, it will re-enter as soon as you leave the ISR. some processors do that automatically, others don't.
0 Kudos