/** * This function initiates an interrupt-driven receive in master mode. * * It sets the transfer size register so the slave can send data to us. * The rest of the work is managed by interrupt handler. * * @param InstancePtr is a pointer to the XIicPs instance. * @param MsgPtr is the pointer to the receive buffer. * @param ByteCount is the number of bytes to be received. * @param SlaveAddr is the address of the slave we are receiving from. * * @return None. * * @note This receive routine is for interrupt-driven transfer only. * ****************************************************************************/ void XIicPs_MasterRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, u16 SlaveAddr) { u32 BaseAddr; /* * Assert validates the input arguments. */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(MsgPtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr); BaseAddr = InstancePtr->Config.BaseAddress; InstancePtr->RecvBufferPtr = MsgPtr; InstancePtr->RecvByteCount = ByteCount; InstancePtr->CurrByteCount = ByteCount; InstancePtr->SendBufferPtr = NULL; InstancePtr->IsSend = 0; InstancePtr->UpdateTxSize = 0; if ((ByteCount > XIICPS_DATA_INTR_DEPTH) || (InstancePtr->IsRepeatedStart)) { XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) | XIICPS_CR_HOLD_MASK); } /* * Initialize for a master receiving role. */ XIicPs_SetupMaster(InstancePtr, RECVING_ROLE); /* * Do the address transfer to signal the slave. */ XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); /* * Setup the transfer size register so the slave knows how much * to send to us. */ if (ByteCount > XIICPS_MAX_TRANSFER_SIZE) { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, XIICPS_MAX_TRANSFER_SIZE); InstancePtr->CurrByteCount = XIICPS_MAX_TRANSFER_SIZE; InstancePtr->UpdateTxSize = 1; }else { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, ByteCount); } XIicPs_EnableInterrupts(BaseAddr, XIICPS_IXR_NACK_MASK | XIICPS_IXR_DATA_MASK | XIICPS_IXR_RX_OVR_MASK | XIICPS_IXR_COMP_MASK | XIICPS_IXR_ARB_LOST_MASK); }
/** * This function initiates an interrupt-driven send in master mode. * * It tries to send the first FIFO-full of data, then lets the interrupt * handler to handle the rest of the data if there is any. * * @param InstancePtr is a pointer to the XIicPs instance. * @param MsgPtr is the pointer to the send buffer. * @param ByteCount is the number of bytes to be sent. * @param SlaveAddr is the address of the slave we are sending to. * * @return None. * * @note This send routine is for interrupt-driven transfer only. * ****************************************************************************/ void XIicPs_MasterSend(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount, u16 SlaveAddr) { u32 BaseAddr; u32 Platform = XGetPlatform_Info(); /* * Assert validates the input arguments. */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(MsgPtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr); BaseAddr = InstancePtr->Config.BaseAddress; InstancePtr->SendBufferPtr = MsgPtr; InstancePtr->SendByteCount = ByteCount; InstancePtr->RecvBufferPtr = NULL; InstancePtr->IsSend = 1; /* * Set repeated start if sending more than FIFO of data. */ if (((InstancePtr->IsRepeatedStart) != 0)|| ((ByteCount > XIICPS_FIFO_DEPTH) != 0U)) { XIicPs_WriteReg(BaseAddr, (u32)XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) | (u32)XIICPS_CR_HOLD_MASK); } /* * Setup as a master sending role. */ (void)XIicPs_SetupMaster(InstancePtr, SENDING_ROLE); (void)TransmitFifoFill(InstancePtr); XIicPs_EnableInterrupts(BaseAddr, (u32)XIICPS_IXR_NACK_MASK | (u32)XIICPS_IXR_COMP_MASK | (u32)XIICPS_IXR_ARB_LOST_MASK); /* * Do the address transfer to notify the slave. */ XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, (u32)SlaveAddr); /* Clear the Hold bit in ZYNQ if receive byte count is less than * the FIFO depth to get the completion interrupt properly. */ if ((ByteCount < XIICPS_FIFO_DEPTH) && (Platform == (u32)XPLAT_ZYNQ)) { XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) & (u32)(~XIICPS_CR_HOLD_MASK)); } }
/** * This function initiates an interrupt-driven send in master mode. * * It tries to send the first FIFO-full of data, then lets the interrupt * handler to handle the rest of the data if there is any. * * @param InstancePtr is a pointer to the XIicPs instance. * @param MsgPtr is the pointer to the send buffer. * @param ByteCount is the number of bytes to be sent. * @param SlaveAddr is the address of the slave we are sending to. * * @return None. * * @note This send routine is for interrupt-driven transfer only. * ****************************************************************************/ void XIicPs_MasterSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, u16 SlaveAddr) { u32 BaseAddr; /* * Assert validates the input arguments. */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(MsgPtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr); BaseAddr = InstancePtr->Config.BaseAddress; InstancePtr->SendBufferPtr = MsgPtr; InstancePtr->SendByteCount = ByteCount; InstancePtr->RecvBufferPtr = NULL; InstancePtr->IsSend = 1; /* * Set repeated start if sending more than FIFO of data. */ if ((InstancePtr->IsRepeatedStart) || (ByteCount > XIICPS_FIFO_DEPTH)) { XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) | XIICPS_CR_HOLD_MASK); } /* * Setup as a master sending role. */ XIicPs_SetupMaster(InstancePtr, SENDING_ROLE); /* * Do the address transfer to notify the slave. */ XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); TransmitFifoFill(InstancePtr); XIicPs_EnableInterrupts(BaseAddr, XIICPS_IXR_NACK_MASK | XIICPS_IXR_COMP_MASK | XIICPS_IXR_ARB_LOST_MASK); }
/** * This function initiates a polled mode receive in master mode. * * It repeatedly sets the transfer size register so the slave can * send data to us. It polls the data register for data to come in. * If slave fails to send us data, it fails with time out. * * @param InstancePtr is a pointer to the XIicPs instance. * @param MsgPtr is the pointer to the receive buffer. * @param ByteCount is the number of bytes to be received. * @param SlaveAddr is the address of the slave we are receiving from. * * @return * - XST_SUCCESS if everything went well. * - XST_FAILURE if timed out. * * @note This receive routine is for polled mode transfer only. * ****************************************************************************/ int XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, u16 SlaveAddr) { u32 IntrStatusReg; u32 Intrs; u32 StatusReg; u32 BaseAddr; int IsHold = 0; int UpdateTxSize = 0; /* * Assert validates the input arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(MsgPtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr); BaseAddr = InstancePtr->Config.BaseAddress; InstancePtr->RecvBufferPtr = MsgPtr; InstancePtr->RecvByteCount = ByteCount; if((ByteCount > XIICPS_DATA_INTR_DEPTH) || (InstancePtr->IsRepeatedStart)) { XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) | XIICPS_CR_HOLD_MASK); IsHold = 1; } XIicPs_SetupMaster(InstancePtr, RECVING_ROLE); /* * Clear the interrupt status register before use it to monitor. */ IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); /* * Set up the transfer size register so the slave knows how much * to send to us. */ if (ByteCount > XIICPS_MAX_TRANSFER_SIZE) { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, XIICPS_MAX_TRANSFER_SIZE); ByteCount = XIICPS_MAX_TRANSFER_SIZE; UpdateTxSize = 1; }else { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, ByteCount); } /* * Intrs keeps all the error-related interrupts. */ Intrs = XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_RX_OVR_MASK | XIICPS_IXR_RX_UNF_MASK | XIICPS_IXR_NACK_MASK; /* * Poll the interrupt status register to find the errors. */ IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); while ((InstancePtr->RecvByteCount > 0) && ((IntrStatusReg & Intrs) == 0)) { StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); while (StatusReg & XIICPS_SR_RXDV_MASK) { if ((InstancePtr->RecvByteCount < XIICPS_DATA_INTR_DEPTH) && IsHold && (!(InstancePtr->IsRepeatedStart))) { IsHold = 0; XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) & (~XIICPS_CR_HOLD_MASK)); } XIicPs_RecvByte(InstancePtr); ByteCount --; if (UpdateTxSize && (ByteCount == XIICPS_FIFO_DEPTH + 1)) break; StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); } if (UpdateTxSize && (ByteCount == XIICPS_FIFO_DEPTH + 1)) { /* * wait while fifo is full */ while(XIicPs_ReadReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET) != (ByteCount - XIICPS_FIFO_DEPTH)); if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) > XIICPS_MAX_TRANSFER_SIZE) { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, XIICPS_MAX_TRANSFER_SIZE); ByteCount = XIICPS_MAX_TRANSFER_SIZE + XIICPS_FIFO_DEPTH; }else { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH); UpdateTxSize = 0; ByteCount = InstancePtr->RecvByteCount; } } IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); } if (!(InstancePtr->IsRepeatedStart)) { XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) & (~XIICPS_CR_HOLD_MASK)); } if (IntrStatusReg & Intrs) { return XST_FAILURE; } return XST_SUCCESS; }
/** * This function initiates a polled mode send in master mode. * * It sends data to the FIFO and waits for the slave to pick them up. * If slave fails to remove data from FIFO, the send fails with * time out. * * @param InstancePtr is a pointer to the XIicPs instance. * @param MsgPtr is the pointer to the send buffer. * @param ByteCount is the number of bytes to be sent. * @param SlaveAddr is the address of the slave we are sending to. * * @return * - XST_SUCCESS if everything went well. * - XST_FAILURE if timed out. * * @note This send routine is for polled mode transfer only. * ****************************************************************************/ int XIicPs_MasterSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, u16 SlaveAddr) { u32 IntrStatusReg; u32 StatusReg; u32 BaseAddr; u32 Intrs; /* * Assert validates the input arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(MsgPtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr); BaseAddr = InstancePtr->Config.BaseAddress; InstancePtr->SendBufferPtr = MsgPtr; InstancePtr->SendByteCount = ByteCount; if ((InstancePtr->IsRepeatedStart) || (ByteCount > XIICPS_FIFO_DEPTH)) { XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) | XIICPS_CR_HOLD_MASK); } XIicPs_SetupMaster(InstancePtr, SENDING_ROLE); XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); /* * Intrs keeps all the error-related interrupts. */ Intrs = XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_TX_OVR_MASK | XIICPS_IXR_NACK_MASK; /* * Clear the interrupt status register before use it to monitor. */ IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); /* * Transmit first FIFO full of data. */ TransmitFifoFill(InstancePtr); IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); /* * Continue sending as long as there is more data and * there are no errors. */ while ((InstancePtr->SendByteCount > 0) && ((IntrStatusReg & Intrs) == 0)) { StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); /* * Wait until transmit FIFO is empty. */ if ((StatusReg & XIICPS_SR_TXDV_MASK) != 0) { IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); continue; } /* * Send more data out through transmit FIFO. */ TransmitFifoFill(InstancePtr); } /* * Check for completion of transfer. */ while ((IntrStatusReg & XIICPS_IXR_COMP_MASK) != XIICPS_IXR_COMP_MASK){ IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); /* * If there is an error, tell the caller. */ if ((IntrStatusReg & Intrs) != 0) { return XST_FAILURE; } } if (!(InstancePtr->IsRepeatedStart)) { XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) & (~XIICPS_CR_HOLD_MASK)); } return XST_SUCCESS; }
/** * This function initiates a polled mode receive in master mode. * * It repeatedly sets the transfer size register so the slave can * send data to us. It polls the data register for data to come in. * If slave fails to send us data, it fails with time out. * * @param InstancePtr is a pointer to the XIicPs instance. * @param MsgPtr is the pointer to the receive buffer. * @param ByteCount is the number of bytes to be received. * @param SlaveAddr is the address of the slave we are receiving from. * * @return * - XST_SUCCESS if everything went well. * - XST_FAILURE if timed out. * * @note This receive routine is for polled mode transfer only. * ****************************************************************************/ s32 XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount, u16 SlaveAddr) { u32 IntrStatusReg; u32 Intrs; u32 StatusReg; u32 BaseAddr; s32 BytesToRecv; s32 BytesToRead; s32 TransSize; u32 Status_Rcv; u32 Status; s32 Result; s32 IsHold; s32 UpdateTxSize = 0; s32 ByteCountVar = ByteCount; u32 Platform; /* * Assert validates the input arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(MsgPtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr); BaseAddr = InstancePtr->Config.BaseAddress; InstancePtr->RecvBufferPtr = MsgPtr; InstancePtr->RecvByteCount = ByteCountVar; Platform = XGetPlatform_Info(); if((ByteCountVar > XIICPS_FIFO_DEPTH) || ((InstancePtr->IsRepeatedStart) !=0)) { XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) | (u32)XIICPS_CR_HOLD_MASK); IsHold = 1; } else { IsHold = 0; } (void)XIicPs_SetupMaster(InstancePtr, RECVING_ROLE); /* * Clear the interrupt status register before use it to monitor. */ IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); /* * Set up the transfer size register so the slave knows how much * to send to us. */ if (ByteCountVar > XIICPS_MAX_TRANSFER_SIZE) { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, XIICPS_MAX_TRANSFER_SIZE); ByteCountVar = (s32)XIICPS_MAX_TRANSFER_SIZE; UpdateTxSize = 1; }else { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, ByteCountVar); } /* * Intrs keeps all the error-related interrupts. */ Intrs = (u32)XIICPS_IXR_ARB_LOST_MASK | (u32)XIICPS_IXR_RX_OVR_MASK | (u32)XIICPS_IXR_RX_UNF_MASK | (u32)XIICPS_IXR_NACK_MASK; /* * Poll the interrupt status register to find the errors. */ IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); while ((InstancePtr->RecvByteCount > 0) && ((IntrStatusReg & Intrs) == 0U)) { StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); while ((StatusReg & XIICPS_SR_RXDV_MASK) != 0U) { if (((InstancePtr->RecvByteCount < XIICPS_DATA_INTR_DEPTH) != 0U) && (IsHold != 0) && ((!InstancePtr->IsRepeatedStart) != 0) && (UpdateTxSize == 0)) { IsHold = 0; XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) & (~XIICPS_CR_HOLD_MASK)); } XIicPs_RecvByte(InstancePtr); ByteCountVar --; if (Platform == (u32)XPLAT_ZYNQ) { if ((UpdateTxSize != 0) && (ByteCountVar == (XIICPS_FIFO_DEPTH + 1))) { break; } } StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); } if (Platform == (u32)XPLAT_ZYNQ) { if ((UpdateTxSize != 0) && (ByteCountVar == (XIICPS_FIFO_DEPTH + 1))) { /* wait while fifo is full */ while (XIicPs_ReadReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET) != (u32)(ByteCountVar - XIICPS_FIFO_DEPTH)) { ; } if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) > XIICPS_MAX_TRANSFER_SIZE) { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, XIICPS_MAX_TRANSFER_SIZE); ByteCountVar = (s32)XIICPS_MAX_TRANSFER_SIZE + XIICPS_FIFO_DEPTH; } else { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH); UpdateTxSize = 0; ByteCountVar = InstancePtr->RecvByteCount; } } } else { if ((InstancePtr->RecvByteCount > 0) && (ByteCountVar == 0)) { /* * Clear the interrupt status register before use it to * monitor. */ IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); if ((InstancePtr->RecvByteCount) > XIICPS_MAX_TRANSFER_SIZE) { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, XIICPS_MAX_TRANSFER_SIZE); ByteCountVar = (s32)XIICPS_MAX_TRANSFER_SIZE; } else { XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, InstancePtr->RecvByteCount); UpdateTxSize = 0; ByteCountVar = InstancePtr->RecvByteCount; } } } IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); } if ((!(InstancePtr->IsRepeatedStart)) != 0) { XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) & (~XIICPS_CR_HOLD_MASK)); } if ((IntrStatusReg & Intrs) != 0x0U) { Result = (s32)XST_FAILURE; } else { Result = (s32)XST_SUCCESS; } return Result; }