/******************************************************************************* * Function Name: I2CM_Stop ******************************************************************************** * * Summary: * Disables the SCB component and its interrupt. * It also disables all TX interrupt sources so as not to cause an unexpected * interrupt trigger because after the component is enabled, the TX FIFO * is empty. * * Parameters: * None * * Return: * None * *******************************************************************************/ void I2CM_Stop(void) { #if (I2CM_SCB_IRQ_INTERNAL) I2CM_DisableInt(); #endif /* (I2CM_SCB_IRQ_INTERNAL) */ /* Call Stop function specific to current operation mode */ I2CM_ScbModeStop(); /* Disable SCB IP */ I2CM_CTRL_REG &= (uint32) ~I2CM_CTRL_ENABLED; /* Disable all TX interrupt sources so as not to cause an unexpected * interrupt trigger because after the component is enabled, the TX FIFO * is empty. * For SCB IP v0, it is critical as it does not mask-out interrupt * sources when they are disabled. This can cause a code lock-up in the * interrupt handler because TX FIFO cannot be loaded after the block * is disabled. */ I2CM_SetTxInterruptMode(I2CM_NO_INTR_SOURCES); #if (I2CM_SCB_IRQ_INTERNAL) I2CM_ClearPendingInt(); #endif /* (I2CM_SCB_IRQ_INTERNAL) */ }
/******************************************************************************* * Function Name: I2CM_I2CMasterClearWriteBuf ****************************************************************************//** * * Resets the write buffer pointer back to the first byte in the buffer. * * \globalvars * I2CM_mstrRdBufIndex - used to current index within master read * buffer. * I2CM_mstrStatus - used to store current status of I2C Master. * *******************************************************************************/ void I2CM_I2CMasterClearWriteBuf(void) { I2CM_DisableInt(); /* Lock from interruption */ I2CM_mstrWrBufIndex = 0u; I2CM_mstrStatus &= (uint16) ~I2CM_I2C_MSTAT_WR_CMPLT; I2CM_EnableInt(); /* Release lock */ }
/******************************************************************************* * Function Name: I2CM_I2CMasterClearStatus ****************************************************************************//** * * Clears all status flags and returns the master status. * * \return * Current status of master. See the I2CM_I2CMasterStatus() * function for constants. * * \globalvars * I2CM_mstrStatus - used to store current status of I2C Master. * *******************************************************************************/ uint32 I2CM_I2CMasterClearStatus(void) { uint32 status; I2CM_DisableInt(); /* Lock from interruption */ /* Read and clear master status */ status = (uint32) I2CM_mstrStatus; I2CM_mstrStatus = I2CM_I2C_MSTAT_CLEAR; I2CM_EnableInt(); /* Release lock */ return(status); }
/******************************************************************************* * Function Name: I2CM_I2CMasterStatus ****************************************************************************//** * * Returns the master's communication status. * * \return * Current status of I2C master. This status incorporates status constants. * Each constant is a bit field value. The value returned may have multiple * bits set to indicate the status of the read or write transfer. * - I2CM_I2C_MSTAT_RD_CMPLT - Read transfer complete. * The error condition status bits must be checked to ensure that * read transfer was completed successfully. * - I2CM_I2C_MSTAT_WR_CMPLT - Write transfer complete. * The error condition status bits must be checked to ensure that write * transfer was completed successfully. * - I2CM_I2C_MSTAT_XFER_INP - Transfer in progress. * - I2CM_I2C_MSTAT_XFER_HALT - Transfer has been halted. * The I2C bus is waiting for ReStart or Stop condition generation. * - I2CM_I2C_MSTAT_ERR_SHORT_XFER - Error condition: Write * transfer completed before all bytes were transferred. The slave NAKed * the byte which was expected to be ACKed. * - I2CM_I2C_MSTAT_ERR_ADDR_NAK - Error condition: Slave did * not acknowledge address. * - I2CM_I2C_MSTAT_ERR_ARB_LOST - Error condition: Master lost * arbitration during communications with slave. * - I2CM_I2C_MSTAT_ERR_BUS_ERROR - Error condition: bus error * occurred during master transfer due to misplaced Start or Stop * condition on the bus. * - I2CM_I2C_MSTAT_ERR_ABORT_XFER - Error condition: Slave was * addressed by another master while master performed the start condition * generation. As a result, master has automatically switched to slave * mode and is responding. The master transaction has not taken place * This error condition only applicable for Multi-Master-Slave mode. * - I2CM_I2C_MSTAT_ERR_XFER - Error condition: This is the * ORed value of all error conditions provided above. * * \globalvars * I2CM_mstrStatus - used to store current status of I2C Master. * *******************************************************************************/ uint32 I2CM_I2CMasterStatus(void) { uint32 status; I2CM_DisableInt(); /* Lock from interruption */ status = (uint32) I2CM_mstrStatus; if (I2CM_CHECK_I2C_MASTER_ACTIVE) { /* Add status of master pending transaction: MSTAT_XFER_INP */ status |= (uint32) I2CM_I2C_MSTAT_XFER_INP; } I2CM_EnableInt(); /* Release lock */ return(status); }
/******************************************************************************* * Function Name: I2CM_I2CMasterWriteBuf ****************************************************************************//** * * Automatically writes an entire buffer of data to a slave device. * Once the data transfer is initiated by this function, further data transfer * is handled by the included ISR. * Enables the I2C interrupt and clears I2CM_I2C_MSTAT_WR_CMPLT * status. * * \param slaveAddr: 7-bit slave address. * \param xferData: Pointer to buffer of data to be sent. * \param cnt: Size of buffer to send. * \param mode: Transfer mode defines: * (1) Whether a start or restart condition is generated at the beginning * of the transfer, and * (2) Whether the transfer is completed or halted before the stop * condition is generated on the bus.Transfer mode, mode constants * may be ORed together. * - I2CM_I2C_MODE_COMPLETE_XFER - Perform complete transfer * from Start to Stop. * - I2CM_I2C_MODE_REPEAT_START - Send Repeat Start instead * of Start. A Stop is generated after transfer is completed unless * NO_STOP is specified. * - I2CM_I2C_MODE_NO_STOP Execute transfer without a Stop. * The following transfer expected to perform ReStart. * * \return * Error status. * - I2CM_I2C_MSTR_NO_ERROR - Function complete without error. * The master started the transfer. * - I2CM_I2C_MSTR_BUS_BUSY - Bus is busy. Nothing was sent on * the bus. The attempt has to be retried. * - I2CM_I2C_MSTR_NOT_READY - Master is not ready for to start * transfer. A master still has not completed previous transaction or a * slave operation is in progress (in multi-master-slave configuration). * Nothing was sent on the bus. The attempt has to be retried. * * \globalvars * I2CM_mstrStatus - used to store current status of I2C Master. * I2CM_state - used to store current state of software FSM. * I2CM_mstrControl - used to control master end of transaction with * or without the Stop generation. * I2CM_mstrWrBufPtr - used to store pointer to master write buffer. * I2CM_mstrWrBufIndex - used to current index within master write * buffer. * I2CM_mstrWrBufSize - used to store master write buffer size. * *******************************************************************************/ uint32 I2CM_I2CMasterWriteBuf(uint32 slaveAddress, uint8 * wrData, uint32 cnt, uint32 mode) { uint32 errStatus; errStatus = I2CM_I2C_MSTR_NOT_READY; if(NULL != wrData) /* Check buffer pointer */ { /* Check FSM state and bus before generating Start/ReStart condition */ if(I2CM_CHECK_I2C_FSM_IDLE) { I2CM_DisableInt(); /* Lock from interruption */ /* Check bus state */ errStatus = I2CM_CHECK_I2C_STATUS(I2CM_I2C_STATUS_BUS_BUSY) ? I2CM_I2C_MSTR_BUS_BUSY : I2CM_I2C_MSTR_NO_ERROR; } else if(I2CM_CHECK_I2C_FSM_HALT) { I2CM_mstrStatus &= (uint16) ~I2CM_I2C_MSTAT_XFER_HALT; errStatus = I2CM_I2C_MSTR_NO_ERROR; } else { /* Unexpected FSM state: exit */ } } /* Check if master is ready to start */ if(I2CM_I2C_MSTR_NO_ERROR == errStatus) /* No error proceed */ { #if (!I2CM_CY_SCBIP_V0 && \ I2CM_I2C_MULTI_MASTER_SLAVE_CONST && I2CM_I2C_WAKE_ENABLE_CONST) I2CM_I2CMasterDisableEcAm(); #endif /* (!I2CM_CY_SCBIP_V0) */ /* Set up write transaction */ I2CM_state = I2CM_I2C_FSM_MSTR_WR_ADDR; I2CM_mstrWrBufIndexTmp = 0u; I2CM_mstrWrBufIndex = 0u; I2CM_mstrWrBufSize = cnt; I2CM_mstrWrBufPtr = (volatile uint8 *) wrData; I2CM_mstrControl = (uint8) mode; slaveAddress = I2CM_GET_I2C_8BIT_ADDRESS(slaveAddress); I2CM_mstrStatus &= (uint16) ~I2CM_I2C_MSTAT_WR_CMPLT; I2CM_ClearMasterInterruptSource(I2CM_INTR_MASTER_ALL); I2CM_ClearTxInterruptSource(I2CM_INTR_TX_UNDERFLOW); /* The TX and RX FIFO have to be EMPTY */ /* Enable interrupt source to catch when address is sent */ I2CM_SetTxInterruptMode(I2CM_INTR_TX_UNDERFLOW); /* Generate Start or ReStart */ if(I2CM_CHECK_I2C_MODE_RESTART(mode)) { I2CM_I2C_MASTER_GENERATE_RESTART; I2CM_TX_FIFO_WR_REG = slaveAddress; } else { I2CM_TX_FIFO_WR_REG = slaveAddress; I2CM_I2C_MASTER_GENERATE_START; } } I2CM_EnableInt(); /* Release lock */ return(errStatus); }
/******************************************************************************* * Function Name: I2CM_I2CMasterSendStart ****************************************************************************//** * * Generates Start condition and sends slave address with read/write bit. * Disables the I2C interrupt. * This function is blocking and does not return until start condition and * address byte are sent and ACK/NACK response is received or errors occurred. * * \param slaveAddress: Right justified 7-bit Slave address (valid range * 8 to 120). * \param bitRnW: Direction of the following transfer. * It is defined by read/write bit within address byte. * - I2CM_I2C_WRITE_XFER_MODE - Set write direction for the * following transfer. * - I2CM_I2C_READ_XFER_MODE - Set read direction for the * following transfer. * * \return * Error status. * - I2CM_I2C_MSTR_NO_ERROR - Function complete without error. * - I2CM_I2C_MSTR_BUS_BUSY - Bus is busy. * Nothing was sent on the bus. The attempt has to be retried. * - I2CM_I2C_MSTR_NOT_READY - Master is not ready for to * start transfer. * A master still has not completed previous transaction or a slave * operation is in progress (in multi-master-slave configuration). * Nothing was sent on the bus. The attempt has to be retried. * - I2CM_I2C_MSTR_ERR_LB_NAK - Error condition: Last byte was * NAKed. * - I2CM_I2C_MSTR_ERR_ARB_LOST - Error condition: Master lost * arbitration. * - I2CM_I2C_MSTR_ERR_BUS_ERR - Error condition: Master * encountered a bus error. Bus error is misplaced start or stop detection. * - I2CM_I2C_MSTR_ERR_ABORT_START - Error condition: The start * condition generation was aborted due to beginning of Slave operation. * This error condition is only applicable for Multi-Master-Slave mode. * * \globalvars * I2CM_state - used to store current state of software FSM. * *******************************************************************************/ uint32 I2CM_I2CMasterSendStart(uint32 slaveAddress, uint32 bitRnW) { uint32 resetIp; uint32 errStatus; resetIp = 0u; errStatus = I2CM_I2C_MSTR_NOT_READY; /* Check FSM state before generating Start condition */ if(I2CM_CHECK_I2C_FSM_IDLE) { /* If bus is free, generate Start condition */ if(I2CM_CHECK_I2C_STATUS(I2CM_I2C_STATUS_BUS_BUSY)) { errStatus = I2CM_I2C_MSTR_BUS_BUSY; } else { I2CM_DisableInt(); /* Lock from interruption */ #if (!I2CM_CY_SCBIP_V0 && \ I2CM_I2C_MULTI_MASTER_SLAVE_CONST && I2CM_I2C_WAKE_ENABLE_CONST) I2CM_I2CMasterDisableEcAm(); #endif /* (!I2CM_CY_SCBIP_V0) */ slaveAddress = I2CM_GET_I2C_8BIT_ADDRESS(slaveAddress); if(0u == bitRnW) /* Write direction */ { I2CM_state = I2CM_I2C_FSM_MSTR_WR_DATA; } else /* Read direction */ { I2CM_state = I2CM_I2C_FSM_MSTR_RD_DATA; slaveAddress |= I2CM_I2C_READ_FLAG; } /* TX and RX FIFO have to be EMPTY */ I2CM_TX_FIFO_WR_REG = slaveAddress; /* Put address in TX FIFO */ I2CM_ClearMasterInterruptSource(I2CM_INTR_MASTER_ALL); I2CM_I2C_MASTER_GENERATE_START; while(!I2CM_CHECK_INTR_MASTER(I2CM_INTR_MASTER_I2C_ACK | I2CM_INTR_MASTER_I2C_NACK | I2CM_INTR_MASTER_I2C_ARB_LOST | I2CM_INTR_MASTER_I2C_BUS_ERROR)) { /* * Write: wait until address has been transferred * Read : wait until address has been transferred, data byte is going to RX FIFO as well. */ } /* Check the results of the address phase */ if(I2CM_CHECK_INTR_MASTER(I2CM_INTR_MASTER_I2C_ACK)) { errStatus = I2CM_I2C_MSTR_NO_ERROR; } else if(I2CM_CHECK_INTR_MASTER(I2CM_INTR_MASTER_I2C_NACK)) { errStatus = I2CM_I2C_MSTR_ERR_LB_NAK; } else if(I2CM_CHECK_INTR_MASTER(I2CM_INTR_MASTER_I2C_ARB_LOST)) { I2CM_state = I2CM_I2C_FSM_IDLE; errStatus = I2CM_I2C_MSTR_ERR_ARB_LOST; resetIp = I2CM_I2C_RESET_ERROR; } else /* I2CM_INTR_MASTER_I2C_BUS_ERROR set is else condition */ { I2CM_state = I2CM_I2C_FSM_IDLE; errStatus = I2CM_I2C_MSTR_ERR_BUS_ERR; resetIp = I2CM_I2C_RESET_ERROR; } I2CM_ClearMasterInterruptSource(I2CM_INTR_MASTER_I2C_ACK | I2CM_INTR_MASTER_I2C_NACK | I2CM_INTR_MASTER_I2C_ARB_LOST | I2CM_INTR_MASTER_I2C_BUS_ERROR); /* Reset block in case of: LOST_ARB or BUS_ERR */ if(0u != resetIp) { I2CM_SCB_SW_RESET; } } } return(errStatus); }
/******************************************************************************* * Function Name: I2CM_I2CMasterReadBuf ****************************************************************************//** * * Automatically reads an entire buffer of data from a slave device. * Once the data transfer is initiated by this function, further data transfer * is handled by the included ISR. * Enables the I2C interrupt and clears I2CM_I2C_MSTAT_RD_CMPLT * status. * * \param slaveAddr: 7-bit slave address. * \param xferData: Pointer to buffer of data to be sent. * \param cnt: Size of buffer to send. * \param mode: Transfer mode defines: * (1) Whether a start or restart condition is generated at the beginning * of the transfer, and * (2) Whether the transfer is completed or halted before the stop * condition is generated on the bus.Transfer mode, mode constants may * be ORed together. See I2CM_I2CMasterWriteBuf() * function for constants. * * \return * Error status.See I2CM_I2CMasterWriteBuf() * function for constants. * * \globalvars * I2CM_mstrStatus - used to store current status of I2C Master. * I2CM_state - used to store current state of software FSM. * I2CM_mstrControl - used to control master end of transaction with * or without the Stop generation. * I2CM_mstrRdBufPtr - used to store pointer to master read buffer. * I2CM_mstrRdBufIndex - used to current index within master read * buffer. * I2CM_mstrRdBufSize - used to store master read buffer size. * *******************************************************************************/ uint32 I2CM_I2CMasterReadBuf(uint32 slaveAddress, uint8 * rdData, uint32 cnt, uint32 mode) { uint32 errStatus; errStatus = I2CM_I2C_MSTR_NOT_READY; if(NULL != rdData) { /* Check FSM state and bus before generating Start/ReStart condition */ if(I2CM_CHECK_I2C_FSM_IDLE) { I2CM_DisableInt(); /* Lock from interruption */ /* Check bus state */ errStatus = I2CM_CHECK_I2C_STATUS(I2CM_I2C_STATUS_BUS_BUSY) ? I2CM_I2C_MSTR_BUS_BUSY : I2CM_I2C_MSTR_NO_ERROR; } else if(I2CM_CHECK_I2C_FSM_HALT) { I2CM_mstrStatus &= (uint16) ~I2CM_I2C_MSTAT_XFER_HALT; errStatus = I2CM_I2C_MSTR_NO_ERROR; } else { /* Unexpected FSM state: exit */ } } /* Check master ready to proceed */ if(I2CM_I2C_MSTR_NO_ERROR == errStatus) /* No error proceed */ { #if (!I2CM_CY_SCBIP_V0 && \ I2CM_I2C_MULTI_MASTER_SLAVE_CONST && I2CM_I2C_WAKE_ENABLE_CONST) I2CM_I2CMasterDisableEcAm(); #endif /* (!I2CM_CY_SCBIP_V0) */ /* Set up read transaction */ I2CM_state = I2CM_I2C_FSM_MSTR_RD_ADDR; I2CM_mstrRdBufIndex = 0u; I2CM_mstrRdBufSize = cnt; I2CM_mstrRdBufPtr = (volatile uint8 *) rdData; I2CM_mstrControl = (uint8) mode; slaveAddress = (I2CM_GET_I2C_8BIT_ADDRESS(slaveAddress) | I2CM_I2C_READ_FLAG); I2CM_mstrStatus &= (uint16) ~I2CM_I2C_MSTAT_RD_CMPLT; I2CM_ClearMasterInterruptSource(I2CM_INTR_MASTER_ALL); /* TX and RX FIFO have to be EMPTY */ /* Prepare reading */ if(I2CM_mstrRdBufSize < I2CM_I2C_FIFO_SIZE) { /* Reading byte-by-byte */ I2CM_SetRxInterruptMode(I2CM_INTR_RX_NOT_EMPTY); } else { /* Receive RX FIFO chunks */ I2CM_ENABLE_MASTER_AUTO_DATA_ACK; I2CM_SetRxInterruptMode(I2CM_INTR_RX_FULL); } /* Generate Start or ReStart */ if(I2CM_CHECK_I2C_MODE_RESTART(mode)) { I2CM_I2C_MASTER_GENERATE_RESTART; I2CM_TX_FIFO_WR_REG = (slaveAddress); } else { I2CM_TX_FIFO_WR_REG = (slaveAddress); I2CM_I2C_MASTER_GENERATE_START; } } I2CM_EnableInt(); /* Release lock */ return(errStatus); }