📄 xiic_l.c
字号:
* 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;}/*****************************************************************************//*** 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. */ do { StatusReg = XIo_In8(BaseAddress + XIIC_SR_REG_OFFSET); IntrStatus = XIIC_READ_IISR(BaseAddress); /* 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; } } while ((StatusReg & XIIC_SR_RX_FIFO_EMPTY_MASK) == XIIC_SR_RX_FIFO_EMPTY_MASK); /* * 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;}/*****************************************************************************//*** 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;}/******************************************************************************** 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;}/******************************************************************************** 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -