Ejemplo n.º 1
0
/*****************************************************************************
*
* This function checks to see if the IIC bus is busy.  If so, it will enable
* the bus not busy interrupt such that the driver is notified when the bus
* is no longer busy.
*
* @param    InstancePtr points to the Iic instance to be worked on.
*
* @return
*
* - FALSE indicates the IIC bus is not busy.
* - TRUE 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
*
******************************************************************************/
static u32 IsBusBusy(XIic * InstancePtr)
{
	u8 ControlReg;
	u8 StatusReg;

	ControlReg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);
	StatusReg = XIo_In8(InstancePtr->BaseAddress + XIIC_SR_REG_OFFSET);

	/* If this device is already master of the bus as when using the repeated
	 * start and the bus is busy setup to wait for it to not be busy
	 */
	if (((ControlReg & XIIC_CR_MSMS_MASK) == 0) &&	/* not master */
	    (StatusReg & XIIC_SR_BUS_BUSY_MASK)) {	/* is busy    */
		/* The bus is busy, clear pending BNB interrupt incase previously set
		 * and then enable BusNotBusy interrupt
		 */
		InstancePtr->BNBOnly = TRUE;
		XIic_mClearEnableIntr(InstancePtr->BaseAddress,
				      XIIC_INTR_BNB_MASK);
		InstancePtr->Stats.BusBusy++;

		return TRUE;
	}

	return FALSE;
}
Ejemplo n.º 2
0
/**
* Receive the specified data from the device that has been previously addressed
* on the IIC bus. This function assumes the following:
*   - The Rx Fifo occupancy depth has been set to its max.
*   - Upon entry, the Rx Fifo is empty.
*   - The 7 bit address has been sent.
*   - The dynamic stop and number of bytes to receive has been written to Tx
*     Fifo.
*
* @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. The range of this
*           value is greater than 0 and not higher than 255.
*
* @return   The number of bytes remaining to be received.
*
* @note     This function contains loops that could cause the function not
*           to return if the hardware is not working.
*
******************************************************************************/
static unsigned DynRecvData(u32 BaseAddress, u8 *BufferPtr, u8 ByteCount)
{
 	u8 StatusReg;
 	u32 IntrStatus;
 	u32 IntrStatusMask;

 	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 a byte to show up in the Rx Fifo.
 		 */
		while (1) {
			IntrStatus = XIIC_READ_IISR(BaseAddress);
			StatusReg = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET);

			if ((StatusReg & XIIC_SR_RX_FIFO_EMPTY_MASK) !=
				XIIC_SR_RX_FIFO_EMPTY_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;
			}
		}

 		/*
 		 * Read in byte from the Rx Fifo. If the Fifo reached the
 		 * programmed occupancy depth as programmed in the Rx occupancy
 		 * reg, this read access will un throttle the bus such that
 		 * the next byte is read from the IIC bus.
 		 */
 		*BufferPtr++ = XIo_In8(BaseAddress + XIIC_DRR_REG_OFFSET);
 		ByteCount--;
 	}

	return ByteCount;
}
Ejemplo n.º 3
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. 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 Device 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. This value can't be
*           greater than 255 and needs to be greater than 0.
*
* @return   The number of bytes received.
*
* @note     Upon entry to this function, the IIC interface needs to be already
*           enabled in the CR register.
*
******************************************************************************/
unsigned XIic_DynRecv(u32 BaseAddress, u8 Address, u8 *BufferPtr, u8 ByteCount)
{
	unsigned RemainingByteCount;
	u32 StatusRegister;

	/*
	 * Clear the latched interrupt status so that it will be updated with
	 * the new state when it changes.
	 */
	XIic_mClearIisr(BaseAddress, XIIC_INTR_TX_EMPTY_MASK |
			XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_ARB_LOST_MASK);

	/*
	 * Send the 7 bit slave address for a read operation and set the state
	 * to indicate the address has been sent. Upon writing the address, a
	 * start condition is initiated. MSMS is automatically set to master
	 * when the address is written to the Fifo. If MSMS was already set,
	 *  then a re-start is sent prior to the address.
	 */
	XIic_mDynSend7BitAddress(BaseAddress, Address, XIIC_READ_OPERATION);

	/*
	 * Wait for the bus to go busy.
	 */
	StatusRegister = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET);

	while (( StatusRegister & XIIC_SR_BUS_BUSY_MASK) != XIIC_SR_BUS_BUSY_MASK)
	{
		StatusRegister = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET);
	}

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

	/*
	 * Write to the Tx Fifo the dynamic stop control bit with the number of
	 * bytes that are to be read over the IIC interface from the presently
	 * addressed device.
	 */
	XIic_mDynSendStop(BaseAddress, ByteCount);

	/*
	 * Receive the data from the IIC bus.
	 */
	RemainingByteCount = DynRecvData(BaseAddress, BufferPtr, ByteCount);

	/*
	 * The receive is complete. Return the number of bytes that were
	 * received.
	 */
	return ByteCount - RemainingByteCount;
}
Ejemplo n.º 4
0
/******************************************************************************
*
* This function fills the FIFO using the occupancy register to determine the
* available space to be filled. When the repeated start option is on, the last
* byte is withheld to allow the control register to be properly set on the last
* byte.
*
* @param    InstancePtr is a pointer to the XIic instance to be worked on.
*
* @param    Role indicates the role of this IIC device, a slave or a master, on
*           the IIC bus (XIIC_SLAVE_ROLE or XIIC_MASTER_ROLE)
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
void XIic_TransmitFifoFill(XIic * InstancePtr, int Role)
{
	u8 AvailBytes;
	int LoopCnt;
	int NumBytesToSend;

	/* Determine number of bytes to write to FIFO. Number of bytes that can be
	 * put into the FIFO is (FIFO depth) - (current occupancy + 1)
	 * When more room in FIFO than msg bytes put all of message in the FIFO.
	 */
	AvailBytes = IIC_TX_FIFO_DEPTH -
		(XIo_In8(InstancePtr->BaseAddress + XIIC_TFO_REG_OFFSET) + 1);

	if (InstancePtr->SendByteCount > AvailBytes) {
		NumBytesToSend = AvailBytes;
	}
	else {
		/* More space in FIFO than bytes in message
		 */
		if ((InstancePtr->Options & XII_REPEATED_START_OPTION) ||
		    (Role == XIIC_SLAVE_ROLE)) {
			NumBytesToSend = InstancePtr->SendByteCount;
		}
		else {
			NumBytesToSend = InstancePtr->SendByteCount - 1;
		}
	}

	/* fill FIFO with amount determined above */

	for (LoopCnt = 0; LoopCnt < NumBytesToSend; LoopCnt++) {
		XIic_mWriteSendByte(InstancePtr);
	}
}
Ejemplo n.º 5
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.º 6
0
Xuint32 Read_Bitmap_Header_Bytes(Xuint32 FLASH_ADDR, Xuint32 offset)
{
Xuint32 Bitmap_Header_Data;
Xuint8 Flash_Data;

XIo_Out16 (FLASH_ADDR, 0xFF);
Flash_Data = XIo_In8(FLASH_ADDR + offset);
Bitmap_Header_Data = 0x00000000 | Flash_Data;
Flash_Data = XIo_In8(FLASH_ADDR + offset + 1);
Bitmap_Header_Data = Bitmap_Header_Data | (Flash_Data << 8);
Flash_Data = XIo_In8(FLASH_ADDR + offset + 2);
Bitmap_Header_Data = Bitmap_Header_Data | (Flash_Data << 16);
Flash_Data = XIo_In8(FLASH_ADDR + offset + 3);
Bitmap_Header_Data = Bitmap_Header_Data | (Flash_Data << 24);


}
Ejemplo n.º 7
0
/**
*
* This function receives a byte from PS/2. It operates in the polling mode
* and blocks until a byte of data is received.
*
* @param    BaseAddress contains the base address of the PS/2 port.
*
* @return   The data byte received by PS/2.
*
* @note     None.
*
*****************************************************************************/
u8
XPs2_RecvByte(u32 BaseAddress)
{
	while (XPs2_mIsReceiveEmpty(BaseAddress)) {
	}

	return (u8) XIo_In8(BaseAddress + XPS2_RX_REG_OFFSET);
}
Ejemplo n.º 8
0
void BMP_buildImageData(struct bitmap* bitm)
{
	Xuint32 rows = bitm->dibHeader.height;
	Xuint32 columns = bitm->dibHeader.width;
	Xint32 i, j;
	bitm->addr += 2;

	/*bitm->imageData = (Xuint32**)malloc(rows * sizeof(Xuint32*));
	for (i = 0; i < rows; i++) {
		bitm->imageData[i] = (Xuint32*)malloc(columns * sizeof(Xuint32));
	}*/

	//Xuint32 addr = XPAR_FLASH_MEM0_BASEADDR + 40 + 14 + 256*4;

	Xuint32 padding = 4 - (columns*(bitm->dibHeader.bpp/8))%4;
	if (padding == 4) {
		padding = 0;
	}
	//xil_printf("%d\n",padding);
	//xil_printf("%d	%d\n",rows,columns);

	for (i = 0; i < rows; ++i)
	{
		for (j = 0; j < columns; ++j)
		{
			if(bitm->dibHeader.bpp == 8)
			{
				bitm->imageData[i][j] = XIo_In8(bitm->addr);
				bitm->addr += 1;
				//addr += 1;
			}
			else if (bitm->dibHeader.bpp == 16)
			{
				bitm->imageData[i][j] = rgb16_to_rgb32(Xil_EndianSwap16(XIo_In16 (bitm->addr)));
				bitm->addr += 2;
			}
			else if (bitm->dibHeader.bpp == 24)
			{
				bitm->imageData[i][j] = (XIo_In8(bitm->addr)) | (XIo_In8(bitm->addr + 1) << 8) | (XIo_In8(bitm->addr + 2) << 16);
				bitm->addr += 3;
			}
		}
		bitm->addr += padding;
	}
}
Ejemplo n.º 9
0
/******************************************************************************
* This function reads a number of bytes from an IIC chip into a
* specified buffer.
*
* @param    CoreAddress contains the address of the IIC core.
* @param    ChipAddress contains the address of the IIC core.
* @param    RegAddress contains the address of the register to write to.
* @param    BufferPtr contains the address of the data buffer to be filled.
* @param    ByteCount contains the number of bytes in the buffer to be read.
*           This value is constrained by the page size of the device such
*           that up to 64K may be read in one call.
*
* @return   The number of bytes read. A value less than the specified input
*           value indicates an error.
*
* @note     None.
*
******************************************************************************/
int fmc_ipmi_iic_read(Xuint32 CoreAddress, Xuint8 ChipAddress, Xuint8 RegAddress, 
                      Xuint8 *BufferPtr, Xuint8 ByteCount)
{
  Xuint8 ReceivedByteCount = 0;
  Xuint8 SentByteCount = 0;
  Xuint8 StatusReg;
  XStatus TestStatus=XST_FAILURE;
  int cnt = 0;

  // Make sure all the Fifo's are cleared and Bus is Not busy.
  do
  {
    StatusReg = XIo_In8(CoreAddress + XIIC_SR_REG_OFFSET);
    //xil_printf("[fmc_imageov_iic_read] XIo_In8(CoreAddress + XIIC_SR_REG_OFFSET) => 0x%02X\n\r", StatusReg );
    StatusReg = StatusReg & (XIIC_SR_RX_FIFO_EMPTY_MASK |
	                          XIIC_SR_TX_FIFO_EMPTY_MASK |
                             XIIC_SR_BUS_BUSY_MASK);
  } while (StatusReg != (XIIC_SR_RX_FIFO_EMPTY_MASK |
			                XIIC_SR_TX_FIFO_EMPTY_MASK));

  // Position the Read pointer to specific location.
  do
  {
    StatusReg = XIo_In8(CoreAddress + XIIC_SR_REG_OFFSET);
    //xil_printf("[fmc_imageov_iic_read] XIo_In8(CoreAddress + XIIC_SR_REG_OFFSET) => 0x%02X\n\r", StatusReg );
    if(!(StatusReg & XIIC_SR_BUS_BUSY_MASK))
    {
      SentByteCount = XIic_DynSend(CoreAddress, ChipAddress, 
                                  (Xuint8 *)&RegAddress, 1,
    								        XIIC_REPEATED_START);
    }
    cnt++;
  }while(SentByteCount != 1 && (cnt < 100000));
  
  // Error writing chip address so return SentByteCount
  if (SentByteCount < 1) { return SentByteCount; }

  // Receive the data.
  ReceivedByteCount = XIic_DynRecv(CoreAddress, ChipAddress, BufferPtr, 
                                   ByteCount);

  // Return the number of bytes received.
  return ReceivedByteCount;
}
Ejemplo n.º 10
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.º 11
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.º 13
0
/**
*
* This function gets the modem status from the specified UART. The modem
* status indicates any changes of the modem signals. This function allows
* the modem status to be read in a polled mode. The modem status is updated
* whenever it is read such that reading it twice may not yield the same
* results.
*
* @param	InstancePtr is a pointer to the XUartNs550 instance .
*
* @return 	The modem status which are bit masks that are contained in
*		the file  xuartns550.h and named XUN_MODEM_*.
*
* @note
*
* The bit masks used for the modem status are the exact bits of the modem
* status register with no abstraction.
*
*****************************************************************************/
u8 XUartNs550_GetModemStatus(XUartNs550 *InstancePtr)
{
	u8 ModemStatusRegister;

	/*
	 * Assert validates the input arguments
	 */
	XASSERT_NONVOID(InstancePtr != NULL);

	/* Read the modem status register to return
	 */
	ModemStatusRegister = XIo_In8(InstancePtr->BaseAddress +
					XUN_MSR_OFFSET);
	return ModemStatusRegister;
}
Ejemplo n.º 14
0
static Xuint8 SlaveRecvData(Xuint32 BaseAddress, Xuint8 *BufferPtr) {
  Xuint8 IntrStatus;

  while(1) {
    IntrStatus = XIIF_V123B_READ_IISR(BaseAddress);
    if( IntrStatus & XIIC_INTR_NAAS_MASK ) {
      //xil_printf("Recv complete: %02x\r\n", IntrStatus);
      break;
    }
    if( IntrStatus & XIIC_INTR_RX_FULL_MASK ) {
      *(BufferPtr++) = XIo_In8(BaseAddress + XIIC_DRR_REG_OFFSET);
      //xil_printf("Data received: %d\r\n", *(BufferPtr-1));
      XI2c_mClearIisr(BaseAddress, XIIC_INTR_RX_FULL_MASK);
    }
  }

} // end SlaveRecvData()
Ejemplo n.º 15
0
/******************************************************************************
* This function writes a buffer of bytes to the IIC chip.
*
* @param    CoreAddress contains the address of the IIC core.
* @param    ChipAddress contains the address of the chip.
* @param    RegAddress contains the address of the register to write to.
* @param    BufferPtr contains the address of the data to write.
* @param    ByteCount contains the number of bytes in the buffer to be written.
*           Note that this should not exceed the page size as noted by the 
*           constant PAGE_SIZE.
*
* @return   The number of bytes written, a value less than that which was
*           specified as an input indicates an error.
*
* @note     None.
*
******************************************************************************/
int fmc_ipmi_iic_write(Xuint32 CoreAddress, Xuint8 ChipAddress, Xuint8 RegAddress, 
                       Xuint8 *BufferPtr, Xuint8 ByteCount)
{
  Xuint8 SentByteCount;
  Xuint8 WriteBuffer[PAGE_SIZE + 1];
  Xuint8 Index;
  Xuint8 StatusReg;

  // Make sure all the Fifo's are cleared and Bus is Not busy.
  do
  {
    StatusReg = XIo_In8(CoreAddress + XIIC_SR_REG_OFFSET);
    //xil_printf("[fmc_imageov_iic_write] XIo_In8(CoreAddress + XIIC_SR_REG_OFFSET) => 0x%02X\n\r", StatusReg );
    StatusReg = StatusReg & (XIIC_SR_RX_FIFO_EMPTY_MASK |
                             XIIC_SR_TX_FIFO_EMPTY_MASK |
                             XIIC_SR_BUS_BUSY_MASK);
  } while (StatusReg != (XIIC_SR_RX_FIFO_EMPTY_MASK |
			                XIIC_SR_TX_FIFO_EMPTY_MASK));

  /*
   * A temporary write buffer must be used which contains both the address
   * and the data to be written, put the address in first 
   */
  WriteBuffer[0] = RegAddress;

  /*
   * Put the data in the write buffer following the address.
   */
  for (Index = 0; Index < ByteCount; Index++)
  {
    WriteBuffer[Index + 1] = BufferPtr[Index];
  }

  /*
   * Write data at the specified address.
   */
  SentByteCount = XIic_DynSend(CoreAddress, ChipAddress, WriteBuffer,
                               ByteCount + 1, XIIC_STOP);
  if (SentByteCount < 1) { SentByteCount = 1; }
                               
  // Return the number of bytes written.
  return SentByteCount - 1;
}
Ejemplo n.º 16
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.º 17
0
/**
*
* Gets the options for the specified driver instance. The options are
* implemented as bit masks such that multiple options may be enabled or
* disabled simulataneously.
*
* @param	InstancePtr is a pointer to the XUartNs550 instance.
*
* @return 	The current options for the UART. The optionss are bit masks
*		that are contained in the file xuartns550.h and
*		named XUN_OPTION_*.
*
* @note		None.
*
*****************************************************************************/
u16 XUartNs550_GetOptions(XUartNs550 *InstancePtr)
{
	u16 Options = 0;
	u8 Register;
	u32 Index;

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

	/*
	 * Loop thru the options table to map the physical options in the
	 * registers of the UART to the logical options to be returned
	 */
	for (Index = 0; Index < XUN_NUM_OPTIONS; Index++) {
		/*
		 * If the FIFO control register is being read, the make sure to
		 * setup the line control register so it can be read
		 */
		if (OptionsTable[Index].RegisterOffset == XUN_FCR_OFFSET) {
			Register = ReadFcrRegister(InstancePtr->BaseAddress);
		} else {
			Register = XIo_In8(InstancePtr->BaseAddress +
					OptionsTable[Index].RegisterOffset);
		}

		/*
		 * If the bit in the register which correlates to the option
		 * is set, then set the corresponding bit in the options,
		 * ignoring any bits which are zero since the options variable
		 * is initialized to zero
		 */
		if (Register & OptionsTable[Index].Mask) {
			Options |= OptionsTable[Index].Option;
		}
	}

	return Options;
}
Ejemplo n.º 18
0
/**
*
* This function determines if the specified UART is sending data. If the
* transmitter register is not empty, it is sending data.
*
* @param	InstancePtr is a pointer to the XUartNs550 instance.
*
* @return	A value of TRUE if the UART is sending data, otherwise FALSE.
*
* @note		None.
*
*****************************************************************************/
int XUartNs550_IsSending(XUartNs550 *InstancePtr)
{
	u8 LsrRegister;

	/*
	 * Assert validates the input arguments
	 */
	XASSERT_NONVOID(InstancePtr != NULL);

	/*
	 * Read the line status register to determine if the transmitter is
	 * empty
	 */
	LsrRegister = XIo_In8(InstancePtr->BaseAddress + XUN_LSR_OFFSET);

	/*
	 * If the transmitter is not empty then indicate that the UART is still
	 * sending some data
	 */
	return ((LsrRegister & XUN_LSR_TX_EMPTY) == 0);
}
Ejemplo n.º 19
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.º 20
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.º 21
0
static void PrintStatus(Xuint32 BaseAddress) {

  Xuint8 CtrlReg, StatusReg, IntrStatus, DevAddress;
  Xuint8 RxFifoOcy, TxFifoOcy, RxFifoDepth;
   
  CtrlReg = XIo_In8(BaseAddress + XIIC_CR_REG_OFFSET);
  StatusReg = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET);
  IntrStatus = XIIF_V123B_READ_IISR(BaseAddress);
  DevAddress = XIo_In8(BaseAddress + XIIC_ADR_REG_OFFSET);
  RxFifoOcy = XIo_In8(BaseAddress + XIIC_RFO_REG_OFFSET);
  TxFifoOcy = XIo_In8(BaseAddress + XIIC_TFO_REG_OFFSET);
  RxFifoDepth = XIo_In8(BaseAddress + XIIC_RFD_REG_OFFSET);

  xil_printf("\r\nControl Reg:\t\t 0x%02x\r\n", CtrlReg);
  xil_printf("Status Reg:\t\t 0x%02x\r\n", StatusReg);
  xil_printf("Interrupts:\t\t 0x%02x\r\n", IntrStatus);
  //xil_printf("Device Address:\t\t 0x%02x\r\n", DevAddress);
  //xil_printf("Rx Fifo Occupancy:\t 0x%02x\r\n", RxFifoOcy);
  //xil_printf("Tx Fifo Occupancy:\t 0x%02x\r\n", TxFifoOcy);
  //xil_printf("Rx Fifo Depth:\t\t 0x%02x\r\n", RxFifoDepth);

} // end PrintStatus()
Ejemplo n.º 22
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.º 23
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. 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: XIIC_STOP = end with STOP condition, XIIC_REPEATED_START
*           = don't end with STOP condition.
*
* @return   The number of bytes sent.
*
* @note     None.
*
******************************************************************************/
unsigned XIic_DynSend(u32 BaseAddress, u16 Address, u8 *BufferPtr,
		      u8 ByteCount, u8 Option)
{
	unsigned RemainingByteCount;
	u32 StatusRegister;

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

	/*
	 * Put the address into the Fifo to be sent and indicate that the
	 * operation to be performed on the bus is a write operation. Upon
	 * writing the address, a start condition is initiated. MSMS is
	 * automatically set to master when the address is written to the Fifo.
	 * If MSMS was already set, then a re-start is sent prior to the
	 *  address.
	 */
	if(!(Address & XIIC_TX_DYN_STOP_MASK))
	{

		XIic_mDynSend7BitAddress(BaseAddress, Address,
		XIIC_WRITE_OPERATION);
	}
	else
	{
		XIic_mDynSendStartStopAddress(BaseAddress, Address,
					XIIC_WRITE_OPERATION);
    }

	/*
	 * Wait for the bus to go busy.
	 */
	StatusRegister = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET);

	while (( StatusRegister & XIIC_SR_BUS_BUSY_MASK) != XIIC_SR_BUS_BUSY_MASK)
	{
		StatusRegister = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET);
	}

	/*
	 * 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 = DynSendData(BaseAddress, BufferPtr, ByteCount,
					 Option);

	/*
	 * The send is complete return the number of bytes that was sent.
	 */
	return ByteCount - RemainingByteCount;
}
Ejemplo n.º 24
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.º 25
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.º 26
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 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 reception
*           of data, XIIC_STOP = end with STOP condition, XIIC_REPEATED_START
*           = don't end with STOP condition.
*
* @return
*
* The number of bytes received.
*
* @note
*
* None
*
******************************************************************************/
unsigned XIic_Recv(u32 BaseAddress, u8 Address,
		   u8 *BufferPtr, unsigned ByteCount, u8 Option)
{
	u8 CntlReg;
	unsigned RemainingByteCount;
	volatile u8 StatusReg;

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


	/* 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.
	 */
	CntlReg = XIo_In8(BaseAddress + XIIC_CR_REG_OFFSET);
	if ((CntlReg & XIIC_CR_REPEATED_START_MASK) == 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
		 */
		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 read operation
		 * and set the state to indicate the address has been sent
		 */
		XIic_mSend7BitAddress(BaseAddress, Address,
				      XIIC_READ_OPERATION);
	}
	/* Try to receive the data from the IIC bus */

	RemainingByteCount =
		RecvData(BaseAddress, BufferPtr, ByteCount, Option);

	CntlReg = XIo_In8(BaseAddress + XIIC_CR_REG_OFFSET);
	if ((CntlReg & XIIC_CR_REPEATED_START_MASK) == 0) {
		/* The receive is complete, disable the IIC device if the Option is
		 * to release the Bus after Reception of data 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.º 27
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.º 28
0
/**
*
* Gets the data format for the specified UART. The data format includes the
* baud rate, number of data bits, number of stop bits, and parity.
*
* @param	InstancePtr is a pointer to the XUartNs550 instance .
* @param	FormatPtr is a pointer to a format structure that will contain
*		the data format after this call completes.
*
* @return	None.
*
* @note		None.
*
* @internal
*
* This function gets the state of the hardware rather than returning a state
* that has been stored to ensure that the hardware is correct.
*
*****************************************************************************/
void XUartNs550_GetDataFormat(XUartNs550 *InstancePtr,
				XUartNs550Format *FormatPtr)
{
	u8 LcrRegister;

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

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

	/*
	 * Get the baud rate from the instance, this is not retrieved from the
	 * hardware because it is only kept as a divisor such that it is more
	 * difficult to get back to the divisor
	 */
	FormatPtr->BaudRate = InstancePtr->BaudRate;

	/*
	 * 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
	 */
	FormatPtr->DataBits = LcrRegister & XUN_LCR_LENGTH_MASK;

	/*
	 * Set the number of stop bits by first clearing out the bits in that
	 * control it in the register, then set the bits in the register, the
	 * default is one stop bit after clearing the register bits
	 */
	if (LcrRegister & XUN_LCR_2_STOP_BITS) {
		FormatPtr->StopBits = XUN_FORMAT_2_STOP_BIT;
	} else {
		FormatPtr->StopBits = XUN_FORMAT_1_STOP_BIT;
	}

	/*
	 * Determine what parity is set from the register and setup the format
	 * to correspond
	 */
	if ((LcrRegister & XUN_LCR_ENABLE_PARITY) == 0) {
		FormatPtr->Parity = XUN_FORMAT_NO_PARITY;
	} else {

		/*
		 * Parity is enables, so determine if it's even or odd and set the
		 * format to correspond
		 */
		if (LcrRegister & XUN_LCR_EVEN_PARITY) {
			FormatPtr->Parity = XUN_FORMAT_EVEN_PARITY;
		} else {
			FormatPtr->Parity = XUN_FORMAT_ODD_PARITY;
		}
	}
}
Ejemplo n.º 29
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.
*
* All XIic device interrupts are ORed into one device interrupt. This routine
* reads the pending interrupts via the IpIf interface and masks that with the
* interrupt mask to evaluate only the interrupts enabled.
*
******************************************************************************/
void XIic_InterruptHandler(void *InstancePtr)
{
	u8 Status;
	u32 IntrStatus;
	u32 IntrPending;
	u32 IntrEnable;
	XIic *IicPtr = NULL;
	u32 Clear = 0;

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

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

	/* Get the interrupt Status from the IPIF. There is no clearing of
	 * interrupts in the IPIF. Interrupts must be cleared at the source.
	 * To find which interrupts are pending; AND interrupts pending with
	 * interrupts masked.
	 */
	IntrPending = XIIC_READ_IISR(IicPtr->BaseAddress);
	IntrEnable = XIIC_READ_IIER(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_IS_GINTR_ENABLED(IicPtr->BaseAddress) == FALSE)) {
		return;
	}

	/* Update interrupt stats and get the contents of the status register
	 */
	IicPtr->Stats.IicInterrupts++;
	Status = XIo_In8(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_mDisableIntr(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);
		}

		/* Clear Interrupts
		 */
		IntrStatus = XIIC_READ_IISR(IicPtr->BaseAddress);
		Clear = IntrStatus & (XIIC_INTR_TX_EMPTY_MASK |
				      XIIC_INTR_TX_HALF_MASK);
	}

	XIIC_WRITE_IISR(IicPtr->BaseAddress, Clear);
}
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()