Ejemplo n.º 1
0
/****************************** XI2c_Recv *********************************
 *
 * 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.
 *
 ****************************************************************************/
Xuint8 XI2c_Recv(Xuint32 BaseAddress, Xuint8 SlaveAddress,
		   Xuint8 *BufferPtr, Xuint8 ByteCount) {
  Xuint8 CtrlReg;

  CtrlReg = XIIC_CR_ENABLE_DEVICE_MASK | XIIC_CR_MSMS_MASK;

  if( ByteCount == 1 ) {
    /** Set the rx_fifo depth to 1 (zero-based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, 0);
    
    /** Send the slave device address **/
    XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_READ_OPERATION);

    /** Enable no-ack for the single byte transfer **/
    CtrlReg |= XIIC_CR_NO_ACK_MASK;
  }
  else if( ByteCount > 1 ) {
    /** Set the rx_fifo to 1 less than the byte count (zero-based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, ByteCount-2);
    
    /** Send the slave device address **/
    XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_READ_OPERATION);
  }

  /** Enable the device and begin the data transfer **/
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

  /** Clear this once the communication begins **/
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_BNB_MASK);

  return RecvData(BaseAddress, SlaveAddress, BufferPtr, ByteCount);
  
} // XI2c_Recv()
Ejemplo n.º 2
0
/**
* 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;
}
Ejemplo n.º 3
0
Xuint8 XI2c_RSRecv(Xuint32 BaseAddress, Xuint8 SlaveAddress, 
		   Xuint8 StartAddress, Xuint8 *BufferPtr, 
		   Xuint8 ByteCount) {
  Xuint8 CtrlReg;

  /** Clear any ISR values that may need clearing **/
  XI2c_mClearIisr(BaseAddress, 
		  XIIC_INTR_BNB_MASK | XIIC_INTR_RX_FULL_MASK | 
		  XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK |
		  XIIC_INTR_ARB_LOST_MASK);

  /** Send slave device address **/
  XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_WRITE_OPERATION);
  XI2c_mSendStartAddress(BaseAddress, StartAddress);
  
  /** Enable device and indicate data transmission **/
  CtrlReg = XIIC_CR_MSMS_MASK | XIIC_CR_ENABLE_DEVICE_MASK |
    XIIC_CR_DIR_IS_TX_MASK;
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);
  
  /** Send the data **/
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_BNB_MASK | XIIC_INTR_TX_ERROR_MASK);
  if( !TXSuccess(BaseAddress) ) {
    //print("XI2c_RSRecv : 1 : TXFailure\r\n");
    //PrintStatus(BaseAddress);
    return 0;
  }

  /** Enable the repeated start **/
  CtrlReg = XIIC_CR_ENABLE_DEVICE_MASK | XIIC_CR_MSMS_MASK |
    XIIC_CR_REPEATED_START_MASK;
  
  if( ByteCount == 1 ) {
    /** Set the rx_fifo depth to 1 (zero-based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, 0);

    /** Enable the no-ack for the single byte transfer **/
    CtrlReg |= XIIC_CR_NO_ACK_MASK;
  }
  else if( ByteCount > 1 ) {
    /** SEt the rx_fifo depth to 1 less than ByteCount (zero-based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, ByteCount-2); 
  }
  
  /** Enable the device and begin the data transfer **/
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

  /** Send the slave device address **/
  XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_READ_OPERATION);

  return RecvData(BaseAddress, SlaveAddress, BufferPtr, ByteCount);

} // end XI2c_Recv()
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
/**
*
* This function sends a data byte to PS/2. This function operates in the
* polling mode and blocks until the data has been put into the transmit
* holding register.
*
* @param    BaseAddress contains the base address of the PS/2 port.
* @param    Data contains the data byte to be sent.
*
* @return   None.
*
* @note     None.
*
*****************************************************************************/
void
XPs2_SendByte(u32 BaseAddress, u8 Data)
{
	while (XPs2_mIsTransmitFull(BaseAddress)) {
	}

	XIo_Out8(BaseAddress + XPS2_TX_REG_OFFSET, Data);
}
Ejemplo n.º 6
0
/**
*
* Sets the options for the specified driver instance. The options are
* implemented as bit masks such that multiple options may be enabled or
* disabled simultaneously.
*
* The GetOptions function may be called to retrieve the currently enabled
* options. The result is ORed in the desired new settings to be enabled and
* ANDed with the inverse to clear the settings to be disabled. The resulting
* value is then used as the options for the SetOption function call.
*
* @param	InstancePtr is a pointer to the XUartNs550 instance.
* @param	Options contains the options to be set which are bit masks
*		contained in the file xuartns550.h and named XUN_OPTION_*.
*
* @return
*		- XST_SUCCESS if the options were set successfully.
*		- XST_UART_CONFIG_ERROR if the options could not be set because
*		the hardware does not support FIFOs
*
* @note		None.
*
*****************************************************************************/
int XUartNs550_SetOptions(XUartNs550 *InstancePtr, u16 Options)
{
	u32 Index;
	u8 Register;

	/*
	 * Assert validates the input arguments
	 */
	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/*
	 * Loop thru the options table to map the logical options to the
	 * physical options in the registers of the UART.
	 */
	for (Index = 0; Index < XUN_NUM_OPTIONS; Index++) {

		/*
		 * If the FIFO control register is being read, this is a
		 * special case that requires special register processing
		 */
		if (OptionsTable[Index].RegisterOffset == XUN_FCR_OFFSET) {
			Register = ReadFcrRegister(InstancePtr->BaseAddress);
		} else {
			/*
			 * Read the register which contains option so that the
			 * register can be changed without destoying any other
			 * bits of the register
			 */
			Register = XIo_In8(InstancePtr->BaseAddress +
					OptionsTable[Index].RegisterOffset);
		}

		/*
		 * If the option is set in the input, then set the
		 * corresponding bit in the specified register, otherwise
		 * clear the bit in the register
		 */
		if (Options & OptionsTable[Index].Option) {
			Register |= OptionsTable[Index].Mask;
		} else {
			Register &= ~OptionsTable[Index].Mask;
		}

		/*
		 * Write the new value to the register to set the option
		 */
		XIo_Out8(InstancePtr->BaseAddress +
				 OptionsTable[Index].RegisterOffset, Register);
	}

	/* To be done, add error checks for enabling/resetting FIFOs */

	return XST_SUCCESS;
}
Ejemplo n.º 7
0
/**
* 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;
}
Ejemplo n.º 8
0
static Xuint8 SendData(Xuint32 BaseAddress, Xuint8 SlaveAddress, 
		       Xuint8 *BufferPtr, Xuint8 ByteCount) {

  Xuint8 IntrStatus, CtrlReg;
  Xuint8 count = 0;
  
  for( count = 0; count < ByteCount-1; count++ ) 
    XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET, *(BufferPtr++));

  /** Wait for tx_fifo empty **/
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_BNB_MASK | XIIC_INTR_TX_ERROR_MASK);

  if( !TXSuccess(BaseAddress) ) {
    //print("SendData : 1 : TXFailure\r\n");
    return 0;
  }

  /** Generate the stop condition **/
  CtrlReg = XIIC_CR_ENABLE_DEVICE_MASK | XIIC_CR_DIR_IS_TX_MASK;
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

  /** Send the last byte **/
  XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET, *BufferPtr);

  /** Wait for tx_fifo empty **/
  if( !TXSuccess(BaseAddress) ) {
    //print("SendData : 2 : TXFailure\r\n");
    return 0;
  }

  /* The receive is complete, disable the IIC device and return the number of
   * bytes that was received, we must wait for the bnb flag to properly
   * disable the device. */
  do {
    IntrStatus = XIIF_V123B_READ_IISR(BaseAddress);
  } while(!(IntrStatus & XIIC_INTR_BNB_MASK));

  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, 0);
  
  return ++count;

} // end SendData()
Ejemplo n.º 9
0
Xuint8 XI2c_SlaveAccess(Xuint32 BaseAddress, Xuint8 SlaveAddress, 
			Xuint8 *BufferPtr) {
  
  Xuint8 CtrlReg, StatusReg, SlaveSendFlag, DeviceAddress;
  Xuint8 IntrStatus, count = 0;

  XI2c_mClearTXFifo(BaseAddress);

  /** Set the device slave address **/
  DeviceAddress = SlaveAddress << 1;
  XIo_Out8(BaseAddress + XIIC_ADR_REG_OFFSET, DeviceAddress);

  /** Wait until the device is addressed as slave **/
  do {
    IntrStatus = XIIF_V123B_READ_IISR(BaseAddress);
  } while(!(IntrStatus & XIIC_INTR_AAS_MASK));

  XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, 0);

  /** Clear the recieve-fifo interrupt register **/
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_RX_FULL_MASK);

  /** Read the status register to see if we need to receive or send data **/
  StatusReg = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET);
  
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_NAAS_MASK | XIIC_INTR_BNB_MASK);

  SlaveSendFlag = StatusReg & XIIC_SR_MSTR_RDING_SLAVE_MASK;

  if( SlaveSendFlag ) {
    SlaveSendData(BaseAddress, BufferPtr);
  }
  else {
    SlaveRecvData(BaseAddress, BufferPtr);
  }

  XI2c_mClearIisr(BaseAddress, XIIC_INTR_AAS_MASK); 
  
  return 1;

} // XI2c_SlaveAccess()
Ejemplo n.º 10
0
/**
*
* This functions reads the FIFO control register. It's primary purpose is to
* isolate the special processing for reading this register. It is necessary
* to write to the line control register, then read the FIFO control register,
* and then restore the line control register.
*
* @param	BaseAddress contains the base address of the registers in the
*		device.
*
* @return	The contents of the FIFO control register.
*
* @note		None.
*
*****************************************************************************/
static u8 ReadFcrRegister(u32 BaseAddress)
{
	u8 LcrRegister;
	u8 FcrRegister;
	u8 IerRegister;

	/*
	 * Enter a critical section here by disabling Uart interrupts.  We do
	 * not want to receive an interrupt while we have the FCR latched since
	 * the interrupt handler may want to read the IIR.
	 */
	IerRegister = XIo_In8(BaseAddress + XUN_IER_OFFSET);
	XIo_Out8(BaseAddress + XUN_IER_OFFSET, 0);

	/*
	 * Get the line control register contents and set the divisor latch
	 * access bit so the FIFO control register can be read, this can't
	 * be done with a true 16550, but is a feature in the Xilinx device
	 */
	LcrRegister = XIo_In8(BaseAddress + XUN_LCR_OFFSET);
	XIo_Out8(BaseAddress + XUN_LCR_OFFSET, LcrRegister | XUN_LCR_DLAB);

	/*
	 * Read the FIFO control register so it can be returned
	 */
	FcrRegister = XIo_In8(BaseAddress + XUN_FCR_OFFSET);

	/*
	 * Restore the line control register to it's original contents such
	 * that the DLAB bit is no longer set and return the register
	 */
	XIo_Out8(BaseAddress + XUN_LCR_OFFSET, LcrRegister);

	/*
	 * Exit the critical section by restoring the IER
	 */
	XIo_Out8(BaseAddress + XUN_IER_OFFSET, IerRegister);

	return FcrRegister;
}
/**
*
* The IIC bus busy signals when a master has control of the bus. Until the bus
* is released, i.e. not busy, other devices must wait to use it.
*
* When this interrupt occurs, it signals that the previous master has released
* the bus for another user.
*
* This interrupt is only enabled when the master Tx is waiting for the bus.
*
* This interrupt causes the following tasks:
* - Disable Bus not busy interrupt
* - Enable bus Ack
*     Should the slave receive have disabled acknowledgement, enable to allow
*     acknowledgment of the sending of our address to again be addresed as slave
* - Flush Rx FIFO
*     Should the slave receive have disabled acknowledgement, a few bytes may
*     be in FIFO if Rx full did not occur because of not enough byte in FIFO
*     to have caused an interrupt.
* - Send status to user via status callback with the value:
*    XII_BUS_NOT_BUSY_EVENT
*
* @param    InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
static void BusNotBusyHandler(XIic * InstancePtr)
{
	u32 Status;
	u8 CntlReg;

	/* Should the slave receive have disabled acknowledgement,
	 * enable to allow acknowledgment of the sending of our address to
	 * again be addresed as slave
	 */
	CntlReg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);
	XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET,
		 (CntlReg & ~XIIC_CR_NO_ACK_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_mFlushTxFifo(InstancePtr);

	/* 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_mFlushRxFifo(InstancePtr);

	/* Send Application messaging status via callbacks. Disable either Tx or
	 * Receive interrupt. Which callback depends on messaging direction.
	 */
	Status = XIIC_READ_IIER(InstancePtr->BaseAddress);
	if (InstancePtr->RecvBufferPtr == NULL) {
		/* Slave was sending data (master was reading), disable
		 * all the transmit interrupts
		 */
		XIIC_WRITE_IIER(InstancePtr->BaseAddress,
				      (Status & ~XIIC_TX_INTERRUPTS));
	}
	else {
		/* Slave was receiving data (master was writing) disable receive
		 * interrupts
		 */
		XIIC_WRITE_IIER(InstancePtr->BaseAddress,
				      (Status & ~XIIC_INTR_RX_FULL_MASK));
	}

	/* Send Status in StatusHandler callback
	 */
	InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
				   XII_BUS_NOT_BUSY_EVENT);
}
Ejemplo n.º 12
0
/******************************************************************************
*
* Initialize the IIC core for Dynamic Functionality.
*
* @param    BaseAddress contains the base address of the IIC Device.
*
* @return   XST_SUCCESS if Successful else XST_FAILURE.
*
* @note     None.
*
******************************************************************************/
int XIic_DynInit(u32 BaseAddress)
{
    u8 Status;

	/*
	 * Reset IIC Core.
	 */
	XIIC_RESET(BaseAddress);

    /*
     * Set receive Fifo depth to maximum (zero based).
     */
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1);

    /*
     * Reset Tx Fifo.
     */
    XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK);

    /*
     * Enable IIC Device, remove Tx Fifo reset & disable general call.
     */
    XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK);

    /*
     * Read status register and verify IIC Device is in initial state. Only the
     * Tx Fifo and Rx Fifo empty bits should be set.
     */
    Status = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET);
    if(Status == (XIIC_SR_RX_FIFO_EMPTY_MASK | XIIC_SR_TX_FIFO_EMPTY_MASK))
    {
        return XST_SUCCESS;
    }

    return XST_FAILURE;
}
Ejemplo n.º 13
0
Xuint8 XI2c_RSSend(Xuint32 BaseAddress, Xuint8 SlaveAddress, 
		   Xuint8 StartAddress, Xuint8 *BufferPtr, 
		   Xuint8 ByteCount) {

  Xuint8 CtrlReg;

  XI2c_mClearTXFifo(BaseAddress);
  
  /* Put the address into the FIFO to be sent and indicate that the operation
   * to be performed on the bus is a write operation */
  XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_WRITE_OPERATION);
  XI2c_mSendStartAddress(BaseAddress, StartAddress);  

  /* MSMS must be set after putting data into transmit FIFO, indicate the
   * direction is transmit, this device is master and enable the IIC device */
  CtrlReg = XIIC_CR_ENABLE_DEVICE_MASK | XIIC_CR_MSMS_MASK | 
    XIIC_CR_DIR_IS_TX_MASK;
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);
    
  /** Wait for tx_fifo empty **/
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_BNB_MASK);
  if( !TXSuccess(BaseAddress) ) {
    //print("XI2c_RSSend : 1 : TXFailure\r\n");
    return 0;
  }
  
  /** Initiate the repeated start **/
  CtrlReg = CtrlReg | XIIC_CR_REPEATED_START_MASK;
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

  /** Send the device address **/
  XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_WRITE_OPERATION);

  return SendData(BaseAddress, SlaveAddress, BufferPtr, ByteCount);

} // end XI2c_RSSend()
Ejemplo n.º 14
0
/******************************* XI2c_Send *********************************
 *  
 * 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.
 *
 ****************************************************************************/
