/**
*
* Runs a limited self-test on the driver/device. This test does a read/write
* test of the Interrupt Registers There is no loopback capabilities for the
* device such that this test does not send or receive data.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return
*		- XST_SUCCESS if no errors are found
*		- XST_FAILURE if errors are found
*
* @note		None.
*
****************************************************************************/
int XIic_SelfTest(XIic *InstancePtr)
{
	int Status = XST_SUCCESS;
	int GlobalIntrStatus;
	u32 IntrEnableStatus;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/*
	 * Store the Global Interrupt Register and the Interrupt Enable Register
	 * contents.
	 */
	GlobalIntrStatus = XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress);
	IntrEnableStatus = XIic_ReadIier(InstancePtr->BaseAddress);

	/*
	 * Reset the device so it's in a known state and the default state of
	 * the interrupt registers can be tested.
	 */
	XIic_Reset(InstancePtr);

	if (XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress)!= 0) {
		Status = XST_FAILURE;
	}

	if (XIic_ReadIier(InstancePtr->BaseAddress)!= 0) {
		Status = XST_FAILURE;
	}

	/*
	 * Test Read/Write to the Interrupt Enable register.
	 */
	XIic_WriteIier(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
	if (XIic_ReadIier(InstancePtr->BaseAddress)!= XIIC_TX_RX_INTERRUPTS) {
		Status = XST_FAILURE;
	}

	/*
	 * Reset device to remove the affects of the previous test.
	 */
	XIic_Reset(InstancePtr);

	/*
	 * Restore the Global Interrupt Register and the Interrupt Enable
	 * Register contents.
	 */
	if (GlobalIntrStatus == TRUE) {
		XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
	}
	XIic_WriteIier(InstancePtr->BaseAddress, IntrEnableStatus);

	return Status;
}
Exemplo n.º 2
0
/**
*
* This function is the interrupt handler for the XIic driver. This function
* should be connected to the interrupt system.
*
* Only one interrupt source is handled for each interrupt allowing
* higher priority system interrupts quicker response time.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
* @internal
*
* The XIIC_INTR_ARB_LOST_MASK and XIIC_INTR_TX_ERROR_MASK interrupts must have
* higher priority than the other device interrupts so that the IIC device does
* not get into a potentially confused state. The remaining interrupts may be
* rearranged with no harm.
*
******************************************************************************/
void XIic_InterruptHandler(void *InstancePtr)
{
	u32 Status;
	u32 IntrStatus;
	u32 IntrPending;
	u32 IntrEnable;
	XIic *IicPtr = NULL;
	u32 Clear = 0;

	/*
	 * Verify that each of the inputs are valid.
	 */
	Xil_AssertVoid(InstancePtr != NULL);

	/*
	 * Convert the non-typed pointer to an IIC instance pointer
	 */
	IicPtr = (XIic *) InstancePtr;

	/*
	 * Get the interrupt Status.
	 */
	IntrPending = XIic_ReadIisr(IicPtr->BaseAddress);
	IntrEnable = XIic_ReadIier(IicPtr->BaseAddress);
	IntrStatus = IntrPending & IntrEnable;

	/*
	 * Do not processes a devices interrupts if the device has no
	 * interrupts pending or the global interrupts have been disabled.
	 */
	if ((IntrStatus == 0) ||
		(XIic_IsIntrGlobalEnabled(IicPtr->BaseAddress) == FALSE)) {
		return;
	}

	/*
	 * Update interrupt stats and get the contents of the status register.
	 */
	IicPtr->Stats.IicInterrupts++;
	Status = XIic_ReadReg(IicPtr->BaseAddress, XIIC_SR_REG_OFFSET);

	/*
	 * Service requesting interrupt.
	 */
	if (IntrStatus & XIIC_INTR_ARB_LOST_MASK) {
		/* Bus Arbritration Lost */

		IicPtr->Stats.ArbitrationLost++;
		XIic_ArbLostFuncPtr(IicPtr);

		Clear = XIIC_INTR_ARB_LOST_MASK;
	} else if (IntrStatus & XIIC_INTR_TX_ERROR_MASK) {
		/* Transmit errors (no acknowledge) received */
		IicPtr->Stats.TxErrors++;
		TxErrorHandler(IicPtr);

		Clear = XIIC_INTR_TX_ERROR_MASK;
	} else if (IntrStatus & XIIC_INTR_NAAS_MASK) {
		/* Not Addressed As Slave */

		XIic_NotAddrAsSlaveFuncPtr(IicPtr);
		Clear = XIIC_INTR_NAAS_MASK;
	} else if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
		/* Receive register/FIFO is full */

		IicPtr->Stats.RecvInterrupts++;

		if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
			XIic_RecvSlaveFuncPtr(IicPtr);
		} else {
			XIic_RecvMasterFuncPtr(IicPtr);
		}

		Clear = XIIC_INTR_RX_FULL_MASK;
	} else if (IntrStatus & XIIC_INTR_AAS_MASK) {
		/* Addressed As Slave */

		XIic_AddrAsSlaveFuncPtr(IicPtr);
		Clear = XIIC_INTR_AAS_MASK;
	} else if (IntrStatus & XIIC_INTR_BNB_MASK) {
		/* IIC bus has transitioned to not busy */

		/* Check if send callback needs to run */
		if (IicPtr->BNBOnly == TRUE) {
			XIic_BusNotBusyFuncPtr(IicPtr);
			IicPtr->BNBOnly = FALSE;
		} else {
			IicPtr->SendHandler(IicPtr->SendCallBackRef, 0);
		}

		Clear = XIIC_INTR_BNB_MASK;

		/* The bus is not busy, disable BusNotBusy interrupt */
		XIic_DisableIntr(IicPtr->BaseAddress, XIIC_INTR_BNB_MASK);

	} else if ((IntrStatus & XIIC_INTR_TX_EMPTY_MASK) ||
		 (IntrStatus & XIIC_INTR_TX_HALF_MASK)) {
		/* Transmit register/FIFO is empty or � empty */
		IicPtr->Stats.SendInterrupts++;

		if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
			XIic_SendSlaveFuncPtr(IicPtr);
		} else {
			XIic_SendMasterFuncPtr(IicPtr);
		}

		IntrStatus = XIic_ReadIisr(IicPtr->BaseAddress);
		Clear = IntrStatus & (XIIC_INTR_TX_EMPTY_MASK |
					  XIIC_INTR_TX_HALF_MASK);
	}

	/*
	 * Clear Interrupts.
	 */
	XIic_WriteIisr(IicPtr->BaseAddress, Clear);
}