/** * Receive data as a master on the IIC bus. This function receives the data * using polled I/O and blocks until the data has been received. It only * supports 7 bit addressing and non-repeated start modes of operation. The * user is responsible for ensuring the bus is not busy if multiple masters * are present on the bus. * * @param BaseAddress contains the base address of the IIC device. * @param Address contains the 7 bit IIC address of the device to send the * specified data to. * @param BufferPtr points to the data to be sent. * @param ByteCount is the number of bytes to be sent. * * @return * * The number of bytes received. * * @note * * None * ******************************************************************************/ unsigned XIic_Recv(u32 BaseAddress, u8 Address, u8 * BufferPtr, unsigned ByteCount) { u8 CntlReg; unsigned RemainingByteCount; /* Tx error is enabled incase the address (7 or 10) has no device to answer * with Ack. When only one byte of data, must set NO ACK before address goes * out therefore Tx error must not be enabled as it will go off immediately * and the Rx full interrupt will be checked. If full, then the one byte * was received and the Tx error will be disabled without sending an error * callback msg. */ XIic_mClearIisr(BaseAddress, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_ARB_LOST_MASK); /* Set receive FIFO occupancy depth for 1 byte (zero based) */ XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, 0); /* 7 bit slave address, send the address for a read operation * and set the state to indicate the address has been sent */ XIic_mSend7BitAddress(BaseAddress, Address, XIIC_READ_OPERATION); /* MSMS gets set after putting data in FIFO. Start the master receive * operation by setting CR Bits MSMS to Master, if the buffer is only one * byte, then it should not be acknowledged to indicate the end of data */ CntlReg = XIIC_CR_MSMS_MASK | XIIC_CR_ENABLE_DEVICE_MASK; if (ByteCount == 1) { CntlReg |= XIIC_CR_NO_ACK_MASK; } /* Write out the control register to start receiving data and call the * function to receive each byte into the buffer */ XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CntlReg); /* Clear the latched interrupt status for the bus not busy bit which must * be done while the bus is busy */ XIic_mClearIisr(BaseAddress, XIIC_INTR_BNB_MASK); /* Try to receive the data from the IIC bus */ RemainingByteCount = RecvData(BaseAddress, BufferPtr, ByteCount); /* * The receive is complete, disable the IIC device and return the number of * bytes that was received */ XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, 0); /* Return the number of bytes that was received */ return ByteCount - RemainingByteCount; }
/** * Send data as a master on the IIC bus. This function sends the data * using polled I/O and blocks until the data has been sent. It only supports * 7 bit addressing and non-repeated start modes of operation. The user is * responsible for ensuring the bus is not busy if multiple masters are present * on the bus. * * @param BaseAddress contains the base address of the IIC device. * @param Address contains the 7 bit IIC address of the device to send the * specified data to. * @param BufferPtr points to the data to be sent. * @param ByteCount is the number of bytes to be sent. * * @return * * The number of bytes sent. * * @note * * None * ******************************************************************************/ unsigned XIic_Send(u32 BaseAddress, u8 Address, u8 * BufferPtr, unsigned ByteCount) { unsigned RemainingByteCount; /* Put the address into the FIFO to be sent and indicate that the operation * to be performed on the bus is a write operation */ XIic_mSend7BitAddress(BaseAddress, Address, XIIC_WRITE_OPERATION); /* Clear the latched interrupt status so that it will be updated with the * new state when it changes, this must be done after the address is put * in the FIFO */ XIic_mClearIisr(BaseAddress, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_ARB_LOST_MASK); /* MSMS must be set after putting data into transmit FIFO, indicate the * direction is transmit, this device is master and enable the IIC device */ XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, XIIC_CR_MSMS_MASK | XIIC_CR_DIR_IS_TX_MASK | XIIC_CR_ENABLE_DEVICE_MASK); /* Clear the latched interrupt * status for the bus not busy bit which must be done while the bus is busy */ XIic_mClearIisr(BaseAddress, XIIC_INTR_BNB_MASK); /* Send the specified data to the device on the IIC bus specified by the * the address */ RemainingByteCount = SendData(BaseAddress, BufferPtr, ByteCount); /* * The send is complete, disable the IIC device and return the number of * bytes that was sent */ XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, 0); return ByteCount - RemainingByteCount; }
/** * Send data as a master on the IIC bus. This function sends the data * using polled I/O and blocks until the data has been sent. It only supports * 7 bit addressing mode of operation. The user is responsible for ensuring * the bus is not busy if multiple masters are present on the bus. * * @param BaseAddress contains the base address of the IIC device. * @param Address contains the 7 bit IIC address of the device to send the * specified data to. * @param BufferPtr points to the data to be sent. * @param ByteCount is the number of bytes to be sent. * @param Option indicates whether to hold or free the bus after * transmitting the data. * * @return * * The number of bytes sent. * * @note * * None * ******************************************************************************/ unsigned XIic_Send(u32 BaseAddress, u8 Address, u8 *BufferPtr, unsigned ByteCount, u8 Option) { unsigned RemainingByteCount; u8 ControlReg; volatile u8 StatusReg; /* Check to see if already Master on the Bus. * If Repeated Start bit is not set send Start bit by setting MSMS bit else * Send the address. */ ControlReg = XIo_In8(BaseAddress + XIIC_CR_REG_OFFSET); if ((ControlReg & XIIC_CR_REPEATED_START_MASK) == 0) { /* Put the address into the FIFO to be sent and indicate that the operation * to be performed on the bus is a write operation */ XIic_mSend7BitAddress(BaseAddress, Address, XIIC_WRITE_OPERATION); /* Clear the latched interrupt status so that it will be updated with the * new state when it changes, this must be done after the address is put * in the FIFO */ XIic_mClearIisr(BaseAddress, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_ARB_LOST_MASK); /* MSMS must be set after putting data into transmit FIFO, indicate the * direction is transmit, this device is master and enable the IIC device */ XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, XIIC_CR_MSMS_MASK | XIIC_CR_DIR_IS_TX_MASK | XIIC_CR_ENABLE_DEVICE_MASK); /* Clear the latched interrupt * status for the bus not busy bit which must be done while the bus is busy */ StatusReg = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET); while ((StatusReg & XIIC_SR_BUS_BUSY_MASK) == 0) { StatusReg = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET); } XIic_mClearIisr(BaseAddress, XIIC_INTR_BNB_MASK); } else { /* Already owns the Bus indicating that its a Repeated Start call. * 7 bit slave address, send the address for a write operation * and set the state to indicate the address has been sent */ XIic_mSend7BitAddress(BaseAddress, Address, XIIC_WRITE_OPERATION); } /* Send the specified data to the device on the IIC bus specified by the * the address */ RemainingByteCount = SendData(BaseAddress, BufferPtr, ByteCount, Option); ControlReg = XIo_In8(BaseAddress + XIIC_CR_REG_OFFSET); if ((ControlReg & XIIC_CR_REPEATED_START_MASK) == 0) { /* The Transmission is completed, disable the IIC device if the Option * is to release the Bus after transmission of data and return the number * of bytes that was received. Only wait if master, if addressed as slave * just reset to release the bus. */ if ((ControlReg & XIIC_CR_MSMS_MASK) != 0) { XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, (ControlReg & ~XIIC_CR_MSMS_MASK)); StatusReg = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET); while ((StatusReg & XIIC_SR_BUS_BUSY_MASK) != 0) { StatusReg = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET); } } XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, 0); } return ByteCount - RemainingByteCount; }