设为首页 加入收藏

TOP

iMX6平台SylixOS I2C总线驱动开发(一)
2017-03-30 14:17:52 】 浏览:428
Tags:iMX6 平台 SylixOS I2C 总线 驱动 开发


1.原理概述



2.I2C总线驱动概述


I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力,比如起始,停止,应答信号和MasterXfer的实现函数。驱动程序包含初始化I2C总线控制器__i2cHwInit函数,操作函数集(总线传输__i2cTransfer函数,总线控制__i2cMasterCtl函数)。


3.Imx6ul控制器的硬件描述


imx6ul处理器内部集成了一个I2C控制器,通过五个寄存器来进行控制:


I2Cx_IADR I2C地址寄存器


I2Cx_IFDR I2C分频寄存器


I2Cx_I2CR I2C控制寄存器


I2Cx_I2SR I2C状态寄存器


I2Cx_I2DR I2C数据寄存器


通过I2Cx_I2CR,I2Cx_IFDR,I2Cx_I2DR,I2Cx_IADR寄存器操作,可在I2C总线上产生开始位、停止位、数据和地址,而传输的状态则通过I2Cx_I2SR寄存器来获取。



4.I2C总线传输编程状态图



图 21 I2C编程状态



5.技术实现



6.I2C总线驱动框架


imx6ul的I2C总线驱动代码在bspimx6ul/driver_module/iic_drv/src/目录下,如图 31所示:



图 31 I2C总线驱动目录


imx6ul的I2C总线驱动代码在bspimx6ul/driver_module/iic_drv/src/目录下,如__所示:


I2C总线驱动实现基本功能,只要实现如图 32中的四个函数即可。



图 32 I2C总线驱动四个基本函数



7.函数i2cBusCreate


该函数初始化目标电路板i2c总线系统,调用i2cBusFuns函数初始化相应I2C总线系统并创建对应I2C适配器。根据在bspimx6ul/bsp/SylixOS/bsp/ulevk_board/bspboard.h中的I2C配置,初始化相应的I2C总线。



8.函数i2cBusFuns


该函数用于初始化 i2c 总线并获取操作函数集,主要包括了设置芯片管脚复用__i2cIomuxConfig函数,初始化I2C控制器__i2cInit函数,返回操作函数集(总线传输Transfer函数,总线控制MasterCtl函数)。



9.函数__i2cInit


该函数用于初始化I2C控制器,主要包括了初始化I2C使用的信号量,设置时钟频率,指定作从设备时的地址。



10.函数__i2cTransfer


该函数为I2C传输函数,用于在I2C总线上传输和接收数据。



11.驱动程序框架


整个驱动程序的框架如图 33所示:



图 33 驱动程序流程框架



12.BSP中驱动配置


根据imx6ul相关芯片手册,配置寄存器地址并定义I2C通道相关信息结构。如图 34所示:



图 34 I2C通道信息


13.代码实现


14.I2C总线驱动代码



15.i2cBusCreate,i2cBusFuncs的具体实现


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


……


}
 


 


 



PLW_I2C_FUNCS i2cBusFuns (UINT uiChannel)


{


/*


* 设置芯片管脚分配,SylixOS 计数从零开始,而 IMX6UL 手册是从 1 开始,需要注意


*/


__i2cIomuxConfig(uiChannel);


 


/*


* 初始化控制器


*/


if (__i2cInit(&__Gimx6ulI2cChannels[uiChannel]) != ERROR_NONE) {


return (LW_NULL);


}


 


/*


* 返回操作函数集


*/


return (&__Gimx6ulI2cFuncs[uiChannel]);


}
 


 



16.__i2cIomuxConfig的具体实现


 



static VOID __i2cIomuxConfig (UINT uiChannel)


{


……


case 0: /* i2c1的管脚复用 */


IomuxConfig(__I2C1_SCL_REG,


__I2C1_SCL_MASK,


__I2C1_SCL_VAL);


IomuxConfig(__I2C1_SDA_REG,


__I2C1_SDA_MASK,


__I2C1_SDA_VAL);


break;


……


}
 


 



17.__i2cInit,__i2cHwInit的具体实现


 



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;


}


……


}
 


 


 



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));


……


}
 


 



18.__i2cTransfer,__i2cTryTransfer的具体实现


 



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); /* 等待一个机器周期重试 */


}


}


……


}
 


 


 



static INT __i2cTryTransfer (UINT uiChannel,


PLW_I2C_ADAPTER pI2cAdapter,


PLW_I2C_MESSAGE pI2cMsg,


I

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python中struct.pack()函数和stru.. 下一篇Hibernate 悲观锁与乐观锁

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目