程序清单 32 i2cBusCreate的具体实现
VOID i2cBusCreate (VOID) { /* * 打开I2Cx的总线驱动配置,在bspimx6ul/bsp/SylixOS/bsp/ulevk_board/bspboard.h文件中配置 */ …… #ifdef CONFIG_BSP_I2C0 pI2cFuncs = i2cBusFuns(0); /* 创建 i2c0总线适配器 */ if (pI2cFuncs) { API_I2cAdapterCreate("/bus/i2c/0", pI2cFuncs, 10, 1); } #endif …… }程序清单 33 i2cBusFuns的具体实现
PLW_I2C_FUNCS i2cBusFuns (UINT uiChannel) { …… if (__i2cInit(&__Gimx6ulI2cChannels[uiChannel]) != ERROR_NONE) { return (LW_NULL); } return (&__Gimx6ulI2cFuncs[uiChannel]); }__i2cInit,__i2cHwInit的具体实现
__i2cInit函数用于初始化I2C控制器,主要包括了初始化I2C使用的信号量,设置时钟频率,指定作从设备时的地址。如程序清单 34,程序清单 35所示。
程序清单 34 __i2cInit的具体实现
static INT __i2cInit (__IMX6UL_I2C_CHANNEL pI2cChannel) { …… /* * 初始化 I2C 控制器 */ if (__i2cHwInit(pI2cChannel->uiChannel) != ERROR_NONE) { printk(KERN_ERR "imx6ulI2cInit(): failed to init!\n"); goto __error_handle; } …… }程序清单 35 __i2cHwInit的具体实现
static INT __i2cHwInit (UINT uiChannel) { …… /* * 设置时钟频率 */ __i2cSetI2cClk(uiChannel, I2C_BUS_FREQ_MAX); /* * 指定从设备地址 */ uiValue = readw(REG_I2C_IADR(uiChannel)); uiValue &= ~IMXUL_DEFAULT_SLAVE_ID_MASK; uiValue |= IMXUL_DEFAULT_SLAVE_ID; writew(uiValue, REG_I2C_IADR(uiChannel)); …… }__i2cTransfer,__i2cTryTransfer的具体实现
__i2cTransfer函数为I2C传输函数,用于在I2C总线上传输和接收数据。如程序清单 36,程序清单 37所示。
程序清单 36 __i2cTransfer的具体实现
static INT __i2cTransfer (UINT uiChannel, PLW_I2C_ADAPTER pI2cAdapter, PLW_I2C_MESSAGE pI2cMsg, INT iNum) { …… /* * 这里使用了错误重传的功能,若传输失败则多次传输,由于实际应用中传输失败是小概率事件, * 建议此功能放在用户层实现,在驱动方便仅仅完成数据传输和接收更合适。 */ for (i = 0; i < pI2cAdapter->I2CADAPTER_iRetry; i++) { if (__i2cTryTransfer(uiChannel, pI2cAdapter, pI2cMsg, iNum) == iNum) { return (iNum); } else { API_TimeSleep(LW_OPTION_WAIT_A_TICK); /* 等待一个机器周期重试 */ } } …… }