📄 ixi2cdrv.c
字号:
(localTempI2cCfg & (~IX_I2C_GEN_CALL_RESPOND_MASK)) | (IX_I2C_GEN_CALL_DISABLE << IX_I2C_GEN_CALL_RESPOND_LOC); } /* end of I2cGenCallResponseEnable = FALSE */ /* Set Master Callbacks whether it is NULL or not */ ixI2cMasterRdCallbackP = initVarsSelected->MasterReadCBP; ixI2cMasterWrCallbackP = initVarsSelected->MasterWriteCBP; /* Enable all the other interrupt bits */ localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_ARB_LOSS_INT_ENABLE_MASK)) | (IX_I2C_INTERRUPT_ENABLE << IX_I2C_ARB_LOSS_INT_ENABLE_LOC); localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_BUS_ERROR_INT_ENABLE_MASK)) | (IX_I2C_INTERRUPT_ENABLE << IX_I2C_BUS_ERROR_INT_ENABLE_LOC); localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_IDBR_RX_FULL_INT_ENABLE_MASK)) | (IX_I2C_INTERRUPT_ENABLE << IX_I2C_IDBR_RX_FULL_INT_ENABLE_LOC); localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_IDBR_TX_EMPTY_INT_ENABLE_MASK)) | (IX_I2C_INTERRUPT_ENABLE << IX_I2C_IDBR_TX_EMPTY_INT_ENABLE_LOC); /* Bind the I2C to the I2C ISR */ if(IX_SUCCESS != ixOsalIrqBind(IX_OSAL_IXP400_I2C_IRQ_LVL, (IxOsalVoidFnVoidPtr)ixI2cDrvInterruptDetected, NULL)) { ixI2cMasterRdCallbackP = NULL; ixI2cMasterWrCallbackP = NULL; ixI2cSlaveRdCallbackP = NULL; ixI2cSlaveWrCallbackP = NULL; ixI2cGenCallCallbackP = NULL; return IX_I2C_INT_BIND_FAIL; } /* end of ixOsalIrqBind FAIL */ ixI2cInterruptMode = TRUE; } /* end of Flow Mode == INTERRUPT MODE */ else /* I2cFlowSelect == IX_I2C_POLL_MODE */ { if(TRUE != initVarsSelected->I2cGenCallResponseEnable) { localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_GEN_CALL_RESPOND_MASK)) | (IX_I2C_GEN_CALL_DISABLE << IX_I2C_GEN_CALL_RESPOND_LOC); } /* end of TRUE == initVarsSelected->I2cGenCallResponseEnable */ /* Set Interrupt Mode flag to false (poll mode) */ ixI2cInterruptMode = FALSE; } /* end of Flow Mode == POLL MODE */ /* Set the SCL Enable */ if(TRUE == initVarsSelected->SCLEnable) { localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_SCL_ENABLE_MASK)) | (IX_I2C_ENABLE << IX_I2C_SCL_ENABLE_LOC); } /* end of TRUE == initVarsSelected->SCLEnable */ /* Check if I2C Init has been called before to avoid multiple instances of memory mapping */ if(FALSE == ixI2cInitComplete) { /* Memory map the control, status, slave_addrees, and data registers of the I2C */ ixI2cBaseAddr = (UINT32)IX_OSAL_MEM_MAP (IX_OSAL_IXP400_I2C_PHYS_BASE, IX_OSAL_IXP400_I2C_MAP_SIZE); ixI2cCRAddr = ixI2cBaseAddr + IX_I2C_CR_OFFSET; ixI2cSRAddr = ixI2cBaseAddr + IX_I2C_SR_OFFSET; ixI2cSARAddr = ixI2cBaseAddr + IX_I2C_SAR_OFFSET; ixI2cDBRAddr = ixI2cBaseAddr + IX_I2C_DBR_OFFSET; ixI2cDrvStatsReset(); /* Clear the I2C statistics counters */ ixI2cInitComplete = TRUE; /* Set the Init Complete flag so that a call to init will not mem map and clear the stats again*/ } /* end of FALSE == ixI2cInitComplete */ /* Set the I2C Hardware Slave address */ if(TRUE == initVarsSelected->I2cSlaveAddrResponseEnable) { IX_OSAL_WRITE_LONG(ixI2cSARAddr, initVarsSelected->I2cHWAddr & IX_I2C_MASK_7_BITS); } else /* Slave address set to an I2C addr that should not be used */ { IX_OSAL_WRITE_LONG(ixI2cSARAddr, IX_I2C_NOT_TO_BE_USED_I2C_ADDR); } /* end of setting I2C Hardware Slave address */ /* Enable the I2C Unit */ localTempI2cCfg = (localTempI2cCfg & (~IX_I2C_UNIT_ENABLE_MASK)) | (IX_I2C_ENABLE << IX_I2C_UNIT_ENABLE_LOC); /* Check if in interrupt mode */ if(TRUE == ixI2cInterruptMode) { /* Clear the slave address detected bit and slave stop detected bit by writing 1 to the bit location */ ixI2cStsStored = (IX_I2C_SET_TO_BE_CLEARED << IX_I2C_SLAVE_ADDR_DETECTED_LOC) | (IX_I2C_SET_TO_BE_CLEARED << IX_I2C_SLAVE_STOP_DETECTED_LOC); IX_OSAL_WRITE_LONG(ixI2cSRAddr, ixI2cStsStored); } /* end of FALSE == ixI2cInterruptMode */ /* Copy the localTempI2cCfg to the global ixI2cCfgStored and write the client configuration into the I2C Control register */ ixI2cCfgStored = localTempI2cCfg; IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); return IX_I2C_SUCCESS;} /* end of ixI2cDrvInit */PUBLIC IX_I2C_STATUSixI2cDrvUninit(void){ if(TRUE == ixI2cInitComplete) { /* Clear I2C Configurations to zero while disabling the I2C */ ixI2cCfgStored = 0; IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); /* Unbind the I2C ISR if interrupt mode is enabled */ if(TRUE == ixI2cInterruptMode) { if(IX_SUCCESS != ixOsalIrqUnbind(IX_OSAL_IXP400_I2C_IRQ_LVL)) { return IX_I2C_INT_UNBIND_FAIL; } /* end of ixOsalIrqUnbind */ /* Set all callback pointers to NULL */ ixI2cMasterRdCallbackP = NULL; ixI2cMasterWrCallbackP = NULL; ixI2cSlaveRdCallbackP = NULL; ixI2cSlaveWrCallbackP = NULL; ixI2cGenCallCallbackP = NULL; ixI2cInterruptMode = FALSE; } /* end of TRUE == ixI2cInterruptMode */ /* Return the memory that was mapped during init which is the I2C control, status, data buffer, and slave address registers. */ IX_OSAL_MEM_UNMAP(ixI2cBaseAddr); ixI2cInitComplete = FALSE; } /* end of TRUE == ixI2cInitComplete */ else /* FALSE == ixI2cInitComplete */ { return IX_I2C_NOT_INIT; } /* end of FALSE == ixI2cInitComplete */ return IX_I2C_SUCCESS;} /* end of ixI2cDrvUninit */PUBLIC IX_I2C_STATUSixI2cDrvSlaveAddrSet(UINT8 SlaveAddrSet){ /* Disallow this function from running if I2C not initialized */ IX_I2C_INIT_SUCCESS_CHECK("ixI2cDrvSlaveAddrSet"); /* Check if the I2C Hardware Address is valid (non-zero) */ if(IX_I2C_INVALID_SLAVE_ADDRESS == SlaveAddrSet) { return IX_I2C_INVALID_SLAVE_ADDR; } /* end of IX_I2C_INVALID_SLAVE_ADDRESS */ /* Set the I2C Hardware Slave address */ IX_OSAL_WRITE_LONG(ixI2cSARAddr, SlaveAddrSet & IX_I2C_MASK_7_BITS); return IX_I2C_SUCCESS;} /* end of ixI2cDrvSlaveAddrSet */PUBLIC IX_I2C_STATUSixI2cDrvBusScan(void){ UINT8 deviceSlaveAddr = 0; UINT32 numOfSlaveDeviceFound = 0; UINT32 slaveAddrToScan = 0; UINT32 numOfTries = 0; UINT32 storedI2cCfg; /* Disallow this function from running if I2C not initialized */ IX_I2C_INIT_SUCCESS_CHECK("ixI2cDrvBusScan"); /* Obtain the IXP's slave address to skip scanning for its own address */ deviceSlaveAddr = IX_OSAL_READ_LONG(ixI2cSARAddr); /* Store previous configuration before running it's own configuration for scanning the bus */ storedI2cCfg = ixI2cCfgStored; ixI2cCfgStored = 0; /* all interrupts are disabled */ ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_SPEEDMODE_MASK)) | (IX_I2C_NORMAL_MODE << IX_I2C_SPEEDMODE_LOC); ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_UNIT_ENABLE_MASK)) | (IX_I2C_ENABLE << IX_I2C_UNIT_ENABLE_LOC); ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_SCL_ENABLE_MASK)) | (IX_I2C_ENABLE << IX_I2C_SCL_ENABLE_LOC); IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); for(slaveAddrToScan = IX_I2C_MIN_SLAVE_ADDR; slaveAddrToScan <= IX_I2C_MAX_7_BIT_SLAVE_ADDR; slaveAddrToScan++) { /* Skip the IXP's own slave device address */ if(slaveAddrToScan == deviceSlaveAddr) { continue; } /* end of skip device's own slave address */ /* Write SlaveAddr into the IDBR after shifting left 1 bit (LSB is zero indicating a write access for the slave that is to be accessed */ IX_OSAL_WRITE_LONG(ixI2cDBRAddr, (slaveAddrToScan << 1) | IX_I2C_SLAVE_WRITE); /* Enable the start signal to control the bus and the Transfer byte bit to transmit a data byte */ ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_SEND_START_MASK)) | (IX_I2C_ENABLE << IX_I2C_SEND_START_LOC); ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_SEND_STOP_MASK)) | (IX_I2C_DISABLE << IX_I2C_SEND_STOP_LOC); ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_MASTER_ABORT_MASK)) | (IX_I2C_DISABLE << IX_I2C_MASTER_ABORT_LOC); ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_TRANSFER_BYTE_MASK)) | (IX_I2C_ENABLE << IX_I2C_TRANSFER_BYTE_LOC); /* Read the I2C Status Register */ ixI2cStsStored = IX_OSAL_READ_LONG(ixI2cSRAddr); /* Check if the I2C bus is busy before starting transfer */ if(IX_I2C_TRIGGERED == ((ixI2cStsStored & IX_I2C_BUS_BUSY_MASK) >> IX_I2C_BUS_BUSY_LOC)) { /* restore to previous configuration */ ixI2cCfgStored = storedI2cCfg; IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); return IX_I2C_MASTER_BUS_BUSY; } /* end of I2C bus is busy */ /* Write the configuration to the ICR to start the transfer */ IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); numOfTries = 0; /* Reset number of tries to check register */ /* Poll for IDBR Transmit Empty to determine the data in the IDBR has bean transmitted */ do /* IX_I2C_TRIGGERED != ixI2cStsStored.IDBRTxEmpty */ { 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++; /* restore to previous configuration */ ixI2cCfgStored = storedI2cCfg; IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); return IX_I2C_MASTER_ARB_LOSS; } /* end of arbitration loss */ } else /* master has transmitted */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -