|   實例解析linux內核I2C體系結構(1)  時間:2016-12-30作者:華清(qing)遠(yuan)見 一、概述 談(tan)到(dao)在linux系統下(xia)編寫(xie)I2C驅(qu)動,目前主要(yao)有兩(liang)種方式,一種是(shi)把(ba)I2C設備當(dang)作(zuo)一個(ge)普通的字符設備來(lai)處理,另一種是(shi)利(li)用linux I2C驅(qu)動體系結構來(lai)完成。下(xia)面比較下(xia)這兩(liang)種驅(qu)動。 
	第一種方法的好處(對應第二種方法的劣勢)有: 
	第一種方法問題(對應第二種方法的好處)有: 本(ben)文針對的(de)對象是熟悉I2C協議,并且想使用linux內核子系(xi)統的(de)開發人(ren)員。 網絡(luo)和一些書籍上有介紹I2C子(zi)系統的(de)源碼結構(gou)。但發現(xian)很多開(kai)發人員看了這些文章后(hou),還(huan)是不清楚自(zi)己究(jiu)竟該做些什么(me)。究(jiu)其原因還(huan)是沒弄清楚I2C子(zi)系統為我們做了些什么(me),以(yi)及(ji)我們怎樣利(li)(li)用(yong)I2C子(zi)系統。本(ben)文首先要解決(jue)是如何利(li)(li)用(yong)現(xian)有內(nei)核支持的(de)I2C適(shi)配器(qi),完成對I2C設備的(de)操作,然后(hou)再過度(du)到適(shi)配器(qi)代(dai)碼的(de)編寫。本(ben)文主要從解決(jue)問(wen)題的(de)角度(du)去(qu)寫,不會(hui)涉及(ji)特別(bie)詳細的(de)代(dai)碼跟(gen)蹤。 二、I2C設(she)備驅動程序編寫(xie) 首先要(yao)明確適(shi)配器驅動的作用是讓我們能夠(gou)通過(guo)它發出符合I2C標準協議的時序。 在Linux內核(he)源(yuan)代碼中的(de)(de)drivers/i2c/busses目錄下(xia)(xia)包含著一(yi)些適配器的(de)(de)驅動(dong)。如S3C2410的(de)(de)驅動(dong)i2c-s3c2410.c。當適配器加載到內核(he)后,接下(xia)(xia)來的(de)(de)工作就要針對具體的(de)(de)設備(bei)(bei)編寫設備(bei)(bei)驅動(dong)了。 編寫(xie)I2C設(she)(she)備(bei)(bei)(bei)驅(qu)動也有兩種方法(fa)。一(yi)種是(shi)利用(yong)系統給我們提供的(de)i2c-dev.c來實現(xian)一(yi)個i2c適配(pei)器的(de)設(she)(she)備(bei)(bei)(bei)文(wen)件(jian)。然后(hou)通過在應用(yong)層操(cao)作i2c適配(pei)器來控制i2c設(she)(she)備(bei)(bei)(bei)。另一(yi)種是(shi)為i2c設(she)(she)備(bei)(bei)(bei),獨立編寫(xie)一(yi)個設(she)(she)備(bei)(bei)(bei)驅(qu)動。注意:在后(hou)一(yi)種情況下,是(shi)不需要使用(yong)i2c-dev.c的(de)。 1、利用i2c-dev.c操作適配器,進而控制i2c設備 i2c-dev.c并沒有針對特定(ding)的(de)(de)設(she)備(bei)(bei)而設(she)計,只(zhi)是提供了通用的(de)(de)read()、write()和ioctl()等(deng)接(jie)口,應用層可(ke)以(yi)借用這(zhe)些(xie)接(jie)口訪問掛(gua)接(jie)在適配器上的(de)(de)i2c設(she)備(bei)(bei)的(de)(de)存(cun)儲空間或寄存(cun)器,并控制I2C設(she)備(bei)(bei)的(de)(de)工作(zuo)方式。 需要特(te)別(bie)注意的(de)是(shi):i2c-dev.c的(de)read()、write()方(fang)法都只適合于如(ru)下方(fang)式(shi)的(de)數(shu)據(ju)格式(shi)(可查(cha)看內核(he)相關源碼) 
	 圖(tu)1 單開始信號(hao)時序 所(suo)以(yi)不(bu)具有太強的通用(yong)性,如下面這種情況就不(bu)適用(yong)(通常出現(xian)在讀目(mu)標時)。 
	 圖2 多開始信(xin)號時序 而(er)且(qie)read()、write()方法只適(shi)用用于適(shi)配(pei)器支持(chi)i2c算法的情況(kuang),如: 
	static const struct i2c_algorithm s3c24xx_i2c_algorithm = { 
	而不適合適配器只支持smbus算法的情況,如: 基于上(shang)面(mian)幾個原因,所以一般(ban)都不會使用i2c-dev.c的(de)read()、write()方(fang)法。常(chang)用的(de)是ioctl()方(fang)法。ioctl()方(fang)法可以實現上(shang)面(mian)所有的(de)情況(兩種數據格式、以及I2C算法和(he)smbus算法)。 
	針對i2c的算法,需要熟悉struct i2c_rdwr_ioctl_data 、struct i2c_msg。使用的命令是I2C_RDWR。 
	針對smbus算法,需要熟悉struct i2c_smbus_ioctl_data。使用的命令是I2C_SMBUS。對于smbus算法,不需要考慮“多開始信號時序”問題。 下面以一個實例講解操(cao)作的具體過程(cheng)。通過S3C2410操(cao)作AT24C02 e2prom。實現在AT24C02中任(ren)意(yi)位(wei)置的讀、寫(xie)功能。 
	首先在內核中已經包含了對s3c2410 中的i2c控制器驅動的支持。提供了i2c算法(非smbus類型的,所以后面的ioctl的命令是I2C_RDWR) 另(ling)外一方面需(xu)要(yao)確(que)定(ding)(ding)為(wei)了實現對AT24C02 e2prom的操作,需(xu)要(yao)確(que)定(ding)(ding)AT24C02的地址及讀寫訪問時(shi)序。 ●  AT24C02地(di)址(zhi)的(de)確定 
	 
	 原(yuan)理圖上(shang)將(jiang)A2、A1、A0都接(jie)地了(le),所以地址是0x50。 ●   AT24C02任(ren)意地址字(zi)節(jie)寫的(de)時序 
	 可見此時(shi)序符(fu)合前面提(ti)到的“單開(kai)始信號時(shi)序” ● AT24C02任意地(di)址字節(jie)讀(du)的時序(xu) 
	 可(ke)見此時序符合前面(mian)提(ti)到的“多開(kai)始信號時序” 
	下面開始具體代碼的分析(代碼在2.6.22內核上測試通過): 
	struct i2c_msg 
	struct i2c_rdwr_ioctl_data 
	/***********主程序***********/ 
	        ret=ioctl(fd,I2C_RDWR,(unsigned long)&e2prom_data); 
	        ret=ioctl(fd,I2C_RDWR,(unsigned long)&e2prom_data); 
	以上講述了一種比較常用的利用i2c-dev.c操作i2c設備的方法,這種方法可以說是在應用層完成了對具體i2c設備的驅動工作。 (1)在內核里寫i2c設備驅動的兩(liang)種(zhong)方式: 
	●    Probe方式(new style),如: 
	●    Adapter方式(LEGACY),如: (2)適配器驅動編寫方法 
	(3)分享一些項目中遇到的問題 
 發表評論 
 |