/** * * 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); }
/** * * 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. * * All XIic device interrupts are ORed into one device interrupt. This routine * reads the pending interrupts via the IpIf interface and masks that with the * interrupt mask to evaluate only the interrupts enabled. * ******************************************************************************/ void XIic_InterruptHandler(void *InstancePtr) { u8 Status; u32 IntrStatus; u32 IntrPending; u32 IntrEnable; XIic *IicPtr = NULL; u32 Clear = 0; /* * Verify that each of the inputs are valid. */ XASSERT_VOID(InstancePtr != NULL); /* * Convert the non-typed pointer to an IIC instance pointer */ IicPtr = (XIic *) InstancePtr; /* Get the interrupt Status from the IPIF. There is no clearing of * interrupts in the IPIF. Interrupts must be cleared at the source. * To find which interrupts are pending; AND interrupts pending with * interrupts masked. */ IntrPending = XIIC_READ_IISR(IicPtr->BaseAddress); IntrEnable = XIIC_READ_IIER(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_IS_GINTR_ENABLED(IicPtr->BaseAddress) == FALSE)) { return; } /* Update interrupt stats and get the contents of the status register */ IicPtr->Stats.IicInterrupts++; Status = XIo_In8(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_mDisableIntr(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); } /* Clear Interrupts */ IntrStatus = XIIC_READ_IISR(IicPtr->BaseAddress); Clear = IntrStatus & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK); } XIIC_WRITE_IISR(IicPtr->BaseAddress, Clear); }