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