/******************************************************************************* * Function Name: I2C_1_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 I2C_1_Stop(void) { #if (I2C_1_SCB_IRQ_INTERNAL) I2C_1_DisableInt(); #endif /* (I2C_1_SCB_IRQ_INTERNAL) */ /* Call Stop function specific to current operation mode */ I2C_1_ScbModeStop(); /* Disable SCB IP */ I2C_1_CTRL_REG &= (uint32) ~I2C_1_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. */ I2C_1_SetTxInterruptMode(I2C_1_NO_INTR_SOURCES); #if (I2C_1_SCB_IRQ_INTERNAL) I2C_1_ClearPendingInt(); #endif /* (I2C_1_SCB_IRQ_INTERNAL) */ }
/******************************************************************************* * Function Name: I2C_1_I2CMasterClearWriteBuf ******************************************************************************** * * Summary: * Resets the write buffer pointer back to the first byte in the buffer. * * Parameters: * None * * Return: * None * * Global variables: * I2C_1_mstrRdBufIndex - used to current index within master read * buffer. * I2C_1_mstrStatus - used to store current status of I2C Master. * *******************************************************************************/ void I2C_1_I2CMasterClearWriteBuf(void) { I2C_1_DisableInt(); /* Lock from interruption */ I2C_1_mstrWrBufIndex = 0u; I2C_1_mstrStatus &= (uint16) ~I2C_1_I2C_MSTAT_WR_CMPLT; I2C_1_EnableInt(); /* Release lock */ }
/******************************************************************************* * Function Name: I2C_1_I2CSlaveClearReadStatus ******************************************************************************** * * Summary: * Clears the read status flags and returns their values. No other status flags * are affected. * * Parameters: * None * * Return: * Current read status of I2C slave. * * Global variables: * I2C_1_slStatus - used to store current status of I2C slave. * *******************************************************************************/ uint32 I2C_1_I2CSlaveClearReadStatus(void) { uint32 status; I2C_1_DisableInt(); /* Lock from interruption */ /* Mask of transfer complete flag and error status */ status = ((uint32) I2C_1_slStatus & I2C_1_I2C_SSTAT_RD_MASK); I2C_1_slStatus &= (uint8) ~I2C_1_I2C_SSTAT_RD_CLEAR; I2C_1_EnableInt(); /* Release lock */ return(status); }
/******************************************************************************* * Function Name: I2C_1_I2CSlaveInitWriteBuf ******************************************************************************** * * Summary: * Sets the buffer pointer and size of the read buffer. This function also * resets the transfer count returned with the I2C_SlaveGetReadBufSize function. * * Parameters: * writeBuf: Pointer to the data buffer to be read by the master. * bufSize: Size of the buffer exposed to the I2C master. * * Return: * None * * Global variables: * I2C_1_slWrBufPtr - used to store pointer to slave write buffer. * I2C_1_slWrBufSize - used to store salve write buffer size. * I2C_1_slWrBufIndex - used to store current index within slave * write buffer. * * Side Effects: * If this function is called during a bus transaction, data from the previous * buffer location and the beginning of current buffer may be transmitted. * *******************************************************************************/ void I2C_1_I2CSlaveInitWriteBuf(uint8 * wrBuf, uint32 bufSize) { /* Check buffer pointer */ if(NULL != wrBuf) { I2C_1_DisableInt(); /* Lock from interruption */ I2C_1_slWrBufPtr = (volatile uint8 *) wrBuf; /* Set buffer pointer */ I2C_1_slWrBufSize = bufSize; /* Set buffer size */ I2C_1_slWrBufIndex = 0u; /* Clear buffer index */ I2C_1_EnableInt(); /* Release lock */ } }
/******************************************************************************* * Function Name: I2C_1_Stop ******************************************************************************** * * Summary: * Disables the SCB component and its interrupt. * * Parameters: * None * * Return: * None * *******************************************************************************/ void I2C_1_Stop(void) { #if(I2C_1_SCB_IRQ_INTERNAL) I2C_1_DisableInt(); #endif /* (I2C_1_SCB_IRQ_INTERNAL) */ I2C_1_CTRL_REG &= (uint32) ~I2C_1_CTRL_ENABLED; /* Disable scb IP */ #if(I2C_1_SCB_IRQ_INTERNAL) I2C_1_ClearPendingInt(); #endif /* (I2C_1_SCB_IRQ_INTERNAL) */ I2C_1_ScbModeStop(); /* Calls scbMode specific Stop function */ }
/******************************************************************************* * Function Name: I2C_1_I2CMasterClearStatus ******************************************************************************** * * Summary: * Clears all status flags and returns the master status. * * Parameters: * None * * Return: * Current status of I2C master. * * Global variables: * I2C_1_mstrStatus - used to store current status of I2C Master. * *******************************************************************************/ uint32 I2C_1_I2CMasterClearStatus(void) { uint32 status; I2C_1_DisableInt(); /* Lock from interruption */ /* Read and clear master status */ status = (uint32) I2C_1_mstrStatus; I2C_1_mstrStatus = I2C_1_I2C_MSTAT_CLEAR; I2C_1_EnableInt(); /* Release lock */ return(status); }
/******************************************************************************* * Function Name: I2C_1_I2CSlaveInitReadBuf ******************************************************************************** * * Summary: * Sets the buffer pointer and size of the read buffer. This function also * resets the transfer count returned with the I2C_SlaveGetReadBufSize function. * * Parameters: * readBuf: Pointer to the data buffer to be read by the master. * bufSize: Size of the read buffer exposed to the I2C master. * * Return: * None * * Global variables: * I2C_1_slRdBufPtr - used to store pointer to slave read buffer. * I2C_1_slRdBufSize - used to store salve read buffer size. * I2C_1_slRdBufIndex - used to store current index within slave * read buffer. * * Side Effects: * If this function is called during a bus transaction, data from the previous * buffer location and the beginning of current buffer may be transmitted. * *******************************************************************************/ void I2C_1_I2CSlaveInitReadBuf(uint8 * rdBuf, uint32 bufSize) { /* Check for proper buffer */ if(NULL != rdBuf) { I2C_1_DisableInt(); /* Lock from interruption */ I2C_1_slRdBufPtr = (volatile uint8 *) rdBuf; /* Set buffer pointer */ I2C_1_slRdBufSize = bufSize; /* Set buffer size */ I2C_1_slRdBufIndex = 0u; /* Clear buffer index */ I2C_1_slRdBufIndexTmp = 0u; /* Clear buffer index */ I2C_1_EnableInt(); /* Release lock */ } }
/******************************************************************************* * Function Name: I2C_1_I2CMasterStatus ******************************************************************************** * * Summary: * Returns the master's communication status. * * Parameters: * None * * Return: * Current status of I2C master. * * Global variables: * I2C_1_mstrStatus - used to store current status of I2C Master. * *******************************************************************************/ uint32 I2C_1_I2CMasterStatus(void) { uint32 status; I2C_1_DisableInt(); /* Lock from interruption */ status = (uint32) I2C_1_mstrStatus; if (I2C_1_CHECK_I2C_MASTER_ACTIVE) { /* Add status of master pending transaction: MSTAT_XFER_INP */ status |= (uint32) I2C_1_I2C_MSTAT_XFER_INP; } I2C_1_EnableInt(); /* Release lock */ return(status); }
/******************************************************************************* * Function Name: I2C_1_Stop ******************************************************************************** * * Summary: * Disables I2C hardware and disables I2C interrupt. Disables Active mode power * template bits or clock gating as appropriate. * * Parameters: * None * * Return: * None * *******************************************************************************/ void I2C_1_Stop(void) { #if((I2C_1_FF_IMPLEMENTED) || \ (I2C_1_UDB_IMPLEMENTED && I2C_1_MODE_SLAVE_ENABLED)) uint8 enableInterrupts; #endif /* ((I2C_1_FF_IMPLEMENTED) || \ (I2C_1_UDB_IMPLEMENTED && I2C_1_MODE_SLAVE_ENABLED)) */ I2C_1_DisableInt(); I2C_1_DISABLE_INT_ON_STOP; /* Interrupt on Stop can be enabled by write */ (void) I2C_1_CSR_REG; /* Clear CSR reg */ #if(I2C_1_TIMEOUT_ENABLED) I2C_1_TimeoutStop(); #endif /* End (I2C_1_TIMEOUT_ENABLED) */ #if(I2C_1_FF_IMPLEMENTED) #if(CY_PSOC3 || CY_PSOC5LP) /* Store registers which are held in reset when Master and Slave bits are cleared */ #if(I2C_1_MODE_SLAVE_ENABLED) I2C_1_backup.addr = I2C_1_ADDR_REG; #endif /* (I2C_1_MODE_SLAVE_ENABLED) */ I2C_1_backup.clkDiv1 = I2C_1_CLKDIV1_REG; I2C_1_backup.clkDiv2 = I2C_1_CLKDIV2_REG; /* Reset FF block */ I2C_1_CFG_REG &= ((uint8) ~I2C_1_ENABLE_MS); CyDelayUs(I2C_1_FF_RESET_DELAY); I2C_1_CFG_REG |= ((uint8) I2C_1_ENABLE_MS); /* Restore registers */ #if(I2C_1_MODE_SLAVE_ENABLED) I2C_1_ADDR_REG = I2C_1_backup.addr; #endif /* (I2C_1_MODE_SLAVE_ENABLED) */ I2C_1_CLKDIV1_REG = I2C_1_backup.clkDiv1; I2C_1_CLKDIV2_REG = I2C_1_backup.clkDiv2; #endif /* (CY_PSOC3 || CY_PSOC5LP) */ /* Disable power to I2C block */ enableInterrupts = CyEnterCriticalSection(); I2C_1_ACT_PWRMGR_REG &= ((uint8) ~I2C_1_ACT_PWR_EN); I2C_1_STBY_PWRMGR_REG &= ((uint8) ~I2C_1_STBY_PWR_EN); CyExitCriticalSection(enableInterrupts); #else #if(I2C_1_MODE_SLAVE_ENABLED) /* Disable slave bit counter */ enableInterrupts = CyEnterCriticalSection(); I2C_1_COUNTER_AUX_CTL_REG &= ((uint8) ~I2C_1_CNT7_ENABLE); CyExitCriticalSection(enableInterrupts); #endif /* (I2C_1_MODE_SLAVE_ENABLED) */ I2C_1_CFG_REG &= ((uint8) ~I2C_1_ENABLE_MS); #endif /* (I2C_1_FF_IMPLEMENTED) */ I2C_1_ClearPendingInt(); /* Clear interrupt triggers on reset */ I2C_1_state = I2C_1_SM_IDLE; /* Reset software FSM */ }
/******************************************************************************* * Function Name: I2C_1_I2CMasterWriteBuf ******************************************************************************** * * Summary: * 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 SCB_ I2C_MSTAT_WR_CMPLT status. * * Parameters: * slaveAddr: 7-bit slave address. * xferData: Pointer to buffer of data to be sent. * cnt: Size of buffer to send. * mode: Transfer mode defines: start or restart condition generation at * begin of the transfer and complete the transfer or halt before * generating a stop. * * Return: * Error status. * * Global variables: * I2C_1_mstrStatus - used to store current status of I2C Master. * I2C_1_state - used to store current state of software FSM. * I2C_1_mstrControl - used to control master end of transaction with * or without the Stop generation. * I2C_1_mstrWrBufPtr - used to store pointer to master write buffer. * I2C_1_mstrWrBufIndex - used to current index within master write * buffer. * I2C_1_mstrWrBufSize - used to store master write buffer size. * *******************************************************************************/ uint32 I2C_1_I2CMasterWriteBuf(uint32 slaveAddress, uint8 * wrData, uint32 cnt, uint32 mode) { uint32 errStatus; errStatus = I2C_1_I2C_MSTR_NOT_READY; if(NULL != wrData) /* Check buffer pointer */ { /* Check FSM state and bus before generating Start/ReStart condition */ if(I2C_1_CHECK_I2C_FSM_IDLE) { I2C_1_DisableInt(); /* Lock from interruption */ /* Check bus state */ errStatus = I2C_1_CHECK_I2C_STATUS(I2C_1_I2C_STATUS_BUS_BUSY) ? I2C_1_I2C_MSTR_BUS_BUSY : I2C_1_I2C_MSTR_NO_ERROR; } else if(I2C_1_CHECK_I2C_FSM_HALT) { I2C_1_mstrStatus &= (uint16) ~I2C_1_I2C_MSTAT_XFER_HALT; errStatus = I2C_1_I2C_MSTR_NO_ERROR; } else { /* Unexpected FSM state: exit */ } } /* Check if master is ready to start */ if(I2C_1_I2C_MSTR_NO_ERROR == errStatus) /* No error proceed */ { #if (!I2C_1_CY_SCBIP_V0 && \ I2C_1_I2C_MULTI_MASTER_SLAVE_CONST && I2C_1_I2C_WAKE_ENABLE_CONST) I2C_1_I2CMasterDisableEcAm(); #endif /* (!I2C_1_CY_SCBIP_V0) */ /* Set up write transaction */ I2C_1_state = I2C_1_I2C_FSM_MSTR_WR_ADDR; I2C_1_mstrWrBufIndexTmp = 0u; I2C_1_mstrWrBufIndex = 0u; I2C_1_mstrWrBufSize = cnt; I2C_1_mstrWrBufPtr = (volatile uint8 *) wrData; I2C_1_mstrControl = (uint8) mode; slaveAddress = I2C_1_GET_I2C_8BIT_ADDRESS(slaveAddress); I2C_1_mstrStatus &= (uint16) ~I2C_1_I2C_MSTAT_WR_CMPLT; I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_ALL); I2C_1_ClearTxInterruptSource(I2C_1_INTR_TX_UNDERFLOW); /* The TX and RX FIFO have to be EMPTY */ /* Generate Start or ReStart */ if(I2C_1_CHECK_I2C_MODE_RESTART(mode)) { I2C_1_I2C_MASTER_GENERATE_RESTART; I2C_1_TX_FIFO_WR_REG = slaveAddress; } else { I2C_1_TX_FIFO_WR_REG = slaveAddress; I2C_1_I2C_MASTER_GENERATE_START; } /* Catch when address is sent */ I2C_1_SetTxInterruptMode(I2C_1_INTR_TX_UNDERFLOW); } I2C_1_EnableInt(); /* Release lock */ return(errStatus); }
/******************************************************************************* * Function Name: I2C_1_I2CMasterSendStart ******************************************************************************** * * Summary: * 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. * * Parameters: * slaveAddress: Right justified 7-bit Slave address (valid range 8 to 120). * bitRnW: Direction of the following transfer. It is defined by * read/write bit within address byte. * * Return: * Erorr status. * * Global variables: * I2C_1_state - used to store current state of software FSM. * *******************************************************************************/ uint32 I2C_1_I2CMasterSendStart(uint32 slaveAddress, uint32 bitRnW) { uint32 resetIp; uint32 errStatus; resetIp = 0u; errStatus = I2C_1_I2C_MSTR_NOT_READY; /* Check FSM state before generating Start condition */ if(I2C_1_CHECK_I2C_FSM_IDLE) { /* If bus is free, generate Start condition */ if(I2C_1_CHECK_I2C_STATUS(I2C_1_I2C_STATUS_BUS_BUSY)) { errStatus = I2C_1_I2C_MSTR_BUS_BUSY; } else { I2C_1_DisableInt(); /* Lock from interruption */ #if (!I2C_1_CY_SCBIP_V0 && \ I2C_1_I2C_MULTI_MASTER_SLAVE_CONST && I2C_1_I2C_WAKE_ENABLE_CONST) I2C_1_I2CMasterDisableEcAm(); #endif /* (!I2C_1_CY_SCBIP_V0) */ slaveAddress = I2C_1_GET_I2C_8BIT_ADDRESS(slaveAddress); if(0u == bitRnW) /* Write direction */ { I2C_1_state = I2C_1_I2C_FSM_MSTR_WR_DATA; } else /* Read direction */ { I2C_1_state = I2C_1_I2C_FSM_MSTR_RD_DATA; slaveAddress |= I2C_1_I2C_READ_FLAG; } /* TX and RX FIFO have to be EMPTY */ I2C_1_TX_FIFO_WR_REG = slaveAddress; /* Put address in TX FIFO */ I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_ALL); I2C_1_I2C_MASTER_GENERATE_START; while(!I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_ACK | I2C_1_INTR_MASTER_I2C_NACK | I2C_1_INTR_MASTER_I2C_ARB_LOST | I2C_1_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(I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_ACK)) { errStatus = I2C_1_I2C_MSTR_NO_ERROR; } else if(I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_NACK)) { errStatus = I2C_1_I2C_MSTR_ERR_LB_NAK; } else if(I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_ARB_LOST)) { I2C_1_state = I2C_1_I2C_FSM_IDLE; errStatus = I2C_1_I2C_MSTR_ERR_ARB_LOST; resetIp = I2C_1_I2C_RESET_ERROR; } else /* I2C_1_INTR_MASTER_I2C_BUS_ERROR set is else condition */ { I2C_1_state = I2C_1_I2C_FSM_IDLE; errStatus = I2C_1_I2C_MSTR_ERR_BUS_ERR; resetIp = I2C_1_I2C_RESET_ERROR; } I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_I2C_ACK | I2C_1_INTR_MASTER_I2C_NACK | I2C_1_INTR_MASTER_I2C_ARB_LOST | I2C_1_INTR_MASTER_I2C_BUS_ERROR); /* Reset block in case of: LOST_ARB or BUS_ERR */ if(0u != resetIp) { I2C_1_SCB_SW_RESET; } } } return(errStatus); }
/******************************************************************************* * Function Name: I2C_1_I2CMasterReadBuf ******************************************************************************** * * Summary: * 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 SCB_ I2C_MSTAT_RD_CMPLT status. * * Parameters: * slaveAddr: 7-bit slave address. * xferData: Pointer to buffer where to put data from slave. * cnt: Size of buffer to read. * mode: Transfer mode defines: start or restart condition generation at * begin of the transfer and complete the transfer or halt before * generating a stop. * * Return: * Error status. * * Global variables: * I2C_1_mstrStatus - used to store current status of I2C Master. * I2C_1_state - used to store current state of software FSM. * I2C_1_mstrControl - used to control master end of transaction with * or without the Stop generation. * I2C_1_mstrRdBufPtr - used to store pointer to master write buffer. * I2C_1_mstrRdBufIndex - used to current index within master write * buffer. * I2C_1_mstrRdBufSize - used to store master write buffer size. * *******************************************************************************/ uint32 I2C_1_I2CMasterReadBuf(uint32 slaveAddress, uint8 * rdData, uint32 cnt, uint32 mode) { uint32 errStatus; errStatus = I2C_1_I2C_MSTR_NOT_READY; if(NULL != rdData) { /* Check FSM state and bus before generating Start/ReStart condition */ if(I2C_1_CHECK_I2C_FSM_IDLE) { I2C_1_DisableInt(); /* Lock from interruption */ /* Check bus state */ errStatus = I2C_1_CHECK_I2C_STATUS(I2C_1_I2C_STATUS_BUS_BUSY) ? I2C_1_I2C_MSTR_BUS_BUSY : I2C_1_I2C_MSTR_NO_ERROR; } else if(I2C_1_CHECK_I2C_FSM_HALT) { I2C_1_mstrStatus &= (uint16) ~I2C_1_I2C_MSTAT_XFER_HALT; errStatus = I2C_1_I2C_MSTR_NO_ERROR; } else { /* Unexpected FSM state: exit */ } } /* Check master ready to proceed */ if(I2C_1_I2C_MSTR_NO_ERROR == errStatus) /* No error proceed */ { #if (!I2C_1_CY_SCBIP_V0 && \ I2C_1_I2C_MULTI_MASTER_SLAVE_CONST && I2C_1_I2C_WAKE_ENABLE_CONST) I2C_1_I2CMasterDisableEcAm(); #endif /* (!I2C_1_CY_SCBIP_V0) */ /* Set up read transaction */ I2C_1_state = I2C_1_I2C_FSM_MSTR_RD_ADDR; I2C_1_mstrRdBufIndex = 0u; I2C_1_mstrRdBufSize = cnt; I2C_1_mstrRdBufPtr = (volatile uint8 *) rdData; I2C_1_mstrControl = (uint8) mode; slaveAddress = (I2C_1_GET_I2C_8BIT_ADDRESS(slaveAddress) | I2C_1_I2C_READ_FLAG); I2C_1_mstrStatus &= (uint16) ~I2C_1_I2C_MSTAT_RD_CMPLT; I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_ALL); /* TX and RX FIFO have to be EMPTY */ /* Generate Start or ReStart */ if(I2C_1_CHECK_I2C_MODE_RESTART(mode)) { I2C_1_I2C_MASTER_GENERATE_RESTART; I2C_1_TX_FIFO_WR_REG = (slaveAddress); } else { I2C_1_TX_FIFO_WR_REG = (slaveAddress); I2C_1_I2C_MASTER_GENERATE_START; } /* Prepare reading */ if(I2C_1_mstrRdBufSize < I2C_1_I2C_FIFO_SIZE) /* Reading byte-by-byte */ { I2C_1_SetRxInterruptMode(I2C_1_INTR_RX_NOT_EMPTY); } else /* Receive RX FIFO chunks */ { I2C_1_ENABLE_MASTER_AUTO_DATA_ACK; I2C_1_SetRxInterruptMode(I2C_1_INTR_RX_FULL); } } I2C_1_EnableInt(); /* Release lock */ return(errStatus); }