예제 #1
0
/**
*
* This function stops the IIC device and driver such that data is no longer
* sent or received on the IIC bus. This function stops the device by
* disabling interrupts. This function only disables interrupts within the
* device such that the caller is responsible for disconnecting the interrupt
* handler of the device from the interrupt source and disabling interrupts
* at other levels.
*
* Due to bus throttling that could hold the bus between messages when using
* repeated start option, stop will not occur when the device is actively
* sending or receiving data from the IIC bus or the bus is being throttled
* by this device, but instead return XST_IIC_BUS_BUSY.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return
*		- XST_SUCCESS indicates all IIC interrupts are disabled.
*		No messages can be received or transmitted until XIic_Start()
*		is called.
*		- XST_IIC_BUS_BUSY indicates this device is currently engaged
*		in message traffic and cannot be stopped.
*
* @note		None.
*
****************************************************************************/
int XIic_Stop(XIic *InstancePtr)
{
	u32 Status;
	u32 CntlReg;

	Xil_AssertNonvoid(InstancePtr != NULL);

	/*
	 * Disable all interrupts globally.
	 */
	XIic_IntrGlobalDisable(InstancePtr->BaseAddress);

	CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
	Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);

	if ((CntlReg & XIIC_CR_MSMS_MASK) ||
		(Status & XIIC_SR_ADDR_AS_SLAVE_MASK)) {
		/*
		 * When this device is using the bus
		 * - re-enable interrupts to finish current messaging
		 * - return bus busy
		 */
		XIic_IntrGlobalEnable(InstancePtr->BaseAddress);

		return XST_IIC_BUS_BUSY;
	}

	InstancePtr->IsStarted = 0;

	return XST_SUCCESS;
}
예제 #2
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)
{
	u32 CntlReg;

	Xil_AssertVoid(InstancePtr != NULL);

	XIic_IntrGlobalDisable(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 = XIic_ReadReg(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.
	 */
	XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET, CntlReg);

	XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
}
/**
*
* Runs a limited self-test on the driver/device. This test does a read/write
* test of the Interrupt Registers There is no loopback capabilities for the
* device such that this test does not send or receive data.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return
*		- XST_SUCCESS if no errors are found
*		- XST_FAILURE if errors are found
*
* @note		None.
*
****************************************************************************/
int XIic_SelfTest(XIic *InstancePtr)
{
	int Status = XST_SUCCESS;
	int GlobalIntrStatus;
	u32 IntrEnableStatus;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/*
	 * Store the Global Interrupt Register and the Interrupt Enable Register
	 * contents.
	 */
	GlobalIntrStatus = XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress);
	IntrEnableStatus = XIic_ReadIier(InstancePtr->BaseAddress);

	/*
	 * Reset the device so it's in a known state and the default state of
	 * the interrupt registers can be tested.
	 */
	XIic_Reset(InstancePtr);

	if (XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress)!= 0) {
		Status = XST_FAILURE;
	}

	if (XIic_ReadIier(InstancePtr->BaseAddress)!= 0) {
		Status = XST_FAILURE;
	}

	/*
	 * Test Read/Write to the Interrupt Enable register.
	 */
	XIic_WriteIier(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
	if (XIic_ReadIier(InstancePtr->BaseAddress)!= XIIC_TX_RX_INTERRUPTS) {
		Status = XST_FAILURE;
	}

	/*
	 * Reset device to remove the affects of the previous test.
	 */
	XIic_Reset(InstancePtr);

	/*
	 * Restore the Global Interrupt Register and the Interrupt Enable
	 * Register contents.
	 */
	if (GlobalIntrStatus == TRUE) {
		XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
	}
	XIic_WriteIier(InstancePtr->BaseAddress, IntrEnableStatus);

	return Status;
}
/**
*
* This function sends data as a slave on the IIC bus and should not be called
* until an event has occurred that indicates the device has been selected by
* a master attempting read from the slave (XII_MASTER_READ_EVENT).
*
* If more data is received than specified a No Acknowledge will be sent to
* signal the Master to stop sending data. Any received data is read to prevent
* the slave device from throttling the bus.
*
* @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 transmission has been
*		initiated.
*		- XST_IIC_NOT_SLAVE indicates the device has not been selected
*		to be a slave on the IIC bus such that data cannot be received.
*
* @internal
*
* The master signals the message completion differently depending on the
* repeated start options.
*
* When the master is not using repeated start:
*  - Not Adressed As Slave NAAS interrupt signals the master has sent a stop
*    condition and is no longer sending data. This doesn't imply that the master
*    will not send a No Ack. It covers when the master fails to send No
*    Ackowledge before releasing the bus.
*  - Tx Error interrupt signals end of message.
*
* When the master is using repeated start:
*  - the Tx Error interrupt signals the master finished sending the msg.
*  - NAAS interrupt will not signal when message is complete as the
*    master may want to write or read another message with this device.
*
* To prevent throttling, the slave must contine to read discard the data
* when the receive buffer is full. When unexpected bytes are received, No Ack
* must be set and the Rx buffer continually read until either NAAS
* or Bus Not Busy BND interrupt signals the master is no longer
* interacting with this slave. At this point the Ack is set to ON allowing
* this device to acknowlefge the an address sent to it for the next
* slave message.
*
* The slave will always receive 1 byte before the bus is throttled causing a
* receive pending interrupt before this routine is executed. After one byte
* the bus will throttle. The depth is set to the proper amount immediatelly
* allowing the master to send more bytes and then to again throttle, but at the
* proper fifo depth. The interrupt is a level. Clearing and enabling will cause
* the Rx interrupt to pend at the correct level.
*
******************************************************************************/
int XIic_SlaveRecv(XIic *InstancePtr, u8 *RxMsgPtr, int ByteCount)
{
    u32 Status;

    /*
     * If the device is not a slave on the IIC bus then indicate an error
     * because data cannot be received on the bus.
     */
    Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
    if ((Status & XIIC_SR_ADDR_AS_SLAVE_MASK) == 0) {
        return XST_IIC_NOT_SLAVE;
    }

    XIic_IntrGlobalDisable(InstancePtr->BaseAddress);

    /*
     * Save message state and invalidate the send buffer pointer to indicate
     * the direction of transfer is receive.
     */
    InstancePtr->RecvByteCount = ByteCount;
    InstancePtr->RecvBufferPtr = RxMsgPtr;
    InstancePtr->SendBufferPtr = NULL;

    /*
     * Set receive FIFO occupancy depth so the Rx interrupt will occur
     * when all bytes received or if more bytes than will fit in FIFO,
     * set to max depth.
     */
    if (ByteCount > IIC_RX_FIFO_DEPTH) {
        XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET,
                      IIC_RX_FIFO_DEPTH - 1);
    } else {
        XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET,
                      ByteCount - 1);
    }

    /*
     * Clear and enable receive full interrupt except when the bytes to
     * receive is only 1, don't clear interrupt as it is the only one your
     * going to get.
     */
    if (ByteCount > 1) {
        XIic_ClearIntr(InstancePtr->BaseAddress,
                       XIIC_INTR_RX_FULL_MASK);
    }

    XIic_EnableIntr(InstancePtr->BaseAddress, XIIC_INTR_RX_FULL_MASK);

    XIic_IntrGlobalEnable(InstancePtr->BaseAddress);

    return XST_SUCCESS;
}
/**
*
* This function sends data as a slave on the IIC bus and should not be called
* until an event has occurred that indicates the device has been selected by
* a master attempting read from the slave (XII_MASTER_READ_EVENT).
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
* @param	TxMsgPtr 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 transmission has been
*		initiated.
*		- XST_IIC_NOT_SLAVE indicates the device has not been
*		selected to be a slave on the IIC bus such that data
*		cannot be sent.
*
* @note		None.
*
******************************************************************************/
int XIic_SlaveSend(XIic *InstancePtr, u8 *TxMsgPtr, int ByteCount)
{
    u32 IntrStatus;
    u32 Status;

    /*
     * If the device is not a slave on the IIC bus then indicate an error
     * because data cannot be sent on the bus.
     */
    Status = XIic_ReadReg(InstancePtr->BaseAddress,  XIIC_SR_REG_OFFSET);
    if ((Status & XIIC_SR_ADDR_AS_SLAVE_MASK) == 0) {
        return XST_IIC_NOT_SLAVE;
    }

    XIic_IntrGlobalDisable(InstancePtr->BaseAddress);

    /*
     * Save message state and invalidate the receive buffer pointer to
     * indicate the direction of transfer is sending.
     */
    InstancePtr->SendByteCount = ByteCount;
    InstancePtr->SendBufferPtr = TxMsgPtr;
    InstancePtr->RecvBufferPtr = NULL;

    /*
     * Start sending the specified data and then interrupt processing will
     * complete it.
     */
    XIic_TransmitFifoFill(InstancePtr, XIIC_SLAVE_ROLE);

    /* Clear any pending Tx empty, Tx Error and interrupt then enable them.
     * The Tx error interrupt indicates when the message is complete.
     * If data remaining to be sent, clear and enable Tx ½ empty interrupt.
     */
    IntrStatus = (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK);
    if (InstancePtr->SendByteCount > 1) {
        IntrStatus |= XIIC_INTR_TX_HALF_MASK;
    }

    /*
     * Clear the interrupts in the status and then enable them and then
     * exit the critical region.
     */
    XIic_ClearEnableIntr(InstancePtr->BaseAddress, IntrStatus);

    XIic_IntrGlobalEnable(InstancePtr->BaseAddress);

    return XST_SUCCESS;
}
예제 #6
0
/**
*
* This function starts the IIC device and driver by enabling the proper
* interrupts such that data may be sent and received on the IIC bus.
* This function must be called before the functions to send and receive data.
*
* Before XIic_Start() is called, the interrupt control must connect the ISR
* routine to the interrupt handler. This is done by the user, and not
* XIic_Start() to allow the user to use an interrupt controller of their choice.
*
* Start enables:
*  - IIC device
*  - Interrupts:
*	 - Addressed as slave to allow messages from another master
*	 - Arbitration Lost to detect Tx arbitration errors
*	 - Global IIC interrupt
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	XST_SUCCESS always.
*
* @note
*
* The device interrupt is connected to the interrupt controller, but no
* "messaging" interrupts are enabled. Addressed as Slave is enabled to
* reception of messages when this devices address is written to the bus.
* The correct messaging interrupts are enabled when sending or receiving
* via the IicSend() and IicRecv() functions. No action is required
* by the user to control any IIC interrupts as the driver completely
* manages all 8 interrupts. Start and Stop control the ability
* to use the device. Stopping the device completely stops all device
* interrupts from the processor.
*
****************************************************************************/
int XIic_Start(XIic *InstancePtr)
{
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/*
	 * Mask off all interrupts, each is enabled when needed.
	 */
	XIic_WriteIier(InstancePtr->BaseAddress, 0);

	/*
	 * Clear all interrupts by reading and rewriting exact value back.
	 * Only those bits set will get written as 1 (writing 1 clears intr).
	 */
	XIic_ClearIntr(InstancePtr->BaseAddress, 0xFFFFFFFF);

	/*
	 * Enable the device.
	 */
	XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
		 XIIC_CR_ENABLE_DEVICE_MASK);
	/*
	 * Set Rx FIFO Occupancy depth to throttle at
	 * first byte(after reset = 0).
	 */
	XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET, 0);

	/*
	 * Clear and enable the interrupts needed.
	 */
	XIic_ClearEnableIntr(InstancePtr->BaseAddress,
				XIIC_INTR_AAS_MASK | XIIC_INTR_ARB_LOST_MASK);

	InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
	InstancePtr->IsDynamic = FALSE;

	/*
	 * Enable the Global interrupt enable.
	 */
	XIic_IntrGlobalEnable(InstancePtr->BaseAddress);

	return XST_SUCCESS;
}
예제 #7
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.
*
******************************************************************************/
int XIic_MasterRecv(XIic *InstancePtr, u8 *RxMsgPtr, int ByteCount)
{
	u32 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_IntrGlobalDisable(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_IntrGlobalEnable(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_ClearEnableIntr(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 = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);

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

		InstancePtr->Stats.RepeatedStarts++;
		XIic_WriteReg(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;
		}
	}
	XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET,
			(u32) 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_Send10BitAddrByte1(InstancePtr->AddrOfSlave,
					 XIIC_WRITE_OPERATION);
		XIic_Send10BitAddrByte2(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_ClearEnableIntr(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_Send7BitAddr(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_ClearEnableIntr(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 = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
	if ((CntlReg & XIIC_CR_MSMS_MASK) == 0) {
		CntlReg |= XIIC_CR_MSMS_MASK;
		XIic_SetControlRegister(InstancePtr, CntlReg, ByteCount);
		XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
				CntlReg);
	}

	XIic_IntrGlobalEnable(InstancePtr->BaseAddress);

	return XST_SUCCESS;
}
예제 #8
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.
*
******************************************************************************/
int XIic_MasterSend(XIic *InstancePtr, u8 *TxMsgPtr, int ByteCount)
{
	u32 CntlReg;

	XIic_IntrGlobalDisable(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_IntrGlobalEnable(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 = XIic_ReadReg(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);

		XIic_WriteReg(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 is 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_Send10BitAddrByte1(InstancePtr->AddrOfSlave,
					 XIIC_WRITE_OPERATION);
		XIic_Send10BitAddrByte2(InstancePtr->AddrOfSlave);
	} else {
		XIic_Send7BitAddr(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_ClearEnableIntr(InstancePtr->BaseAddress,
					XIIC_INTR_TX_HALF_MASK);
	}

	/*
	 * Clear any pending Tx empty, Tx Error and then enable them.
	 */
	XIic_ClearEnableIntr(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 = XIic_ReadReg(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;
		XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
			 CntlReg);
	}

	XIic_IntrGlobalEnable(InstancePtr->BaseAddress);

	return XST_SUCCESS;
}
/**
* 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 general call address. This is not allowed for Master
*		receive mode.
*
* @note		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.
*
******************************************************************************/
int XIic_DynMasterRecv(XIic *InstancePtr, u8 *RxMsgPtr, u8 ByteCount)
{
    u32 CntlReg;
    u32 RxFifoOccy;

    /*
     * 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;
    }

    /*
     * Disable the Interrupts.
     */
    XIic_IntrGlobalDisable(InstancePtr->BaseAddress);

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

    /*
     * 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_IntrGlobalEnable(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.
     */
    XIic_ClearEnableIntr(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 = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
    if (CntlReg & XIIC_CR_MSMS_MASK) {
        /*
         * Set the Repeated Start bit in CR.
         */
        CntlReg |= XIIC_CR_REPEATED_START_MASK;
        XIic_SetControlRegister(InstancePtr, CntlReg, ByteCount);

        /*
         * Increment stats counts.
         */
        InstancePtr->Stats.RepeatedStarts++;
        XIic_WriteReg(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 immediately
     * 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) {
        RxFifoOccy = 0;
    }
    else {
        if (ByteCount <= IIC_RX_FIFO_DEPTH) {
            RxFifoOccy = ByteCount - 2;
        } else {
            RxFifoOccy = IIC_RX_FIFO_DEPTH - 1;
        }
    }

    XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET,
                  RxFifoOccy);

    /*
     * Send the Seven Bit address. Only 7 bit addressing is supported in
     * Dynamic mode and mark that the address has been sent.
     */
    XIic_DynSend7BitAddress(InstancePtr->BaseAddress,
                            InstancePtr->AddrOfSlave, XIIC_READ_OPERATION);
    InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;

    /*
     * Send the bytecount to be received and set the stop bit.
     */
    XIic_DynSendStop(InstancePtr->BaseAddress, ByteCount);

    /*
     * Tx error is enabled incase the address 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_ClearEnableIntr(InstancePtr->BaseAddress,
                         XIIC_INTR_TX_ERROR_MASK);

    /*
     * Enable the Interrupts.
     */
    XIic_IntrGlobalEnable(InstancePtr->BaseAddress);

    return XST_SUCCESS;
}
/**
* This function sends data as a Dynamic 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 is
* sent by using XIic_DynSend7BitAddress().
*
* @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 if successful else XST_FAILURE.
*
* @note		None.
*
******************************************************************************/
int XIic_DynMasterSend(XIic *InstancePtr, u8 *TxMsgPtr, u8 ByteCount)
{
    u32 CntlReg;

    XIic_IntrGlobalDisable(InstancePtr->BaseAddress);

    /*
     * Ensure that the Dynamic master processing has been included such that
     * events will be properly handled.
     */
    XIIC_DYN_MASTER_INCLUDE;
    InstancePtr->IsDynamic = TRUE;

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

        return XST_FAILURE;
    }

    /*
     * 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 = XIic_ReadReg(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_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
                      CntlReg);
        InstancePtr->Stats.RepeatedStarts++;
    }

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

    /*
     * Send the Seven Bit address. Only 7 bit addressing is supported in
     * Dynamic mode.
     */
    XIic_DynSend7BitAddress(InstancePtr->BaseAddress,
                            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 the Tx FIFO.
     */
    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_ClearEnableIntr(InstancePtr->BaseAddress,
                             XIIC_INTR_TX_HALF_MASK);
    }

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

    /*
     * Enable the Interrupts.
     */
    XIic_IntrGlobalEnable(InstancePtr->BaseAddress);

    return XST_SUCCESS;
}