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 heitbrsp
Visitor
1,284 Views
Registered: ‎01-25-2017

bare metal axi iic interrupt help

Hi,

 

I'm trying to get an i2c AXI peripheral to work on a Zynq board. I have the thing working in so far as it actually is able to send messages, but I seem to have problems getting the interrupt system to work. In this system the iic IP interrupt is hooked directly into the interrupt port of the zynq processor. I found the example bare metal i2c in the BSP program along with the scu/gci BSP example. I've combined the two together, but I'm still not seeing any interrupts.  I've posted the program below. Any hints would be helpful.

 

 

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

/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */


/*
 * The following constant defines the address of the IIC
 * temperature sensor device on the IIC bus. Note that since
 * the address is only 7 bits, this  constant is the address divided by 2.
 */
#define CAMERA_SLAVE_ADDRESS	0X30	/* camera read addr */

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

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

/************************** Function Prototypes ****************************/

int TempSensorExample(u16 IicDeviceId, u8 TempSensorAddress,
						  u8 *TemperaturePtr);

int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr);

int ScuGicInterrupt_Init(u16 DeviceId,XIic *IicInstancePtr);

static void  SendHandler (void *CallbackRef, int ByteCount);

static void RecvHandler(void *CallbackRef, int ByteCount);

static void StatusHandler(void *CallbackRef, int Status);

void My_XIic_InterruptHandler(void *InstancePtr);


/************************** Variable Definitions **************************/



XScuGic InterruptController; /* Instance of the Interrupt Controller */
static XScuGic_Config *GicConfig;/* The configuration parameters of thecontroller */


XIic Iic;		  /* The instance of the IIC device */

int TransmitComplete = 0;


/*
 * The following structure contains fields that are used with the callbacks
 * (handlers) of the IIC driver. The driver asynchronously calls handlers
 * when abnormal events occur or when data has been sent or received. This
 * structure must be volatile to work when the code is optimized.
 */
volatile struct {
	int  EventStatus;
	int  RemainingRecvBytes;
	int EventStatusUpdated;
	int RecvBytesUpdated;
} HandlerInfo;

/*****************************************************************************/
/**
*
* The purpose of this function is to illustrate how to use the IIC driver to
* read the temperature.
*
* @param	None
*
* @return	XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note		None
*
*******************************************************************************/
int main(void)
{
	int Status;
	u8 TemperaturePtr;

	/*
	 * Call the TempSensorExample.
	 */
	Status =  TempSensorExample(IIC_DEVICE_ID, CAMERA_SLAVE_ADDRESS,
							&TemperaturePtr);
	if (Status != XST_SUCCESS) {
		xil_printf("IIC tempsensor Example Failed\r\n");
		return XST_FAILURE;
	}

	xil_printf("Successfully ran IIC camera read Example\r\n");
	xil_printf("Value returned: 0x%x \r\n",TemperaturePtr);

	return XST_SUCCESS;

}

/*****************************************************************************/
/**
* The function reads the temperature of the IIC temperature sensor on the
* IIC bus. It initializes the IIC device driver and sets it up to communicate
* with the temperature sensor. This function does contain a loop that polls
* for completion of the IIC processing such that it may not return if
* interrupts or the hardware are not working.
*
* @param	IicDeviceId is the XPAR_<IIC_instance>_DEVICE_ID value from
*		xparameters.h for the IIC Device
* @param	TempSensorAddress is the address of the Temperature Sensor device
*		on the IIC bus
* @param	TemperaturePtr is the data byte read from the temperature sensor
*
* @return	XST_SUCCESS to indicate success, else XST_FAILURE to indicate
*		a Failure.
*
* @note		None.
*
*******************************************************************************/
int TempSensorExample(u16 IicDeviceId, u8 TempSensorAddress, u8 *RecBuffer)
{
	int Status;
	static int Initialized = FALSE;
	XIic_Config *ConfigPtr;	/* Pointer to configuration data */

	u8 buff[1];
//INIT------------------------------------------------------
	if (!Initialized) {
		Initialized = TRUE;

		/*
		 * Initialize the IIC driver so that it is ready to use.
		 */
		ConfigPtr = XIic_LookupConfig(IicDeviceId);
		if (ConfigPtr == NULL) {
			return XST_FAILURE;
		}

		Status = XIic_CfgInitialize(&Iic, ConfigPtr,
						ConfigPtr->BaseAddress);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}


		/*
		 * Setup handler to process the asynchronous events which occur,
		 * the driver is only interrupt driven such that this must be
		 * done prior to starting the device.
		 */
		XIic_SetRecvHandler(&Iic, (void *)&HandlerInfo, RecvHandler);
		XIic_SetSendHandler(&Iic, (void *)&HandlerInfo, SendHandler);
		XIic_SetStatusHandler(&Iic, (void *)&HandlerInfo,
						StatusHandler);

		/*
		 * Connect the ISR to the interrupt and enable interrupts.
		 */
		Status =  ScuGicInterrupt_Init(XPAR_PS7_SCUGIC_0_DEVICE_ID,&Iic);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}

		/*
		 * Start the IIC driver such that it is ready to send and
		 * receive messages on the IIC interface, set the address
		 * to send to which is the temperature sensor address
		 */
		XIic_Start(&Iic);
		XIic_SetAddress(&Iic, XII_ADDR_TO_SEND_TYPE, TempSensorAddress);
	}
