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