示例#1
0
/**
*
* This function sets the options for the IIC device driver. The options control
* how the device behaves relative to the IIC bus. If an option applies to
* how messages are sent or received on the IIC bus, it must be set prior to
* calling functions which send or receive data.
*
* To set multiple options, the values must be ORed together. To not change
* existing options, read/modify/write with the current options using
* XIic_GetOptions().
*
* <b>USAGE EXAMPLE:</b>
*
* Read/modify/write to enable repeated start:
* <pre>
*   u8 Options;
*   Options = XIic_GetOptions(&Iic);
*   XIic_SetOptions(&Iic, Options | XII_REPEATED_START_OPTION);
* </pre>
*
* Disabling General Call:
* <pre>
*   Options = XIic_GetOptions(&Iic);
*   XIic_SetOptions(&Iic, Options &= ~XII_GENERAL_CALL_OPTION);
* </pre>
*
* @param    InstancePtr is a pointer to the XIic instance to be worked on.
*
* @param    NewOptions are the options to be set.  See xiic.h for a list of
*           the available options.
*
* @return
*
* None.
*
* @note
*
* Sending or receiving messages with repeated start enabled, and then
* disabling repeated start, will not take effect until another master
* transaction is completed. i.e. After using repeated start, the bus will
* continue to be throttled after repeated start is disabled until a master
* transaction occurs allowing the IIC to release the bus.
* <br><br>
* Options enabled will have a 1 in its appropriate bit position.
*
****************************************************************************/
void XIic_SetOptions(XIic * InstancePtr, u32 NewOptions)
{
	u8 CntlReg;

	XASSERT_VOID(InstancePtr != NULL);

	XIic_mEnterCriticalRegion(InstancePtr->BaseAddress);

	/* Update the options in the instance and get the contents of the control
	 * register such that the general call option can be modified
	 */
	InstancePtr->Options = NewOptions;
	CntlReg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);

	/* The general call option is the only option that maps directly to
	 * a hardware register feature
	 */
	if (NewOptions & XII_GENERAL_CALL_OPTION) {
		CntlReg |= XIIC_CR_GENERAL_CALL_MASK;
	}
	else {
		CntlReg &= ~XIIC_CR_GENERAL_CALL_MASK;
	}

	/* Write the new control register value to the register */

	XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET, CntlReg);

	XIic_mExitCriticalRegion(InstancePtr->BaseAddress);
}
示例#2
0
/**
* This function receives data as a master from a slave device on the IIC bus.
* If the bus is busy, it will indicate so and then enable an interrupt such
* that the status handler will be called when the bus is no longer busy.  The
* slave address which has been set with the XIic_SetAddress() function is the
* address from which data is received. Receiving data on the bus performs a
* read operation.
*
* @param    InstancePtr is a pointer to the Iic instance to be worked on.
* @param    RxMsgPtr is a pointer to the data to be transmitted
* @param    ByteCount is the number of message bytes to be sent
*
* @return
*
* - XST_SUCCESS indicates the message reception processes has been initiated.
* - XST_IIC_BUS_BUSY indicates the bus was in use and that the BusNotBusy
*   interrupt is enabled which will update the EventStatus when the bus is no
*   longer busy.
* - XST_IIC_GENERAL_CALL_ADDRESS indicates the slave address is set to the
*   the general call address. This is not allowed for Master receive mode.
*
* @internal
*
* The receive FIFO threshold is a zero based count such that 1 must be
* subtracted from the desired count to get the correct value. When receiving
* data it is also necessary to not receive the last byte with the prior bytes
* because the acknowledge must be setup before the last byte is received.
*
******************************************************************************/
XStatus XIic_MasterRecv(XIic * InstancePtr, u8 * RxMsgPtr, int ByteCount)
{
	u8 CntlReg;
	u8 Temp;

	/* If the slave address is zero (general call) the master can't perform
	 * receive operations, indicate an error
	 */
	if (InstancePtr->AddrOfSlave == 0) {
		return XST_IIC_GENERAL_CALL_ADDRESS;
	}

	XIic_mEnterCriticalRegion(InstancePtr->BaseAddress);

	/* Ensure that the master processing has been included such that events
	 * will be properly handled
	 */
	XIIC_MASTER_INCLUDE;
	InstancePtr->IsDynamic = FALSE;
	/*
	 * If the busy is busy, then exit the critical region and wait for the
	 * bus to not be busy, the function enables the bus not busy interrupt
	 */
	if (IsBusBusy(InstancePtr)) {
		XIic_mExitCriticalRegion(InstancePtr->BaseAddress);

		return XST_IIC_BUS_BUSY;
	}

	/* Save message state for event driven processing
	 */
	InstancePtr->RecvByteCount = ByteCount;
	InstancePtr->RecvBufferPtr = RxMsgPtr;

	/* Clear and enable Rx full interrupt if using 7 bit, If 10 bit, wait until
	 * last address byte sent incase arbitration gets lost while sending out
	 * address.
	 */
	if ((InstancePtr->Options & XII_SEND_10_BIT_OPTION) == 0) {
		XIic_mClearEnableIntr(InstancePtr->BaseAddress,
				      XIIC_INTR_RX_FULL_MASK);
	}

	/* If already a master on the bus, the direction was set by Rx Interrupt
	 * routine to tx which is throttling bus because during Rxing, Tx reg is
	 * empty = throttle. CR needs setting before putting data or the address
	 * written will go out as Tx instead of receive. Start Master Rx by setting
	 * CR Bits MSMS to Master and msg direction.
	 */
	CntlReg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);

	if (CntlReg & XIIC_CR_MSMS_MASK) {
		CntlReg |= XIIC_CR_REPEATED_START_MASK;
		XIic_mSetControlRegister(InstancePtr, CntlReg, ByteCount);

		InstancePtr->Stats.RepeatedStarts++;	/* increment stats counts */
		XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET,
			 CntlReg);

	}

	/* Set receive FIFO occupancy depth which must be done prior to writing the
	 * address in the FIFO because the transmitter will immediatedly start when
	 * in repeated start mode followed by the receiver such that the number of
	 * bytes to receive should be set 1st.
	 */
	if (ByteCount == 1) {
		Temp = 0;
	} else {
		if (ByteCount <= IIC_RX_FIFO_DEPTH) {
			Temp = ByteCount - 2;
		} else {
			Temp = IIC_RX_FIFO_DEPTH - 1;
		}
	}
	XIo_Out8(InstancePtr->BaseAddress + XIIC_RFD_REG_OFFSET, Temp);

	if (InstancePtr->Options & XII_SEND_10_BIT_OPTION) {
		/* Send the 1st and 2nd byte of the 10 bit address of a write
		 * operation, write because it's a 10 bit address
		 */
		XIic_mSend10BitAddrByte1(InstancePtr->AddrOfSlave,
					 XIIC_WRITE_OPERATION);
		XIic_mSend10BitAddrByte2(InstancePtr->AddrOfSlave);

		/* Set flag to indicate the next byte of the address needs to be
		 * send, clear and enable tx empty interrupt
		 */
		InstancePtr->TxAddrMode = XIIC_TX_ADDR_MSTR_RECV_MASK;
		XIic_mClearEnableIntr(InstancePtr->BaseAddress,
				      XIIC_INTR_TX_EMPTY_MASK);
	} else {
		/* 7 bit slave address, send the address for a read operation
		 * and set the state to indicate the address has been sent
		 */
		XIic_mSend7BitAddr(InstancePtr->AddrOfSlave,
				   XIIC_READ_OPERATION);
		InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;
	}

	/* 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_mClearEnableIntr(InstancePtr->BaseAddress,
			      XIIC_INTR_TX_ERROR_MASK);

	/*  When repeated start not used, MSMS gets set after putting data
	 *  in Tx reg. Start Master Rx by setting CR Bits MSMS to Master and
	 *  msg direction.
	 */
	CntlReg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);
	if ((CntlReg & XIIC_CR_MSMS_MASK) == 0) {
		CntlReg |= XIIC_CR_MSMS_MASK;
		XIic_mSetControlRegister(InstancePtr, CntlReg, ByteCount);
		XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET,
			 CntlReg);
	}

	XIic_mExitCriticalRegion(InstancePtr->BaseAddress);

	return XST_SUCCESS;
}
示例#3
0
/**
* This function sends data as a master on the IIC bus. If the bus is busy, it
* will indicate so and then enable an interrupt such that the status handler
* will be called when the bus is no longer busy.  The slave address which has
* been set with the XIic_SetAddress() function is the address to which the
* specific data is sent.  Sending data on the bus performs a write operation.
*
* @param    InstancePtr points to the Iic instance to be worked on.
* @param    TxMsgPtr points to the data to be transmitted
* @param    ByteCount is the number of message bytes to be sent
*
* @return
*
* - XST_SUCCESS indicates the message transmission has been initiated.
* - XST_IIC_BUS_BUSY indicates the bus was in use and that the BusNotBusy
*   interrupt is enabled which will update the EventStatus when the bus is no
*   longer busy.
*
* @note
*
* None
*
******************************************************************************/
XStatus XIic_MasterSend(XIic * InstancePtr, u8 * TxMsgPtr, int ByteCount)
{
	u8 CntlReg;

	XIic_mEnterCriticalRegion(InstancePtr->BaseAddress);

	/* Ensure that the master processing has been included such that events
	 * will be properly handled
	 */
	XIIC_MASTER_INCLUDE;
	InstancePtr->IsDynamic = FALSE;

	/*
	 * If the busy is busy, then exit the critical region and wait for the
	 * bus to not be busy, the function enables the bus not busy interrupt
	 */
	if (IsBusBusy(InstancePtr)) {
		XIic_mExitCriticalRegion(InstancePtr->BaseAddress);

		return XST_IIC_BUS_BUSY;
	}

	/* If it is already a master on the bus (repeated start), the direction was
	 * set to tx which is throttling bus.  The control register needs to be set
	 * before putting data into the FIFO
	 */
	CntlReg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);

	if (CntlReg & XIIC_CR_MSMS_MASK) {
		CntlReg &= ~XIIC_CR_NO_ACK_MASK;
		CntlReg |=
		    (XIIC_CR_DIR_IS_TX_MASK | XIIC_CR_REPEATED_START_MASK);

		XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET,
			 CntlReg);
		InstancePtr->Stats.RepeatedStarts++;
	}

	/* Save message state
	 */
	InstancePtr->SendByteCount = ByteCount;
	InstancePtr->SendBufferPtr = TxMsgPtr;

	/* Put the address into the FIFO to be sent and indicate that the operation
	 * to be performed on the bus is a write operation, a general call address
	 * handled the same as a 7 bit address even if 10 bit address is selected
	 * Set the transmit address state to indicate the address has been sent
	 */
	if ((InstancePtr->Options & XII_SEND_10_BIT_OPTION) &&
	    (InstancePtr->AddrOfSlave != 0)) {
		XIic_mSend10BitAddrByte1(InstancePtr->AddrOfSlave,
					 XIIC_WRITE_OPERATION);
		XIic_mSend10BitAddrByte2(InstancePtr->AddrOfSlave);
	} else {
		XIic_mSend7BitAddr(InstancePtr->AddrOfSlave,
				   XIIC_WRITE_OPERATION);
	}
	/* Set the transmit address state to indicate the address has been sent
	 * for communication with event driven processing
	 */
	InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;

	/* Fill remaining available FIFO with message data
	 */
	if (InstancePtr->SendByteCount > 1) {
		XIic_TransmitFifoFill(InstancePtr, XIIC_MASTER_ROLE);
	}

	/* After filling fifo, if data yet to send > 1, enable Tx ½ empty interrupt
	 */
	if (InstancePtr->SendByteCount > 1) {
		XIic_mClearEnableIntr(InstancePtr->BaseAddress,
				      XIIC_INTR_TX_HALF_MASK);
	}

	/* Clear any pending Tx empty, Tx Error and then enable them.
	 */
	XIic_mClearEnableIntr(InstancePtr->BaseAddress,
			      XIIC_INTR_TX_ERROR_MASK |
			      XIIC_INTR_TX_EMPTY_MASK);

	/* When repeated start not used, MSMS must be set after putting data into
	 * transmit FIFO, start the transmitter
	 */

	CntlReg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);
	if ((CntlReg & XIIC_CR_MSMS_MASK) == 0) {
		CntlReg &= ~XIIC_CR_NO_ACK_MASK;
		CntlReg |= XIIC_CR_MSMS_MASK | XIIC_CR_DIR_IS_TX_MASK;
		XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET,
			 CntlReg);
	}

	XIic_mExitCriticalRegion(InstancePtr->BaseAddress);

	return XST_SUCCESS;
}