Xuint8 XI2c_Send(Xuint32 BaseAddress, Xuint8 SlaveAddress,
		 Xuint8 *BufferPtr, Xuint8 ByteCount) {

  Xuint8 CtrlReg;

  XI2c_mClearTXFifo(BaseAddress);

  /** Send the device address **/
  XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_WRITE_OPERATION);

  /** Enable the device and begin transmitting **/
  CtrlReg = XIIC_CR_ENABLE_DEVICE_MASK | XIIC_CR_MSMS_MASK |
    XIIC_CR_DIR_IS_TX_MASK;
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

  return SendData(BaseAddress, SlaveAddress, BufferPtr, ByteCount);

} // end XI2c_Send()
Ejemplo n.º 15
0
/**
*
* This functions sets the receive FIFO trigger level. The receive trigger
* level specifies the number of bytes in the receive FIFO that cause a receive
* data event (interrupt) to be generated. The FIFOs must be enabled to set the
* trigger level.
*
* @param	InstancePtr is a pointer to the XUartNs550 instance .
* @param	TriggerLevel contains the trigger level to set. Constants which
*		define each trigger level are contained in the file xuartns550.h
*		and named XUN_FIFO_TRIGGER_*.
*
* @return
*		- XST_SUCCESS if the trigger level was set
*		- XST_UART_CONFIG_ERROR if the trigger level could not be set,
*		either the hardware does not support the FIFOs or FIFOs
*		are not enabled
*
* @note		None.
*
*****************************************************************************/
int XUartNs550_SetFifoThreshold(XUartNs550 *InstancePtr, u8 TriggerLevel)
{
	u8 FcrRegister;

	/*
	 * Assert validates the input arguments
	 */
	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID((TriggerLevel == XUN_FIFO_TRIGGER_14) ||
			(TriggerLevel == XUN_FIFO_TRIGGER_08) ||
			(TriggerLevel == XUN_FIFO_TRIGGER_04) ||
			(TriggerLevel == XUN_FIFO_TRIGGER_01));
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/*
	 * Read the value of the FIFO control register, this read takes special
	 * register processing
	 */
	FcrRegister = ReadFcrRegister(InstancePtr->BaseAddress);

	/*
	 * If the FIFO control register indicates that FIFOs are disabled, then
	 * either they are just disabled or it has no FIFOs, return an error
	 */
	if ((FcrRegister & XUN_FIFO_ENABLE) == 0) {
		return XST_UART_CONFIG_ERROR;
	}

	/*
	 * Set the receive FIFO trigger level by clearing out the old level in
	 * the FIFO control register and writing in the new level
	 */
	FcrRegister &= ~XUN_FIFO_RX_TRIGGER;
	FcrRegister |= TriggerLevel;

	/*
	 * Write the new value for the FIFO control register to it such that the
	 * threshold is changed, writing to it is normal unlike reading from it
	 */
	XIo_Out8(InstancePtr->BaseAddress + XUN_FCR_OFFSET, FcrRegister);

	return XST_SUCCESS;
}
Ejemplo n.º 16
0
static Xuint8 SlaveSendData(Xuint32 BaseAddress, Xuint8 *BufferPtr) {
  Xuint8 IntrStatus;

  XI2c_mClearIisr(BaseAddress, XIIC_INTR_TX_ERROR_MASK);

  while(1) {

    do {
      IntrStatus = XIIF_V123B_READ_IISR(BaseAddress);

      if( IntrStatus & (XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_NAAS_MASK) ) {
	//xil_printf("Send complete: %02x\r\n", IntrStatus);
	return;
      }

    } while( !(IntrStatus & XIIC_INTR_TX_EMPTY_MASK) );

    //xil_printf("Data sent: %d\r\n", *BufferPtr);
    XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET, *(BufferPtr++));
    XI2c_mClearIisr(BaseAddress, XIIC_INTR_TX_EMPTY_MASK);
  }
  
} // end SlaveSendData()
Ejemplo n.º 17
0
/******************************************************************************
*
* This function sends the proper byte of the address as well as generate the
* proper address bit fields depending on the address byte required and the
* direction of the data (write or read).
*
* A master receiving has the restriction that the direction must be switched
* from write to read when the third address byte is transmitted.
* For the last byte of the 10 bit address, repeated start must be set prior
* to writing the address. If repeated start options is enabled, the
* control register is written before the address is written to the tx reg.
*
* @param    InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return
*
* None.
*
* @note
*
* This function does read/modify/write to the device control register. Calling
* functions must ensure critical sections are used.
*
******************************************************************************/
static void SendSlaveAddr(XIic * InstancePtr)
{
	u8 CRreg;

	/* Set the control register for Master Receive, repeated start must be set
	 * before writing the address, MSMS should be already set, don't set here
	 * so if arbitration is lost or some other reason we don't want MSMS set
	 * incase of error
	 */
	CRreg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);

	CRreg |= XIIC_CR_REPEATED_START_MASK;
	CRreg &= ~XIIC_CR_DIR_IS_TX_MASK;

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

	/* Send the 1st byte of the 10 bit address as a read operation, enable the
	 * receive interrupt to know when data is received, assuming that the
	 * receive FIFO threshold has been previously set
	 */
	XIic_mSend10BitAddrByte1(InstancePtr->AddrOfSlave, XIIC_READ_OPERATION);

	XIic_mClearEnableIntr(InstancePtr->BaseAddress, XIIC_INTR_RX_FULL_MASK);
}
Ejemplo n.º 18
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;
	u8 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 = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);
	BytesInFifo = XIo_In8(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_mDisableIntr(InstancePtr->BaseAddress,
				  XIIC_INTR_TX_ERROR_MASK);
		XIic_mClearIntr(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.
		 */
		XIo_Out8(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_mReadRecvByte(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;
		}
		XIo_Out8(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_mReadRecvByte(InstancePtr);
		}
		XIo_Out8(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_mDisableIntr(InstancePtr->BaseAddress,
				  XIIC_INTR_RX_FULL_MASK);

		XIo_Out8(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_mReadRecvByte(InstancePtr);
		}
	}
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
0
/******************************************************************************
*
* Send the specified buffer to the device that has been previously addressed
* on the IIC bus. This function assumes that the 7 bit address has been sent.
*
* @param    BaseAddress contains the base address of the IIC Device.
* @param    BufferPtr points to the data to be sent.
* @param    ByteCount is the number of bytes to be sent.
* @param    Option: XIIC_STOP = end with STOP condition, XIIC_REPEATED_START
*           = don't end with STOP condition.
*
* @return   The number of bytes remaining to be sent.
*
* @note     This function does not take advantage of the transmit Fifo because
*           it is designed for minimal code space and complexity.
*
******************************************************************************/
static unsigned DynSendData(u32 BaseAddress, u8 *BufferPtr,
			    u8 ByteCount, u8 Option)
{
	u32 IntrStatus;

	while (ByteCount > 0) {
		/*
		 * Wait for the transmit to be empty before sending any more
		 * data by polling the interrupt status register.
		 */
		while (1) {
			IntrStatus = XIIC_READ_IISR(BaseAddress);
			if (IntrStatus & (XIIC_INTR_TX_ERROR_MASK |
					  XIIC_INTR_ARB_LOST_MASK |
					  XIIC_INTR_BNB_MASK)) {
				/*
				 * Error condition (NACK or ARB Lost or BNB
				 * Error Has occurred. Clear the Control
				 * register to send a STOP condition on the Bus
				 * and return the number of bytes still to
				 * transmit.
				 */

				XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET,
					 0x03);
				XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET,
					 0x01);

				return ByteCount;
			}

			/*
			 * Check for the transmit Fifo to become Empty.
			 */
			if (IntrStatus & XIIC_INTR_TX_EMPTY_MASK) {
				break;
			}
		}

		/*
		 * Send data to Tx Fifo. If a stop condition is specified and
		 * the last byte is being sent, then set the dynamic stop bit.
		 */
		if ((ByteCount == 1) && (Option == XIIC_STOP)) {
			/*
			 * The MSMS will be cleared automatically upon setting
			 *  dynamic stop.
			 */
			XIo_Out16(BaseAddress + XIIC_DTR_REG_OFFSET - 1,
				  	XIIC_TX_DYN_STOP_MASK | *BufferPtr++);
		}
		else {
			XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET,
				 				*BufferPtr++);
		}

		/*
		 * Update the byte count to reflect the byte sent.
		 */
		ByteCount--;
	}

	if (Option == XIIC_STOP) {
		/*
		 * If the Option is to release the bus after transmission of
		 * data, Wait for the bus to transition to not busy before
		 * returning, the IIC device cannot be disabled until this
		 * occurs.
		 */
		while (1) {
			if (XIIC_READ_IISR(BaseAddress) & XIIC_INTR_BNB_MASK) {
				break;
			}
		}
	}

	return ByteCount;
}
Ejemplo n.º 21
0
/******************************************************************************
*
* Send the specified buffer to the device that has been previously addressed
* on the IIC bus.  This function assumes that the 7 bit address has been sent
* and it should wait for the transmit of the address to complete.
*
* @param    BaseAddress contains the base address of the IIC device.
* @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 remaining to be sent.
*
* @note
*
* This function does not take advantage of the transmit FIFO because it is
* designed for minimal code space and complexity.  It contains loops that
* that could cause the function not to return if the hardware is not working.
*
******************************************************************************/
static unsigned SendData(u32 BaseAddress, u8 *BufferPtr,
			 unsigned ByteCount, u8 Option)
{
	u32 IntrStatus;

	/* Send the specified number of bytes in the specified buffer by polling
	 * the device registers and blocking until complete
	 */
	while (ByteCount > 0) {
		/* Wait for the transmit to be empty before sending any more data
		 * by polling the interrupt status register
		 */
		while (1) {
			IntrStatus = XIIC_READ_IISR(BaseAddress);

			if (IntrStatus & (XIIC_INTR_TX_ERROR_MASK |
					  XIIC_INTR_ARB_LOST_MASK |
					  XIIC_INTR_BNB_MASK)) {
				return ByteCount;
			}

			if (IntrStatus & XIIC_INTR_TX_EMPTY_MASK) {
				break;
			}
		}
		/* If there is more than one byte to send then put the next byte to send
		 * into the transmit FIFO
		 */
		if (ByteCount > 1) {
			XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET,
				 *BufferPtr++);
		}
		else {
			if (Option == XIIC_STOP) {
				/* If the Option is to release the bus after the last data
				 * byte, Set the stop Option before sending the last byte
				 * of data so that the stop Option will be generated
				 * immediately following the data. This is done by clearing
				 * the MSMS bit in the control register.
				 */
				XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET,
					 XIIC_CR_ENABLE_DEVICE_MASK |
					 XIIC_CR_DIR_IS_TX_MASK);
			}

			/* Put the last byte to send in the transmit FIFO */

			XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET,
				 *BufferPtr++);

			if (Option == XIIC_REPEATED_START) {
				XIic_mClearIisr(BaseAddress,
						XIIC_INTR_TX_EMPTY_MASK);
				/* Wait for the transmit to be empty before setting RSTA bit. */
				while (1) {
					IntrStatus =
						XIIC_READ_IISR
						(BaseAddress);
					if (IntrStatus &
					    XIIC_INTR_TX_EMPTY_MASK) {
						/* RSTA bit should be set only when the FIFO is completely Empty.
						 */
						XIo_Out8(BaseAddress +
							 XIIC_CR_REG_OFFSET,
							 XIIC_CR_REPEATED_START_MASK
							 |
							 XIIC_CR_ENABLE_DEVICE_MASK
							 |
							 XIIC_CR_DIR_IS_TX_MASK
							 | XIIC_CR_MSMS_MASK);
						break;
					}
				}
			}

		}

		/* Clear the latched interrupt status register and this must be done after
		 * the transmit FIFO has been written to or it won't clear
		 */
		XIic_mClearIisr(BaseAddress, XIIC_INTR_TX_EMPTY_MASK);

		/* Update the byte count to reflect the byte sent and clear the latched
		 * interrupt status so it will be updated for the new state
		 */
		ByteCount--;
	}

	if (Option == XIIC_STOP) {
		/* If the Option is to release the bus after transmission of data,
		 * Wait for the bus to transition to not busy before returning, the IIC
		 * device cannot be disabled until this occurs.
		 * Note that this is different from a receive operation because the stop
		 * Option causes the bus to go not busy.
		 */
		while (1) {
			if (XIIC_READ_IISR(BaseAddress) &
			    XIIC_INTR_BNB_MASK) {
				break;
			}
		}
	}

	return ByteCount;
}
Ejemplo n.º 22
0
/**
* 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;
}
Ejemplo n.º 23
0
/******************************************************************************
*
* Receive the specified data from the device that has been previously addressed
* on the IIC bus.  This function assumes that the 7 bit address has been sent
* and it should wait for the transmit of the address to complete.
*
* @param    BaseAddress contains the base address of the IIC device.
* @param    BufferPtr points to the buffer to hold the data that is received.
* @param    ByteCount is the number of bytes to be received.
* @param    Option indicates whether to hold or free the bus after reception
*           of data, XIIC_STOP = end with STOP condition, XIIC_REPEATED_START
*           = don't end with STOP condition.
*
* @return
*
* The number of bytes remaining to be received.
*
* @note
*
* This function does not take advantage of the receive FIFO because it is
* designed for minimal code space and complexity.  It contains loops that
* that could cause the function not to return if the hardware is not working.
*
* This function assumes that the calling function will disable the IIC device
* after this function returns.
*
******************************************************************************/
static unsigned RecvData(u32 BaseAddress, u8 *BufferPtr,
			 unsigned ByteCount, u8 Option)
{
	u8 CntlReg;
	u32 IntrStatusMask;
	u32 IntrStatus;

	/* Attempt to receive the specified number of bytes on the IIC bus */

	while (ByteCount > 0) {
		/* Setup the mask to use for checking errors because when receiving one
		 * byte OR the last byte of a multibyte message an error naturally
		 * occurs when the no ack is done to tell the slave the last byte
		 */
		if (ByteCount == 1) {
			IntrStatusMask =
				XIIC_INTR_ARB_LOST_MASK | XIIC_INTR_BNB_MASK;
		}
		else {
			IntrStatusMask =
				XIIC_INTR_ARB_LOST_MASK |
				XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_BNB_MASK;
		}

		/* Wait for the previous transmit and the 1st receive to complete
		 * by checking the interrupt status register of the IPIF
		 */
		while (1) {
			IntrStatus = XIIC_READ_IISR(BaseAddress);
			if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
				break;
			}
			/* Check the transmit error after the receive full because when
			 * sending only one byte transmit error will occur because of the
			 * no ack to indicate the end of the data
			 */
			if (IntrStatus & IntrStatusMask) {
				return ByteCount;
			}
		}

		CntlReg = XIo_In8(BaseAddress + XIIC_CR_REG_OFFSET);

		/* Special conditions exist for the last two bytes so check for them
		 * Note that the control register must be setup for these conditions
		 * before the data byte which was already received is read from the
		 * receive FIFO (while the bus is throttled
		 */
		if (ByteCount == 1) {
			if (Option == XIIC_STOP) {

				/* If the Option is to release the bus after the last data
				 * byte, it has already been read and no ack has been done, so
				 * clear MSMS while leaving the device enabled so it can get off
				 * the IIC bus appropriately with a stop.
				 */
				XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET,
					 XIIC_CR_ENABLE_DEVICE_MASK);
			}
		}

		/* Before the last byte is received, set NOACK to tell the slave IIC
		 * device that it is the end, this must be done before reading the byte
		 * from the FIFO
		 */
		if (ByteCount == 2) {
			/* Write control reg with NO ACK allowing last byte to
			 * have the No ack set to indicate to slave last byte read.
			 */
			XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET,
				 CntlReg | XIIC_CR_NO_ACK_MASK);
		}

		/* Read in data from the FIFO and unthrottle the bus such that the
		 * next byte is read from the IIC bus
		 */
		*BufferPtr++ = XIo_In8(BaseAddress + XIIC_DRR_REG_OFFSET);

		if ((ByteCount == 1) && (Option == XIIC_REPEATED_START)) {

			/* RSTA bit should be set only when the FIFO is completely Empty.
			 */
			XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET,
				 XIIC_CR_ENABLE_DEVICE_MASK | XIIC_CR_MSMS_MASK
				 | XIIC_CR_REPEATED_START_MASK);

		}

		/* Clear the latched interrupt status so that it will be updated with
		 * the new state when it changes, this must be done after the receive
		 * register is read
		 */
		XIic_mClearIisr(BaseAddress, XIIC_INTR_RX_FULL_MASK |
				XIIC_INTR_TX_ERROR_MASK |
				XIIC_INTR_ARB_LOST_MASK);
		ByteCount--;
	}


	if (Option == XIIC_STOP) {

		/* If the Option is to release the bus after Reception of data, wait
		 * for the bus to transition to not busy before returning, the IIC
		 * device cannot be disabled until this occurs. It should transition as
		 * the MSMS bit of the control register was cleared before the last byte
		 * was read from the FIFO.
		 */
		while (1) {
			if (XIIC_READ_IISR(BaseAddress) &
			    XIIC_INTR_BNB_MASK) {
				break;
			}
		}
	}

	return ByteCount;
}
Ejemplo n.º 24
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.
*
* @note
*
* No action is required to clear this interrupt in the device as it is a
* pulse. The interrupt need only be cleared in the IpIf interface.
*
******************************************************************************/
static void TxErrorHandler(XIic * InstancePtr)
{
	u32 IntrStatus;
	u8 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_mFlushTxFifo(InstancePtr);
		XIic_mDisableIntr(InstancePtr->BaseAddress,
				  XIIC_TX_RX_INTERRUPTS);


		/* If operating in Master mode, call status handler to indicate
		 * NOACK occured
		 */
		CntlReg =
			XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);
		if ((CntlReg & XIIC_CR_MSMS_MASK) != 0) {
			InstancePtr->StatusHandler(InstancePtr->
						   StatusCallBackRef,
						   XII_SLAVE_NO_ACK_EVENT);
		}
		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_READ_IISR(InstancePtr->BaseAddress);
	if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
		/* Rx Reg/FIFO has data,  Disable tx error interrupts */

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

	XIic_mFlushTxFifo(InstancePtr);

	/* Disable and clear tx empty, ½ empty, Rx Full or tx error interrupts
	 */
	XIic_mDisableIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
	XIic_mClearIntr(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 = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);
	CntlReg &= ~XIIC_CR_MSMS_MASK;
	XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET, CntlReg);


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

	/* make event callback */

	InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
				   XII_SLAVE_NO_ACK_EVENT);
}
Ejemplo n.º 25
0
/**
*
* Write data into a packet FIFO configured for the Data Realignment Engine
* (DRE). A packet FIFO channel configured in this way will accept any
* combination of byte, half-word, or word writes. The DRE will shift the data
* into the correct byte lane.
*
* @param RegBaseAddress is the base address of the FIFO registers.
*
* @param DataBaseAddress is the base address of the FIFO keyhole.
*
* @param BufferPtr points to the memory buffer that data is to be read from
*        and written into the FIFO. Since this buffer is a byte buffer, the
*        data is assumed to be endian independent. There are no alignment
*        restrictions.
*
* @param ByteCount contains the number of bytes to read from the buffer and to
*        write to the FIFO.
*
* @return
*
* XST_SUCCESS is returned if the operation succeeded.  If there is not enough
* room in the FIFO to hold the specified bytes, XST_PFIFO_NO_ROOM is
* returned.
*
* @note
*
* This function assumes that if the device inserting data into the FIFO is
* a byte device, the order of the bytes in each 32/64 bit word is from the most
* significant byte to the least significant byte.
*
******************************************************************************/
XStatus XPacketFifoV200a_L0WriteDre(Xuint32 RegBaseAddress,
                                    Xuint32 DataBaseAddress,
                                    Xuint8 *BufferPtr,
                                    Xuint32 ByteCount)
{
    Xuint32 FifoRoomLeft;
    Xuint32 BytesLeft;
    Xuint32 Width;

    /* calculate how many slots are left in the FIFO
     */
    FifoRoomLeft = XIo_In32(RegBaseAddress + XPF_V200A_COUNT_STATUS_REG_OFFSET)
        & XPF_V200A_COUNT_MASK;

    /* determine the width of the FIFO
     */
    Width = XIo_In32(RegBaseAddress + XPF_V200A_COUNT_STATUS_REG_OFFSET) &
            XPF_V200A_FIFO_WIDTH_MASK;

    /* from the width, determine how many bytes can be written to the FIFO
     */
    if ((Width == XPF_V200A_FIFO_WIDTH_LEGACY_TYPE) ||
        (Width == XPF_V200A_FIFO_WIDTH_32BITS_TYPE))
    {
        FifoRoomLeft *= 4;
    }
    else if (Width == XPF_V200A_FIFO_WIDTH_64BITS_TYPE)
    {
        FifoRoomLeft *= 8;
    }

    /* Make sure there's enough room in the FIFO */
    if (FifoRoomLeft < ByteCount)
    {
        return XST_PFIFO_NO_ROOM;
    }

    /* Determine the number of bytes to write until 32 bit alignment is
     * reached, then write those bytes to the FIFO one byte at a time
     */
    BytesLeft = (unsigned)BufferPtr % sizeof(Xuint32);
    ByteCount -= BytesLeft;
    while (BytesLeft--)
    {
        XIo_Out8(DataBaseAddress, *BufferPtr++);
    }

    /* Write as many 32 bit words as we can */
    BytesLeft = ByteCount;
    while (BytesLeft >= sizeof(Xuint32))
    {
        XIo_Out32(DataBaseAddress, *(Xuint32*)BufferPtr);
        BufferPtr += sizeof(Xuint32);
        BytesLeft -= sizeof(Xuint32);
    }

    /* Write remaining bytes */
    while (BytesLeft--)
    {
        XIo_Out8(DataBaseAddress, *BufferPtr++);
    }

    return XST_SUCCESS;

}
Ejemplo n.º 26
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;
}
Ejemplo n.º 27
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)
{
	u8 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_mDisableIntr(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_mWriteSendByte(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 =
			    XIo_In8(InstancePtr->BaseAddress +
				    XIIC_CR_REG_OFFSET);
			CntlReg &= ~XIIC_CR_MSMS_MASK;
			XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET,
				 CntlReg);

			XIic_mWriteSendByte(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_mDisableIntr(InstancePtr->BaseAddress,
					  XIIC_TX_INTERRUPTS);
			XIic_mEnableIntr(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 =
			    XIo_In8(InstancePtr->BaseAddress +
				    XIIC_CR_REG_OFFSET);
			CntlReg |= XIIC_CR_REPEATED_START_MASK;
			XIo_Out8(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_mDisableIntr(InstancePtr->BaseAddress,
					  XIIC_TX_INTERRUPTS);
			InstancePtr->SendHandler(InstancePtr->SendCallBackRef,
						 0);
		}
	}

	return;
}
Ejemplo n.º 28
0
/**
*
* Sets the data format for the specified UART. The data format includes the
* baud rate, number of data bits, number of stop bits, and parity. It is the
* caller's responsibility to ensure that the UART is not sending or receiving
* data when this function is called.
*
* @param	InstancePtr is a pointer to the XUartNs550 instance .
* @param	FormatPtr is a pointer to a format structure containing the data
*		format to be set.
*
* @return
*
*		- XST_SUCCESS if the data format was successfully set.
*		- XST_UART_BAUD_ERROR indicates the baud rate could not be set
*		because of the amount of error with the baud rate and the input
*		clock frequency.
*		- XST_INVALID_PARAM if one of the parameters was not valid.
*
* @note
*
* The data types in the format type, data bits and parity, are 32 bit fields
* to prevent a compiler warning that is a bug with the GNU PowerPC compiler.
* The asserts in this function will cause a warning if these fields are
* bytes.
* <br><br>
* The baud rates tested include: 1200, 2400, 4800, 9600, 19200, 38400, 57600
* and 115200.
*
*****************************************************************************/
int XUartNs550_SetDataFormat(XUartNs550 *InstancePtr,
					XUartNs550Format *FormatPtr)
{
	int Status;
	u8 LcrRegister;

	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(FormatPtr != NULL);

	/*
	 * Verify the inputs specified are valid and return an error if any
	 * are not, without setting the data format
	 */
	if ((FormatPtr->DataBits > XUN_FORMAT_8_BITS)	||
		(FormatPtr->Parity > XUN_FORMAT_EVEN_PARITY) ||
		((FormatPtr->StopBits != XUN_FORMAT_2_STOP_BIT) &&
		(FormatPtr->StopBits != XUN_FORMAT_1_STOP_BIT))) {
		return XST_INVALID_PARAM;
	}

	/*
	 * Try to set the baud rate and if it's not successful then don't
	 * continue altering the data format, this is done first to avoid the
	 * format from being altered when an error occurs
	 */
	Status = XUartNs550_SetBaudRate(InstancePtr, FormatPtr->BaudRate);
	if (Status != XST_SUCCESS) {
		return Status;
	}

	/*
	 * Read the line control register which contains the parity, length and
	 * stop bits so they can be updated without affecting any other bits
	 */
	LcrRegister = XIo_In8(InstancePtr->BaseAddress + XUN_LCR_OFFSET);

	/*
	 * Set the length of data (8,7,6,5) by first clearing out the bits
	 * that control it in the register, then set the length in the register
	 */
	LcrRegister &= ~XUN_LCR_LENGTH_MASK;
	LcrRegister |= FormatPtr->DataBits;

	/*
	 * Set the number of stop bits in the line control register, if the
	 * number of stop bits is not 2, then it must be one which is the bit
	 * in the register cleared
	 */
	if (FormatPtr->StopBits == XUN_FORMAT_2_STOP_BIT) {
		LcrRegister |= XUN_LCR_2_STOP_BITS;
	} else {
		LcrRegister &= ~XUN_LCR_2_STOP_BITS;
	}

	/*
	 * Set the parity by first clearing out the bits that control it in the
	 * register, then set the bits in the register, the default is no parity
	 * after clearing the register bits
	 */
	LcrRegister &= ~XUN_LCR_PARITY_MASK;
	if (FormatPtr->Parity != XUN_FORMAT_NO_PARITY) {
		/* Some form of parity is specified, set the bit indicating that
		 * parity is enabled, then setup even or odd, the default is odd
		 * after clearing the register bits
		 */
		LcrRegister |= XUN_LCR_ENABLE_PARITY;
		if (FormatPtr->Parity == XUN_FORMAT_EVEN_PARITY) {
			LcrRegister |= XUN_LCR_EVEN_PARITY;
		}
	}

	/*
	 * Write the line control register out to save the new data format
	 * that has been created
	 */
	XIo_Out8(InstancePtr->BaseAddress + XUN_LCR_OFFSET, LcrRegister);

	return XST_SUCCESS;
}
Ejemplo n.º 29
0
/**
*
* This functions runs a self-test on the driver and hardware device. This self
* test performs a local loopback and verifies data can be sent and received.
*
* The statistics are cleared at the end of the test. The time for this test
* to execute is proportional to the baud rate that has been set prior to
* calling this function.
*
* @param	InstancePtr is a pointer to the XUartNs550 instance
*
* @return
*
* 		- XST_SUCCESS if the test was successful
* 		- XST_UART_TEST_FAIL if the test failed looping back the data
*
* @note 	This function can hang if the hardware is not functioning
*		properly.
*
******************************************************************************/
int XUartNs550_SelfTest(XUartNs550 *InstancePtr)
{
	int Status = XST_SUCCESS;
	u8 McrRegister;
	u8 LsrRegister;
	u8 IerRegister;
	u8 Index;

	/*
	 * Assert validates the input arguments
	 */
	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/*
	 * Setup for polling by disabling all interrupts in the interrupt enable
	 * register
	 */
	IerRegister = XIo_In8(InstancePtr->BaseAddress + XUN_IER_OFFSET);
	XIo_Out8(InstancePtr->BaseAddress + XUN_IER_OFFSET, 0);

	/*
	 * Setup for loopback by enabling the loopback in the modem control
	 * register
	 */
	McrRegister = XIo_In8(InstancePtr->BaseAddress + XUN_MCR_OFFSET);
	XIo_Out8(InstancePtr->BaseAddress + XUN_MCR_OFFSET,
			 McrRegister | XUN_MCR_LOOP);

	/*
	 * Send a number of bytes and receive them, one at a time so this
	 * test will work for 450 and 550
	 */
	for (Index = 0; Index < XUN_TOTAL_BYTES; Index++) {
		/*
		 * Send out the byte and if it was not sent then the failure
		 * will be caught in the compare at the end
		 */
		XUartNs550_Send(InstancePtr, &TestString[Index], 1);

		/*
		 * Wait til the byte is received such that it should be waiting
		 * in the receiver. This can hang if the HW is broken.
		 */
		do {
			LsrRegister = XIo_In8(InstancePtr->BaseAddress +
				  XUN_LSR_OFFSET);
		}
		while ((LsrRegister & XUN_LSR_DATA_READY) == 0);

		/*
		 * Receive the byte that should have been received because of
		 * the loopback, if it wasn't received then it will be caught
		 * in the compare at the end
		 */
		XUartNs550_Recv(InstancePtr, &ReturnString[Index], 1);
	}

	/*
	 * Clear the stats since they are corrupted by the test
	 */
	XUartNs550_mClearStats(InstancePtr);

	/*
	 * Compare the bytes received to the bytes sent to verify the exact data
	 * was received
	 */
	for (Index = 0; Index < XUN_TOTAL_BYTES; Index++) {
		if (TestString[Index] != ReturnString[Index]) {
			Status = XST_UART_TEST_FAIL;
		}
	}

	/*
	 * Restore the registers which were altered to put into polling and
	 * loopback modes so that this test is not destructive
	 */
	XIo_Out8(InstancePtr->BaseAddress + XUN_IER_OFFSET, IerRegister);
	XIo_Out8(InstancePtr->BaseAddress + XUN_MCR_OFFSET, McrRegister);

	return Status;
}
Ejemplo n.º 30
0
static Xuint8 RecvData(Xuint32 BaseAddress, Xuint8 SlaveAddress, 
		       Xuint8 *BufferPtr, Xuint8 ByteCount) {

  Xuint8 IntrStatus, CtrlReg;
  Xuint8 count = 0;

  if( ByteCount > 1 ) {

    /** Receive the data **/
    if( !RXSuccess(BaseAddress) ) {
      //print("RecvData : 1 : RXFailure\r\n");
      return 0;
    }

    /** Set no-ack for the last byte **/
    CtrlReg = XIo_In8(BaseAddress + XIIC_CR_REG_OFFSET) |
      XIIC_CR_NO_ACK_MASK;
    XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

    /** Read in the data from the rx_fifo **/
    for( count = 0; count < (ByteCount-1); count++ ) {
      *(BufferPtr++) = XIo_In8(BaseAddress + XIIC_DRR_REG_OFFSET);
      //xil_printf("Data received: %d\r\n", *(BufferPtr-1));
    }

    /** Clear the rx_full flag **/
    XI2c_mClearIisr(BaseAddress, XIIC_INTR_RX_FULL_MASK);

    /** Set the rx_fifo depth to 1 (zero based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, 0);
  
  }

  /** Receive the data **/
  if( !RXSuccess(BaseAddress) ) {
    //print("RecvData : 2 : RXFailure\r\n");
    return 0;
  }

  /** Set up for a clean release of the iic bus **/
  CtrlReg = XIIC_CR_ENABLE_DEVICE_MASK;
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

  /** Read in the data from the rx_fifo **/
  *BufferPtr = XIo_In8(BaseAddress + XIIC_DRR_REG_OFFSET);
  //xil_printf("Data received: %d\r\n", *BufferPtr); 

  /** Clear the rx_full mask **/
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_RX_FULL_MASK);

  /* The receive is complete, disable the IIC device and return the number of
   * bytes that was received, we must wait for the bnb flag to properly
   * disable the device. THIS DOESN'T WORK RIGHT. */
/*    print("Waiting for bnb_high..."); */
/*    do { */
/*      IntrStatus = XIIF_V123B_READ_IISR(BaseAddress); */
/*    } while(!(IntrStatus & XIIC_INTR_BNB_MASK)); */
/*    print("done!\r\n"); */

  //XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, 0);
  
  /* Return the number of bytes that was received */
  return ++count;

} // end RecvData()