Xuint8 XI2c_SlaveAccess(Xuint32 BaseAddress, Xuint8 SlaveAddress, Xuint8 *BufferPtr) { Xuint8 CtrlReg, StatusReg, SlaveSendFlag, DeviceAddress; Xuint8 IntrStatus, count = 0; XI2c_mClearTXFifo(BaseAddress); /** Set the device slave address **/ DeviceAddress = SlaveAddress << 1; XIo_Out8(BaseAddress + XIIC_ADR_REG_OFFSET, DeviceAddress); /** Wait until the device is addressed as slave **/ do { IntrStatus = XIIF_V123B_READ_IISR(BaseAddress); } while(!(IntrStatus & XIIC_INTR_AAS_MASK)); XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, 0); /** Clear the recieve-fifo interrupt register **/ XI2c_mClearIisr(BaseAddress, XIIC_INTR_RX_FULL_MASK); /** Read the status register to see if we need to receive or send data **/ StatusReg = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET); XI2c_mClearIisr(BaseAddress, XIIC_INTR_NAAS_MASK | XIIC_INTR_BNB_MASK); SlaveSendFlag = StatusReg & XIIC_SR_MSTR_RDING_SLAVE_MASK; if( SlaveSendFlag ) { SlaveSendData(BaseAddress, BufferPtr); } else { SlaveRecvData(BaseAddress, BufferPtr); } XI2c_mClearIisr(BaseAddress, XIIC_INTR_AAS_MASK); return 1; } // XI2c_SlaveAccess()
/** * The interrupt handler for slave mode. It does the protocol handling for * the interrupt-driven transfers. * * Completion events and errors are signaled to upper layer for proper * handling. * * <pre> * * The interrupts that are handled are: * - DATA * If the instance is sending, it means that the master wants to read more * data from us. Send more data, and check whether we are done with this * send. * * If the instance is receiving, it means that the master has writen * more data to us. Receive more data, and check whether we are done with * with this receive. * * - COMP * This marks that stop sequence has been sent from the master, transfer * is about to terminate. However, for receiving, the master may have * written us some data, so receive that first. * * It is an error if the amount of transfered data is less than expected. * * - NAK * This marks that master does not want our data. It is for send only. * * - Other interrupts * These interrupts are marked as error. * * </pre> * * @param InstancePtr is a pointer to the XIicPs instance. * * @return None. * * @note None. * ****************************************************************************/ void XIicPs_SlaveInterruptHandler(XIicPs *InstancePtr) { u32 IntrStatusReg; u32 IsSend = 0U; u32 StatusEvent = 0U; s32 LeftOver; u32 BaseAddr; /* * Assert validates the input arguments. */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); BaseAddr = InstancePtr->Config.BaseAddress; /* * Read the Interrupt status register. */ IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); /* * Write the status back to clear the interrupts so no events are missed * while processing this interrupt. */ XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); /* * Use the Mask register AND with the Interrupt Status register so * disabled interrupts are not processed. */ IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET)); /* * Determine whether the device is sending. */ if (InstancePtr->RecvBufferPtr == NULL) { IsSend = 1U; } /* Data interrupt * * This means master wants to do more data transfers. * Also check for completion of transfer, signal upper layer if done. */ if ((u32)0U != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) { if (IsSend != 0x0U) { LeftOver = TransmitFifoFill(InstancePtr); /* * We may finish send here */ if (LeftOver == 0) { StatusEvent |= XIICPS_EVENT_COMPLETE_SEND; } } else { LeftOver = SlaveRecvData(InstancePtr); /* We may finish the receive here */ if (LeftOver == 0) { StatusEvent |= XIICPS_EVENT_COMPLETE_RECV; } } } /* * Complete interrupt. * * In slave mode, it means the master has done with this transfer, so * we signal the application using completion event. */ if (0U != (IntrStatusReg & XIICPS_IXR_COMP_MASK)) { if (IsSend != 0x0U) { if (InstancePtr->SendByteCount > 0) { StatusEvent |= XIICPS_EVENT_ERROR; }else { StatusEvent |= XIICPS_EVENT_COMPLETE_SEND; } } else { LeftOver = SlaveRecvData(InstancePtr); if (LeftOver > 0) { StatusEvent |= XIICPS_EVENT_ERROR; } else { StatusEvent |= XIICPS_EVENT_COMPLETE_RECV; } } } /* * Nack interrupt, pass this information to application. */ if (0U != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) { StatusEvent |= XIICPS_EVENT_NACK; } /* * All other interrupts are treated as error. */ if (0U != (IntrStatusReg & (XIICPS_IXR_TO_MASK | XIICPS_IXR_RX_UNF_MASK | XIICPS_IXR_TX_OVR_MASK | XIICPS_IXR_RX_OVR_MASK))){ StatusEvent |= XIICPS_EVENT_ERROR; } /* * Signal application if there are any events. */ if (0U != StatusEvent) { InstancePtr->StatusHandler(InstancePtr->CallBackRef, StatusEvent); } }