/**
*
* This function sends data on the IIC bus as a slave.
*
* When message data has been sent, but the master keeps reading data, the FIFO
* is filled to prevent bus throttling. There is no way to notify master of this
* condition. While sending data as a slave a transmit error indicates the
* master has completed the data transfer.
*
* NAAS interrupt signals when repeated start occurred and the msg is finished
* and BNB signals when the master sent a stop.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void SendSlaveData(XIic *InstancePtr)
{
    /*
     * When message has been sent, but master keeps reading data, must put a
     * byte in the FIFO or bus will throttle. There is no way to notify
     * master of this condition.
     */
    if (InstancePtr->SendByteCount == 0) {
        XIic_WriteReg(InstancePtr->BaseAddress,
                      XIIC_DTR_REG_OFFSET, 0xFF);
        return;
    }

    /*
     * Send the data by filling the transmit FIFO.
     */
    XIic_TransmitFifoFill(InstancePtr, XIIC_SLAVE_ROLE);
    /*
     * When the amount of data remaining to send is less than the half mark
     * of the FIFO making the use of ½ empty interrupt unnecessary,
     * disable it. Is this a problem that it's checking against 1 rather
     * than half?
     */
    if (InstancePtr->SendByteCount < 1) {
        XIic_DisableIntr(InstancePtr->BaseAddress,
                         XIIC_INTR_TX_HALF_MASK);
    }
    return;
}
示例#2
0
/**
*
* When multiple IIC devices attempt to use the bus simultaneously, only
* a single device will be able to keep control as a master. Those devices
* that didn't retain control over the bus are said to have lost arbitration.
* When arbitration is lost, this interrupt occurs sigaling the user that
* the message did not get sent as expected.
*
* This function, at arbitration lost:
*   - Disables Tx empty, ½ empty and Tx error interrupts
*   - Clears any Tx empty, ½ empty Rx Full or Tx error interrupts
*   - Clears Arbitration lost interrupt,
*   - Flush Tx FIFO
*   - Call StatusHandler callback with the value: XII_ARB_LOST_EVENT
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void ArbitrationLostHandler(XIic *InstancePtr)
{
	/*
	 * Disable Tx empty and ½ empty and Tx error interrupts before clearing
	 * them so they won't occur again.
	 */
	XIic_DisableIntr(InstancePtr->BaseAddress, XIIC_TX_INTERRUPTS);

	/*
	 * Clear any Tx empty, ½ empty Rx Full or Tx error interrupts.
	 */
	XIic_ClearIntr(InstancePtr->BaseAddress, XIIC_TX_INTERRUPTS);

	XIic_FlushTxFifo(InstancePtr);

	/*
	 * Update Status via StatusHandler callback.
	 */
	InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
				   XII_ARB_LOST_EVENT);
}
/**
*
* This function is called when the IIC device is Addressed As a Slave (AAS).
* This occurs when another device on the bus, a master, has addressed this
* device to receive a message.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void AddrAsSlaveHandler(XIic *InstancePtr)
{
    u32 Status;
    int CallValue;

    /*
     * Disable AAS interrupt to clear the interrupt condition since this is
     * interrupt does not go away and enable the not addressed as a slave
     * interrrupt to tell when the master stops data transfer.
     */
    XIic_DisableIntr(InstancePtr->BaseAddress, XIIC_INTR_AAS_MASK);
    XIic_ClearEnableIntr(InstancePtr->BaseAddress, XIIC_INTR_NAAS_MASK);

    /*
     * Determine how the slave is being addressed and call the handler to
     * notify the user of the event.
     */
    Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);

    /*
     * Determine if the master is trying to perform a read or write
     * operation.
     */
    if (Status & XIIC_SR_MSTR_RDING_SLAVE_MASK) {
        CallValue = XII_MASTER_READ_EVENT;
    } else {
        CallValue = XII_MASTER_WRITE_EVENT;
    }

    /*
     * If being addressed with general call also indicate to handler.
     */
    if (Status & XIIC_SR_GEN_CALL_MASK) {
        CallValue |= XII_GENERAL_CALL_EVENT;
    }

    InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef, CallValue);
    return;
}
示例#4
0
/**
*
* This function is called when the receive register is full. The number
* of bytes received to cause the interrupt is adjustable using the Receive FIFO
* Depth register. The number of bytes in the register is read in the Receive
* FIFO occupancy register. Both these registers are zero based values (0-15)
* such that a value of zero indicates 1 byte.
*
* For a Master Receiver to properly signal the end of a message, the data must
* be read in up to the message length - 1, where control register bits will be
* set for bus controls to occur on reading of the last byte.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void RecvMasterData(XIic *InstancePtr)
{
	u8 LoopCnt;
	int BytesInFifo;
	int BytesToRead;
	u32 CntlReg;

	/*
	 * Device is a master receiving, get the contents of the control
	 * register and determine the number of bytes in fifo to be read out.
	 */
	CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
	BytesInFifo = XIic_ReadReg(InstancePtr->BaseAddress,
				XIIC_RFO_REG_OFFSET) + 1;

	/*
	 * If data in FIFO holds all data to be retrieved - 1, set NOACK and
	 * disable the Tx error.
	 */
	if ((InstancePtr->RecvByteCount - BytesInFifo) == 1) {
		/*
		 * Disable Tx error interrupt to prevent interrupt
		 * as this device will cause it when it set NO ACK next.
		 */
		XIic_DisableIntr(InstancePtr->BaseAddress,
				  XIIC_INTR_TX_ERROR_MASK);
		XIic_ClearIntr(InstancePtr->BaseAddress,
				XIIC_INTR_TX_ERROR_MASK);

		/*
		 * Write control reg with NO ACK allowing last byte to
		 * have the No ack set to indicate to slave last byte read.
		 */
		XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
			 (CntlReg | XIIC_CR_NO_ACK_MASK));

		/*
		 * Read one byte to clear a place for the last byte to be read
		 * which will set the NO ACK.
		 */
		XIic_ReadRecvByte(InstancePtr);
	}

	/*
	 * If data in FIFO is all the data to be received then get the data
	 * and also leave the device in a good state for the next transaction.
	 */
	else if ((InstancePtr->RecvByteCount - BytesInFifo) == 0) {
		/*
		 * If repeated start option is off then the master should stop
		 * using the bus, otherwise hold the bus, setting repeated start
		 * stops the slave from transmitting data when the FIFO is read.
		 */
		if ((InstancePtr->Options & XII_REPEATED_START_OPTION) == 0) {
			CntlReg &= ~XIIC_CR_MSMS_MASK;
		} else {
			CntlReg |= XIIC_CR_REPEATED_START_MASK;
		}
		XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
			 CntlReg);

		/*
		 * Read data from the FIFO then set zero based FIFO read depth
		 * for a byte.
		 */
		for (LoopCnt = 0; LoopCnt < BytesInFifo; LoopCnt++) {
			XIic_ReadRecvByte(InstancePtr);
		}
		XIic_WriteReg(InstancePtr->BaseAddress,
				XIIC_RFD_REG_OFFSET, 0);

		/*
		 * Disable Rx full interrupt and write the control reg with ACK
		 * allowing next byte sent to be acknowledged automatically.
		 */
		XIic_DisableIntr(InstancePtr->BaseAddress,
				  XIIC_INTR_RX_FULL_MASK);

		XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
			 (CntlReg & ~XIIC_CR_NO_ACK_MASK));

		/*
		 * Send notification of msg Rx complete in RecvHandler callback.
		 */
		InstancePtr->RecvHandler(InstancePtr->RecvCallBackRef, 0);
	} else {
		/*
		 * Fifo data not at n-1, read all but the last byte of data
		 * from the slave, if more than a FIFO full yet to receive
		 * read a FIFO full.
		 */
		BytesToRead = InstancePtr->RecvByteCount - BytesInFifo - 1;
		if (BytesToRead > IIC_RX_FIFO_DEPTH) {
			BytesToRead = IIC_RX_FIFO_DEPTH;
		}

		/*
		 * Read in data from the FIFO.
		 */
		for (LoopCnt = 0; LoopCnt < BytesToRead; LoopCnt++) {
			XIic_ReadRecvByte(InstancePtr);
		}
	}
}
示例#5
0
/******************************************************************************
*
* When the IIC Tx FIFO/register goes empty, this routine is called by the
* interrupt service routine to fill the transmit FIFO with data to be sent.
*
* This function also is called by the Tx ½ empty interrupt as the data handling
* is identical when you don't assume the FIFO is empty but use the Tx_FIFO_OCY
* register to indicate the available free FIFO bytes.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void SendMasterData(XIic *InstancePtr)
{
	u32 CntlReg;

	/*
	 * The device is a master on the bus.  If there is still more address
	 * bytes to send when in master receive operation and the slave device
	 * is 10 bit addressed.
	 * This requires the lower 7 bits of address to be resent when the mode
	 * switches to Read instead of write (while sending addresses).
	 */
	if (InstancePtr->TxAddrMode & XIIC_TX_ADDR_MSTR_RECV_MASK) {
		/*
		 * Send the 1st byte of the slave address in the read operation
		 * and change the state to indicate this has been done
		 */
		SendSlaveAddr(InstancePtr);
		InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;
	}

	/*
	 * In between 1st and last byte of message, fill the FIFO with more data
	 * to send, disable the 1/2 empty interrupt based upon data left to
	 * send.
	 */
	else if (InstancePtr->SendByteCount > 1) {
		XIic_TransmitFifoFill(InstancePtr, XIIC_MASTER_ROLE);

		if (InstancePtr->SendByteCount < 2) {
			XIic_DisableIntr(InstancePtr->BaseAddress,
					  XIIC_INTR_TX_HALF_MASK);
		}
	}
	/*
	 * If there is only one byte left to send, processing differs between
	 * repeated start and normal messages.
	 */
	else if (InstancePtr->SendByteCount == 1) {
		/*
		 * When using repeated start, another interrupt is expected
		 * after the last byte has been sent, so the message is not
		 * done yet.
		 */
		if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
			XIic_WriteSendByte(InstancePtr);
		}

		/*
		 * When not using repeated start, the stop condition must be
		 * generated after the last byte is written. The bus is
		 * throttled waiting for the last byte.
		 */
		else {
			/*
			 * Set the stop condition before sending the last byte
			 * of data so that the stop condition will be generated
			 * immediately following the data another transmit
			 * interrupt is not expected so the message is done.
			 */
			CntlReg = XIic_ReadReg(InstancePtr->BaseAddress,
					XIIC_CR_REG_OFFSET);
			CntlReg &= ~XIIC_CR_MSMS_MASK;
			XIic_WriteReg(InstancePtr->BaseAddress,
					XIIC_CR_REG_OFFSET,
					CntlReg);

			XIic_WriteSendByte(InstancePtr);

			/*
			 * Wait for bus to not be busy before declaring message
			 * has been sent for the no repeated start operation.
			 * The callback will be called from the BusNotBusy part
			 * of the Interrupt handler to ensure that the message
			 * is completely sent.
			 * Disable the Tx interrupts and enable the BNB
			 * interrupt.
			 */

			InstancePtr->BNBOnly = FALSE;
			XIic_DisableIntr(InstancePtr->BaseAddress,
						XIIC_TX_INTERRUPTS);
			XIic_EnableIntr(InstancePtr->BaseAddress,
					 XIIC_INTR_BNB_MASK);

		}
	} else {
		if (InstancePtr->Options & XII_REPEATED_START_OPTION) {

			/*
			 * The message being sent has completed. When using
			 * repeated start with no more bytes to send repeated
			 * start needs to be set in the control register so
			 * that the bus will still be held by this master.
			 */
			CntlReg = XIic_ReadReg(InstancePtr->BaseAddress,
					XIIC_CR_REG_OFFSET);
			CntlReg |= XIIC_CR_REPEATED_START_MASK;
			XIic_WriteReg(InstancePtr->BaseAddress,
					XIIC_CR_REG_OFFSET, CntlReg);

			/*
			 * If the message that was being sent has finished,
			 * disable all transmit interrupts and call the callback
			 * that was setup to indicate the message was sent,
			 * with 0 bytes remaining.
			 */

			XIic_DisableIntr(InstancePtr->BaseAddress,
					  XIIC_TX_INTERRUPTS);
			InstancePtr->SendHandler(InstancePtr->SendCallBackRef,
						 0);
		}
	}

	return;
}
示例#6
0
/**
*
* This interrupt occurs four different ways: Two as master and two as slave.
* Master:
* <pre>
*  (1) Transmitter (IMPLIES AN ERROR)
*      The slave receiver did not acknowledge properly.
*  (2) Receiver (Implies Tx complete)
*      Interrupt caused by setting TxAck high in the IIC to indicate to the
*      the last byte has been transmitted.
* </pre>
*
* Slave:
* <pre>
*  (3) Transmitter (Implies Tx complete)
*      Interrupt caused by master device indicating last byte of the message
*      has been transmitted.
*  (4) Receiver (IMPLIES AN ERROR)
*      Interrupt caused by setting TxAck high in the IIC to indicate Rx
*      IIC had a problem - set by this device and condition already known
*      and interrupt is not enabled.
* </pre>
*
* This interrupt is enabled during Master send and receive and disabled
* when this device knows it is going to send a negative acknowledge (Ack = No).
*
* Signals user of Tx error via status callback sending: XII_TX_ERROR_EVENT
*
* When MasterRecv has no message to send and only receives one byte of data
* from the salve device, the TxError must be enabled to catch addressing
* errors, yet there is not opportunity to disable TxError when there is no
* data to send allowing disabling on last byte. When the slave sends the
* only byte the NOAck causes a Tx Error. To disregard this as no real error,
* when there is data in the Receive FIFO/register then the error was not
* a device address write error, but a NOACK read error - to be ignored.
* To work with or without FIFO's, the Rx Data interrupt is used to indicate
* data is in the Rx register.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
******************************************************************************/
static void TxErrorHandler(XIic *InstancePtr)
{
	u32 IntrStatus;
	u32 CntlReg;

	/*
	 * When Sending as a slave, Tx error signals end of msg. Not Addressed
	 * As Slave will handle the callbacks. this is used to only flush
	 * the Tx fifo. The addressed as slave bit is gone as soon as the bus
	 * has been released such that the buffer pointers are used to determine
	 * the direction of transfer (send or receive).
	 */
	if (InstancePtr->RecvBufferPtr == NULL) {
		/*
		 * Master Receiver finished reading message. Flush Tx fifo to
		 * remove an 0xFF that was written to prevent bus throttling,
		 * and disable all transmit and receive interrupts.
		 */
		XIic_FlushTxFifo(InstancePtr);
		XIic_DisableIntr(InstancePtr->BaseAddress,
				  XIIC_TX_RX_INTERRUPTS);

		/*
		 * If operating in Master mode, call status handler to indicate
		 * NOACK occured.
		 */
		IntrStatus = XIic_ReadIisr(InstancePtr->BaseAddress);
		if ((IntrStatus & XIIC_INTR_AAS_MASK) == 0) {
			InstancePtr->StatusHandler(InstancePtr->
						   StatusCallBackRef,
						   XII_SLAVE_NO_ACK_EVENT);
		} else {
			/* Decrement the Tx Error since Tx Error interrupt
			 * implies transmit complete while sending as Slave
			 */
			 InstancePtr->Stats.TxErrors--;
		}

		return;
	}

	/*
	 * Data in the receive register from either master or slave receive
	 * When:slave, indicates master sent last byte, message completed.
	 * When:master, indicates a master Receive with one byte received. When
	 * a byte is in Rx reg then the Tx error indicates the Rx data was
	 * recovered normally Tx errors are not enabled such that this should
	 * not occur.
	 */
	IntrStatus = XIic_ReadIisr(InstancePtr->BaseAddress);
	if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
		/* Rx Reg/FIFO has data,  Disable Tx error interrupts */

		XIic_DisableIntr(InstancePtr->BaseAddress,
				  XIIC_INTR_TX_ERROR_MASK);
		return;
	}

	XIic_FlushTxFifo(InstancePtr);

	/*
	 * Disable and clear Tx empty, � empty, Rx Full or Tx error interrupts.
	 */
	XIic_DisableIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
	XIic_ClearIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);

	/* Clear MSMS as on Tx error when Rxing, the bus will be
	 * stopped but MSMS bit is still set. Reset to proper state
	 */
	CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
	CntlReg &= ~XIIC_CR_MSMS_MASK;
	XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET, CntlReg);


	/*
	 * Set FIFO occupancy depth = 1 so that the first byte will throttle
	 * next recieve msg.
	 */
	XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET, 0);

	/*
	 * Call the event callback.
	 */
	InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
				   XII_SLAVE_NO_ACK_EVENT);
}
示例#7
0
/**
*
* This function is the interrupt handler for the XIic driver. This function
* should be connected to the interrupt system.
*
* Only one interrupt source is handled for each interrupt allowing
* higher priority system interrupts quicker response time.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
* @internal
*
* The XIIC_INTR_ARB_LOST_MASK and XIIC_INTR_TX_ERROR_MASK interrupts must have
* higher priority than the other device interrupts so that the IIC device does
* not get into a potentially confused state. The remaining interrupts may be
* rearranged with no harm.
*
******************************************************************************/
void XIic_InterruptHandler(void *InstancePtr)
{
	u32 Status;
	u32 IntrStatus;
	u32 IntrPending;
	u32 IntrEnable;
	XIic *IicPtr = NULL;
	u32 Clear = 0;

	/*
	 * Verify that each of the inputs are valid.
	 */
	Xil_AssertVoid(InstancePtr != NULL);

	/*
	 * Convert the non-typed pointer to an IIC instance pointer
	 */
	IicPtr = (XIic *) InstancePtr;

	/*
	 * Get the interrupt Status.
	 */
	IntrPending = XIic_ReadIisr(IicPtr->BaseAddress);
	IntrEnable = XIic_ReadIier(IicPtr->BaseAddress);
	IntrStatus = IntrPending & IntrEnable;

	/*
	 * Do not processes a devices interrupts if the device has no
	 * interrupts pending or the global interrupts have been disabled.
	 */
	if ((IntrStatus == 0) ||
		(XIic_IsIntrGlobalEnabled(IicPtr->BaseAddress) == FALSE)) {
		return;
	}

	/*
	 * Update interrupt stats and get the contents of the status register.
	 */
	IicPtr->Stats.IicInterrupts++;
	Status = XIic_ReadReg(IicPtr->BaseAddress, XIIC_SR_REG_OFFSET);

	/*
	 * Service requesting interrupt.
	 */
	if (IntrStatus & XIIC_INTR_ARB_LOST_MASK) {
		/* Bus Arbritration Lost */

		IicPtr->Stats.ArbitrationLost++;
		XIic_ArbLostFuncPtr(IicPtr);

		Clear = XIIC_INTR_ARB_LOST_MASK;
	} else if (IntrStatus & XIIC_INTR_TX_ERROR_MASK) {
		/* Transmit errors (no acknowledge) received */
		IicPtr->Stats.TxErrors++;
		TxErrorHandler(IicPtr);

		Clear = XIIC_INTR_TX_ERROR_MASK;
	} else if (IntrStatus & XIIC_INTR_NAAS_MASK) {
		/* Not Addressed As Slave */

		XIic_NotAddrAsSlaveFuncPtr(IicPtr);
		Clear = XIIC_INTR_NAAS_MASK;
	} else if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
		/* Receive register/FIFO is full */

		IicPtr->Stats.RecvInterrupts++;

		if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
			XIic_RecvSlaveFuncPtr(IicPtr);
		} else {
			XIic_RecvMasterFuncPtr(IicPtr);
		}

		Clear = XIIC_INTR_RX_FULL_MASK;
	} else if (IntrStatus & XIIC_INTR_AAS_MASK) {
		/* Addressed As Slave */

		XIic_AddrAsSlaveFuncPtr(IicPtr);
		Clear = XIIC_INTR_AAS_MASK;
	} else if (IntrStatus & XIIC_INTR_BNB_MASK) {
		/* IIC bus has transitioned to not busy */

		/* Check if send callback needs to run */
		if (IicPtr->BNBOnly == TRUE) {
			XIic_BusNotBusyFuncPtr(IicPtr);
			IicPtr->BNBOnly = FALSE;
		} else {
			IicPtr->SendHandler(IicPtr->SendCallBackRef, 0);
		}

		Clear = XIIC_INTR_BNB_MASK;

		/* The bus is not busy, disable BusNotBusy interrupt */
		XIic_DisableIntr(IicPtr->BaseAddress, XIIC_INTR_BNB_MASK);

	} else if ((IntrStatus & XIIC_INTR_TX_EMPTY_MASK) ||
		 (IntrStatus & XIIC_INTR_TX_HALF_MASK)) {
		/* Transmit register/FIFO is empty or � empty */
		IicPtr->Stats.SendInterrupts++;

		if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
			XIic_SendSlaveFuncPtr(IicPtr);
		} else {
			XIic_SendMasterFuncPtr(IicPtr);
		}

		IntrStatus = XIic_ReadIisr(IicPtr->BaseAddress);
		Clear = IntrStatus & (XIIC_INTR_TX_EMPTY_MASK |
					  XIIC_INTR_TX_HALF_MASK);
	}

	/*
	 * Clear Interrupts.
	 */
	XIic_WriteIisr(IicPtr->BaseAddress, Clear);
}
/**
*
* This function is called when the IIC device receives Not Addressed As Slave
* (NAAS) interrupt which indicates that the master has released the bus implying
* a data transfer is complete.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void NotAddrAsSlaveHandler(XIic *InstancePtr)
{
    u32 Status;
    u32 CntlReg;
    u8 BytesToRead;
    u8 LoopCnt;

    /*
     * Disable NAAS so that the condition will not continue to interrupt
     * and enable the addressed as slave interrupt to know when a master
     * selects a slave on the bus.
     */
    XIic_DisableIntr(InstancePtr->BaseAddress, XIIC_INTR_NAAS_MASK);
    XIic_ClearEnableIntr(InstancePtr->BaseAddress, XIIC_INTR_AAS_MASK);

    /*
     * Flush Tx FIFO by toggling TxFIFOResetBit. FIFO runs normally at 0
     * Do this incase needed to Tx FIFO with more than expected if what
     * was set to Tx was less than what the Master expected - read more
     * from this slave so FIFO had junk in it.
     */
    XIic_FlushTxFifo(InstancePtr);

    /*
     * NAAS interrupt was asserted but received data in recieve FIFO is
     * less than Rc_FIFO_PIRQ to assert an receive full interrupt,in this
     * condition as data recieved is valid we have to read data before FIFO
     * flush.
     */
    Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);

    if (!(Status & XIIC_SR_RX_FIFO_EMPTY_MASK))
    {
        BytesToRead = (XIic_ReadReg(InstancePtr->BaseAddress,
                                    XIIC_RFO_REG_OFFSET)) + 1;
        if (InstancePtr->RecvByteCount > BytesToRead) {

            for (LoopCnt = 0; LoopCnt < BytesToRead; LoopCnt++) {
                XIic_ReadRecvByte(InstancePtr);
            }
        }
    }

    InstancePtr->RecvByteCount = 0;
    /*
     * Flush Rx FIFO should slave Rx had a problem, sent No ack but
     * still received a few bytes. Should the slave receive have disabled
     * acknowledgement, clear Rx FIFO.
     */
    XIic_FlushRxFifo(InstancePtr);

    /*
     * Set FIFO occupancy depth = 1 so that the first byte will throttle
     * next recieve msg.
     */
    XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET, 0);

    /*
     * Should the slave receive have disabled acknowledgement,
     * enable to allow acknowledgment for receipt of our address to
     * again be used as a slave.
     */
    CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
    XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
                  (CntlReg & ~XIIC_CR_NO_ACK_MASK));

    /*
     * Which callback depends on messaging direction, the buffer pointer NOT
     * being used indicates the direction of data transfer.
     */
    Status = XIic_ReadIier(InstancePtr->BaseAddress);
    if (InstancePtr->RecvBufferPtr == NULL) {
        /*
         * Slave was sending data so disable all transmit interrupts and
         * call the callback handler to indicate the transfer is
         * complete.
         */
        XIic_WriteIier(InstancePtr->BaseAddress,
                       (Status & ~XIIC_TX_INTERRUPTS));
        InstancePtr->SendHandler(InstancePtr->SendCallBackRef,
                                 InstancePtr->SendByteCount);
    }
    else {
        /*
         * Slave was receiving data so disable receive full interrupt
         * and call the callback handler to notify the transfer is
         * complete.
         */
        XIic_WriteIier(InstancePtr->BaseAddress,
                       (Status & ~XIIC_INTR_RX_FULL_MASK));
        InstancePtr->RecvHandler(InstancePtr->RecvCallBackRef,
                                 InstancePtr->RecvByteCount);
    }
    return;
}
/******************************************************************************
*
* When the IIC Tx FIFO/register goes empty, this routine is called by the
* interrupt service routine to fill the transmit FIFO with data to be sent.
*
* This function also is called by the Tx ½ empty interrupt as the data handling
* is identical when you don't assume the FIFO is empty but use the Tx_FIFO_OCY
* register to indicate the available free FIFO bytes.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void DynSendMasterData(XIic *InstancePtr)
{
    u32 CntlReg;

    /*
     * In between 1st and last byte of message, fill the FIFO with more data
     * to send, disable the 1/2 empty interrupt based upon data left to
     * send.
     */
    if (InstancePtr->SendByteCount > 1) {
        XIic_TransmitFifoFill(InstancePtr, XIIC_MASTER_ROLE);

        if (InstancePtr->SendByteCount < 2) {
            XIic_DisableIntr(InstancePtr->BaseAddress,
                             XIIC_INTR_TX_HALF_MASK);
        }
    }

    /*
     * If there is only one byte left to send, processing differs between
     * repeated start and normal messages.
     */
    else if (InstancePtr->SendByteCount == 1) {
        /*
         * When using repeated start, another interrupt is expected
         * after the last byte has been sent, so the message is not
         * done yet.
         */
        if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
            XIic_WriteSendByte(InstancePtr);
        } else {
            XIic_DynSendStop(InstancePtr->BaseAddress,
                             *InstancePtr->SendBufferPtr);

            /*
             * Wait for bus to not be busy before declaring message
             * has been sent for the no repeated start operation.
             * The callback will be called from the BusNotBusy part
             * of the Interrupt handler to ensure that the message
             * is completely sent. Disable the Tx interrupts and
             * enable the BNB interrupt.
             */
            InstancePtr->BNBOnly = FALSE;
            XIic_DisableIntr(InstancePtr->BaseAddress,
                             XIIC_TX_INTERRUPTS);
            XIic_EnableIntr(InstancePtr->BaseAddress,
                            XIIC_INTR_BNB_MASK);
        }
    } else {
        if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
            /*
             * The message being sent has completed. When using
             * repeated start with no more bytes to send repeated
             * start needs to be set in the control register so
             * that the bus will still be held by this master.
             */
            CntlReg = XIic_ReadReg(InstancePtr->BaseAddress,
                                   XIIC_CR_REG_OFFSET);
            CntlReg |= XIIC_CR_REPEATED_START_MASK;
            XIic_WriteReg(InstancePtr->BaseAddress,
                          XIIC_CR_REG_OFFSET, CntlReg);

            /*
             * If the message that was being sent has finished,
             * disable all transmit interrupts and call the callback
             * that was setup to indicate the message was sent,
             * with 0 bytes remaining.
             */
            XIic_DisableIntr(InstancePtr->BaseAddress,
                             XIIC_TX_INTERRUPTS);
            InstancePtr->SendHandler(InstancePtr->SendCallBackRef,
                                     0);
        }
    }

    return;
}