//INIT---------------------------------------------------------------
	Status = XST_FAILURE;

	buff[0]=0x0A;
	if (XIic_MasterSend(&Iic, buff, 1) !=XST_SUCCESS){
		return Status;
	}

	//while(TransmitComplete ==0);

	/*
	 * Attempt to receive a byte of data from the temperature sensor
	 * on the IIC interface, ignore the return value since this example is
	 * a single master system such that the IIC bus should not ever be busy
	 */
	if (XIic_MasterRecv(&Iic, RecBuffer, 1))
		return Status;

	/*
	 * The message is being received from the temperature sensor,
	 * wait for it to complete by polling the information that is
	 * updated asynchronously by interrupt processing
	 */
	while(1) {
		if(HandlerInfo.RecvBytesUpdated == TRUE) {
			/*
			 * The device information has been updated for receive
			 * processing,if all bytes received (1), indicate
			 * success
			 */
			if (HandlerInfo.RemainingRecvBytes == 0) {
				Status = XST_SUCCESS;
			}
			break;
		}

		/*
		 * Any event status which occurs indicates there was an error,
		 * so return unsuccessful, for this example there should be no
		 * status events since there is a single master on the bus
		 */
		if (HandlerInfo.EventStatusUpdated == TRUE) {
			break;
		}
	}

	return Status;
}




int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr)
{
	/*
	* Connect the interrupt controller interrupt handler to the hardware
	* interrupt handling logic in the ARM processor.
	*/
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
	(Xil_ExceptionHandler) XScuGic_InterruptHandler,
	XScuGicInstancePtr);
	/*
	* Enable interrupts in the ARM
	*/
	Xil_ExceptionEnable();
	return XST_SUCCESS;
}


int ScuGicInterrupt_Init(u16 DeviceId,XIic *IicInstancePtr)
{
	int Status;
	/*
	* Initialize the interrupt controller driver so that it is ready to
	* use.
	* */
	GicConfig = XScuGic_LookupConfig(DeviceId);
	if (NULL == GicConfig) {
	return XST_FAILURE;
	}
	Status = XScuGic_CfgInitialize(&InterruptController, GicConfig,GicConfig->CpuBaseAddress);

	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	/*
	* Setup the Interrupt System
	* */
	Status = SetUpInterruptSystem(&InterruptController);
	if (Status != XST_SUCCESS) {
	return XST_FAILURE;
	}


	/*
	 * Perform a self-test to ensure that the hardware was built
	 * correctly
	 */
	Status = XScuGic_SelfTest(&InterruptController);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	* Connect a device driver handler that will be called when an
	* interrupt for the device occurs, the device driver handler performs
	* the specific interrupt processing for the device
	*/
	Status = XScuGic_Connect(&InterruptController,
			XPAR_FABRIC_IIC_0_VEC_ID,
			(Xil_ExceptionHandler)XIic_InterruptHandler,
			(void *)IicInstancePtr
	);
	if (Status != XST_SUCCESS) {
	return XST_FAILURE;
	}
	/*
	* Enable the interrupt for the device and then cause (simulate) an
	* interrupt so the handlers will be called
	*/
	XScuGic_Enable(&InterruptController, XPAR_FABRIC_AXI_IIC_0_IIC2INTC_IRPT_INTR);
	return XST_SUCCESS;
}



static void SendHandler(void *CallbackRef, int ByteCount)
{
	TransmitComplete = 1;
}




/*****************************************************************************/
/**
* This receive handler is called asynchronously from an interrupt context and
* and indicates that data in the specified buffer was received. The byte count
* should equal the byte count of the buffer if all the buffer was filled.
*
* @param	CallBackRef is a pointer to the IIC device driver instance which
*		the handler is being called for.
* @param	ByteCount indicates the number of bytes remaining to be received of
*		the requested byte count. A value of zero indicates all requested
*		bytes were received.
*
* @return	None.
*
* @notes	None.
*
****************************************************************************/
static void RecvHandler(void *CallbackRef, int ByteCount)
{
	HandlerInfo.RemainingRecvBytes = ByteCount;
	HandlerInfo.RecvBytesUpdated = TRUE;
}

/*****************************************************************************/
/**
* This status handler is called asynchronously from an interrupt context and
* indicates that the conditions of the IIC bus changed. This  handler should
* not be called for the application unless an error occurs.
*
* @param	CallBackRef is a pointer to the IIC device driver instance which the
*		handler is being called for.
* @param	Status contains the status of the IIC bus which changed.
*
* @return	None.
*
* @notes	None.
*
****************************************************************************/
static void StatusHandler(void *CallbackRef, int Status)
{
	HandlerInfo.EventStatus |= Status;
	HandlerInfo.EventStatusUpdated = TRUE;
}

void My_XIic_InterruptHandler(void *InstancePtr){
	XIic_InterruptHandler(InstancePtr);
}
0 Kudos
1 Reply
Observer aviteri@dorc
Observer
1,056 Views
Registered: ‎01-23-2017

Re: bare metal axi iic interrupt help

HI heitbrsp,

I am having the same problem state here.

What I noticed is : if you uncomment the

while(TransmitComplete ==0);

then it works. I have in my code the following

 

while (!TransmitComplete || (XIic_IsIicBusy(InstancePtr) == TRUE)); /* Wait till the transmission is completed. */

 With that the interrupt is triggered and the SendHandler function is reached.

 

However, I don't like it because the processor is kept in the while waiting.

 

Did you solve your issue ?.

I am looking for a solution in which the while is not used. 

 

Greetings,

 

AV.

0 Kudos