📄 ixi2cdrv.c
字号:
ixI2cStsStored = IX_OSAL_READ_LONG(ixI2cSRAddr); \ /* Delay before next read */ \ ixI2cDrvSleep(IX_I2C_US_DELAY_FOR_REG_READ); \} while ((IX_I2C_TRIGGERED != ((ixI2cStsStored & IX_I2C_IDBR_TX_EMPTY_MASK) >>\ IX_I2C_IDBR_TX_EMPTY_LOC)) && \ (numOfTries++ < IX_I2C_NUM_TO_POLL_IDBR_TX_EMPTY)); \ \/* Check if master failed to transmit */ \if(IX_I2C_TRIGGERED != ((ixI2cStsStored & IX_I2C_IDBR_TX_EMPTY_MASK) >> \ IX_I2C_IDBR_TX_EMPTY_LOC)) \{ \ /* Check if transmit failure is due to arbitration loss */ \ if(IX_I2C_TRIGGERED == ((ixI2cStsStored & \ IX_I2C_ARB_LOSS_DETECTED_MASK) >> IX_I2C_ARB_LOSS_DETECTED_LOC)) \ { \ /* Clear the slave address detected bit by writing \ one to the bit location */ \ ixI2cStsStored = \ (IX_I2C_SET_TO_BE_CLEARED << IX_I2C_ARB_LOSS_DETECTED_LOC); \ IX_OSAL_WRITE_LONG(ixI2cSRAddr, ixI2cStsStored); \ ixI2cStatsCounters.ixI2cArbLossCounter++; \ return IX_I2C_MASTER_ARB_LOSS; \ } /* end of arbitration loss */ \ else /* transmit failure */ \ { \ /* increment the stats for number of bytes master has Tx (includes \ slave address) and one byte for master failed to transmit */ \ if(dataXferred != 0) /* slave addr already sent */ \ { \ ixI2cStatsCounters.ixI2cMasterXmitCounter += (dataXferred + 1); \ } /* end of slave addr already sent */ \ ixI2cStatsCounters.ixI2cMasterFailedXmitCounter++; \ return IX_I2C_MASTER_XFER_ERROR; \ } /* end of transmit failure */ \} /* end of master failed to transmit *//* Used in ixI2cDrvWriteTransfer and ixI2cDrvReadTransfer to check for bus error occurences during transfers. If a bus error occurs, then it will send a master abort. */#define IX_I2C_CHECK_FOR_BUS_ERROR \/* Check for bus error due to previous transfer before continuing \ transfering more data by checking the I2C Status Register */ \ixI2cStsStored = IX_OSAL_READ_LONG(ixI2cSRAddr); \if(IX_I2C_TRIGGERED == ((ixI2cStsStored & IX_I2C_BUS_ERROR_DETECTED_MASK) >>\ IX_I2C_BUS_ERROR_DETECTED_LOC)) \{ \ /* Clear the bus error detected bit by writing one to the bit \ location */ \ ixI2cStsStored = \ (IX_I2C_SET_TO_BE_CLEARED << IX_I2C_BUS_ERROR_DETECTED_LOC) | \ (IX_I2C_SET_TO_BE_CLEARED << IX_I2C_IDBR_TX_EMPTY_LOC); \ IX_OSAL_WRITE_LONG(ixI2cSRAddr, ixI2cStsStored); \ \ /* Send master abort signal */ \ ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_MASTER_ABORT_MASK)) | \ (IX_I2C_ENABLE << IX_I2C_MASTER_ABORT_LOC); \ ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_TRANSFER_BYTE_MASK)) | \ (IX_I2C_DISABLE << IX_I2C_TRANSFER_BYTE_LOC); \ IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); \ return IX_I2C_MASTER_BUS_ERROR; \} /* end of bus error detected *//* * section for enums *//* Used in interrupt mode to determine the operation mode */typedef enum{ IX_I2C_SLAVE_READ_OPERATION = 0x0, IX_I2C_SLAVE_WRITE_OPERATION, IX_I2C_MASTER_READ_OPERATION, IX_I2C_MASTER_WRITE_OPERATION, IX_I2C_GENERAL_CALL_OPERATION} IxI2cOperationMode;/* Used in interrupt mode by master in sync mode to determine transfer status */typedef enum{ IX_I2C_INTR_XFER_IN_PROGRESS = 0xFF, IX_I2C_INTR_XFER_SUCCESSFUL = IX_I2C_SUCCESS, IX_I2C_INTR_ARB_LOSS = IX_I2C_MASTER_ARB_LOSS, IX_I2C_INTR_XFER_ERROR = IX_I2C_MASTER_XFER_ERROR, IX_I2C_INTR_BUS_ERROR = IX_I2C_MASTER_BUS_ERROR} IxI2cInterruptTransferStatus;/** * section for typedef *//* typedef for I2C buffer tracker */typedef struct{ char* bufP; /**< pointer to the location of the buffer */ UINT32 offset; /**< offset from the pointer head */ UINT32 bufSize; /**< size of the buffer */ IxI2cXferMode XferMode; /**< USED ONLY IN MASTER: to indicate transaction mode */} IxI2cBufTracker;/** * Private variables defined here *//* Interrupt handler function pointers */PRIVATE IxI2cMasterReadCallbackP ixI2cMasterRdCallbackP = NULL;PRIVATE IxI2cMasterWriteCallbackP ixI2cMasterWrCallbackP = NULL;PRIVATE IxI2cSlaveReadCallbackP ixI2cSlaveRdCallbackP = NULL;PRIVATE IxI2cSlaveWriteCallbackP ixI2cSlaveWrCallbackP = NULL;PRIVATE IxI2cGenCallCallbackP ixI2cGenCallCallbackP = NULL;PRIVATE UINT32 ixI2cBaseAddr = 0;/* Base addr of the I2C registers */PRIVATE UINT32 ixI2cCRAddr = 0; /* Addr of the I2C control register (CR) */PRIVATE UINT32 ixI2cSRAddr = 0; /* Addr of the I2C status register (CR) */PRIVATE UINT32 ixI2cSARAddr = 0;/* Addr of the I2C slave addr register (CR) */PRIVATE UINT32 ixI2cDBRAddr = 0;/* Addr of the I2C data buffer register (CR) */PRIVATE UINT32 ixI2cDelayType = IX_I2C_LOOP_DELAY;/* Storage for the I2C configuration which is used over many functions to increase efficiency */PRIVATE UINT32 ixI2cCfgStored;/* Storage for the I2C status which is used by many functions to avoid declaration of the same struct multiple times */PRIVATE UINT32 ixI2cStsStored;/* Storage for the I2C statistics counters */PRIVATE IxI2cStatsCounters ixI2cStatsCounters;/* Storage for the buffer info that is used for tracking slave or general calls in interrupt mode */PRIVATE IxI2cBufTracker ixI2cSlaveOrGenBufTracker;/* Storage for the buffer info that is used for tracking master in interrupt mode */PRIVATE IxI2cBufTracker ixI2cMasterBufTracker;/* Flag used in interrupt mode to indicate the operation mode - master read, master write, slave read, slave write, or general call. By default it is set to slave read */PRIVATE IxI2cOperationMode ixI2cOpMode = IX_I2C_SLAVE_READ_OPERATION;/* Flag used in interrupt mode to indicate the status of the master transfer - in progress, successful, arb loss, or transfer error */PRIVATE IxI2cInterruptTransferStatus ixI2cIntrXferStatus = IX_I2C_INTR_XFER_SUCCESSFUL;/* Flag to indicate if the mode is interrupt or poll. */PRIVATE BOOL ixI2cInterruptMode = FALSE;/* Flag to indicate if the init has been done and thus not performing some instructions that should not be done more than once (please refer to the init API. Example: memory mapping). if init is called more than once (which is allowed) */PRIVATE BOOL ixI2cInitComplete = FALSE;/** * Private function declaration */PRIVATE void ixI2cDrvInterruptDetected (void);PRIVATE void ixI2cDrvBusErrorHdlr (void);PRIVATE void ixI2cDrvSlaveAddrDetectedHdlr (void);PRIVATE void ixI2cDrvGenCallAddrDetectedHdlr (void);PRIVATE void ixI2cDrvIDBRRxFullHdlr (void);PRIVATE void ixI2cDrvIDBRTxEmptyHdlr (void);PRIVATE void ixI2cDrvArbLossDetectedHdlr (void);PRIVATE void ixI2cDrvSlaveStopDetectedHdlr (void);PRIVATE void ixI2cDrvSleep(UINT32 delay);/** * Function definitions */PUBLIC IX_I2C_STATUSixI2cDrvInit (IxI2cInitVars *initVarsSelected){ UINT32 localTempI2cCfg; /* Check if the hardware supports I2C. By reading the device type, it can be determined if the hardware supports I2C. Currenlty only the IXP46X supports I2C. */ if(IX_FEATURE_CTRL_DEVICE_TYPE_IXP46X != ixFeatureCtrlDeviceRead()) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixI2cDrvInit: There's no dedicated I2C hardware" " support!\n", 0,0,0,0,0,0); return IX_I2C_NOT_SUPPORTED; } /* end of device detected is not IXP46x */ /* Valid parameter check section */ /* Check if the initVarsSelected is NULL */ if(NULL == initVarsSelected) { return IX_I2C_NULL_POINTER; } /* end of initVarsSelected is NULL */ /* Check if the I2C speed mode (100Kbps or 400Kbps) selected is valid */ if(initVarsSelected->I2cSpeedSelect > IX_I2C_FAST_MODE) { return IX_I2C_INVALID_SPEED_MODE_ENUM_VALUE; } /* end of invalid I2cSpeedSelect */ /* Check if the I2C flow mode (interrupt or poll) selected is valid */ if(initVarsSelected->I2cFlowSelect > IX_I2C_INTERRUPT_MODE) { return IX_I2C_INVALID_FLOW_MODE_ENUM_VALUE; } /* end of invalid I2cFlowSelect */ /* Check if the I2C Hardware Address is valid (non-zero) */ if(IX_I2C_INVALID_SLAVE_ADDRESS == initVarsSelected->I2cHWAddr) { return IX_I2C_INVALID_SLAVE_ADDR; } /* end of invalid I2C slave address */ /* Clear I2C Configurations to zero, only client configurations that are non-zero will be set to one in the following */ localTempI2cCfg = 0; /* Set the I2C speed mode selected */ localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_SPEEDMODE_MASK)) | (initVarsSelected->I2cSpeedSelect << IX_I2C_SPEEDMODE_LOC); /* If previously Interrupt Mode was set, then unbind the interrupt and reset callback pointers to NULL */ if(TRUE == ixI2cInterruptMode) { if(IX_SUCCESS != ixOsalIrqUnbind(IX_OSAL_IXP400_I2C_IRQ_LVL)) { return IX_I2C_INT_UNBIND_FAIL; } /* end of ixOsalIrqUnbind */ ixI2cMasterRdCallbackP = NULL; ixI2cMasterWrCallbackP = NULL; ixI2cSlaveRdCallbackP = NULL; ixI2cSlaveWrCallbackP = NULL; ixI2cGenCallCallbackP = NULL; ixI2cInterruptMode = FALSE; } /* end of TRUE == ixI2cInterruptMode */ /* Check if interrupt mode is selected */ if(IX_I2C_INTERRUPT_MODE == initVarsSelected->I2cFlowSelect) { /* Check if configuration is set to respond to slave address */ if(TRUE == initVarsSelected->I2cSlaveAddrResponseEnable) { /* Check if slave callbacks are NULL, then return error */ if((NULL == initVarsSelected->SlaveReadCBP) || (NULL == initVarsSelected->SlaveWriteCBP)) { return IX_I2C_SLAVE_ADDR_CB_MISSING; } /* end of slave callback are NULL */ ixI2cSlaveRdCallbackP = initVarsSelected->SlaveReadCBP; ixI2cSlaveWrCallbackP = initVarsSelected->SlaveWriteCBP; localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_SLAVE_ADDR_DETECT_ENABLE_MASK)) | (IX_I2C_INTERRUPT_ENABLE << IX_I2C_SLAVE_ADDR_DETECT_ENABLE_LOC); localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_SLAVE_STOP_DETECT_ENABLE_MASK)) | (IX_I2C_INTERRUPT_ENABLE << IX_I2C_SLAVE_STOP_DETECT_ENABLE_LOC); } /* end of I2cSlaveAddrResponseEnable == TRUE */ /* Check if configuration is set to respond to general calls */ if(TRUE == initVarsSelected->I2cGenCallResponseEnable) { /* Check gen call callback is NULL, then return error */ if(NULL == initVarsSelected->GenCallCBP) { return IX_I2C_GEN_CALL_CB_MISSING; } /* end of gen call callback is NULL */ localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_SLAVE_ADDR_DETECT_ENABLE_MASK)) | (IX_I2C_INTERRUPT_ENABLE << IX_I2C_SLAVE_ADDR_DETECT_ENABLE_LOC); localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_SLAVE_STOP_DETECT_ENABLE_MASK)) | (IX_I2C_INTERRUPT_ENABLE << IX_I2C_SLAVE_STOP_DETECT_ENABLE_LOC); ixI2cGenCallCallbackP = initVarsSelected->GenCallCBP; } /* end of I2cGenCallResponseEnable == TRUE */ else /* I2cGenCallResponseEnable = FALSE */ { localTempI2cCfg =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -