




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、IIC設(shè)備驅(qū)動(dòng)程序IIC設(shè)備是一種通過(guò)IIC總線(xiàn)連接的設(shè)備,由于其簡(jiǎn)單性,被廣泛引用于電子系統(tǒng)中。在現(xiàn)代電子系統(tǒng)中,有很多的IIC設(shè)備需要進(jìn)行相互之間通信IIC總線(xiàn)是由PHILIPS公司開(kāi)發(fā)的兩線(xiàn)式串行總線(xiàn),用于連接微處理器和外部IIC設(shè)備。IIC設(shè)備產(chǎn)生于20世紀(jì)80年代,最初專(zhuān)用與音頻和視頻設(shè)備,現(xiàn)在在各種電子設(shè)備中都廣泛應(yīng)用IIC總線(xiàn)有兩條總線(xiàn)線(xiàn)路,一條是串行數(shù)據(jù)線(xiàn)(SDA),一條是串行時(shí)鐘線(xiàn)(SCL)。SDA負(fù)責(zé)數(shù)據(jù)傳輸,SCL負(fù)責(zé)數(shù)據(jù)傳輸?shù)臅r(shí)鐘同步。IIC設(shè)備通過(guò)這兩條總線(xiàn)連接到處理器的IIC總線(xiàn)控制器上。一種典型的設(shè)備連接如圖:與其他總線(xiàn)相比,IIC總線(xiàn)有很多重要的特點(diǎn)。在選擇一種
2、設(shè)備來(lái)完成特定功能時(shí),這些特點(diǎn)是選擇IIC設(shè)備的重要依據(jù)。主要特點(diǎn):1,每一個(gè)連接到總線(xiàn)的設(shè)備都可以通過(guò)唯一的設(shè)備地址單獨(dú)訪(fǎng)問(wèn)2,串行的8位雙向數(shù)據(jù)傳輸,位速率在標(biāo)準(zhǔn)模式下可達(dá)到100kb/s;快速模式下可以達(dá)到400kb/s;告訴模式下可以達(dá)到3.4Mb/s3,總線(xiàn)長(zhǎng)度最長(zhǎng)7.6m左右4,片上濾波器可以增加抗干擾能力,保證數(shù)據(jù)的完成傳輸5,連接到一條IIC總線(xiàn)上的設(shè)備數(shù)量只受到最大電容400pF的限制6,它是一個(gè)多主機(jī)系統(tǒng),在一條總線(xiàn)上可以同時(shí)有多個(gè)主機(jī)存在,通過(guò)沖突檢測(cè)方式和延時(shí)等待防止數(shù)據(jù)不被破壞。同一時(shí)間只能有一個(gè)主機(jī)占用總線(xiàn) IIC總線(xiàn)在傳輸數(shù)據(jù)的過(guò)程中有3種類(lèi)型的信號(hào):開(kāi)
3、始信號(hào)、結(jié)束信號(hào)、和應(yīng)答信號(hào)>>開(kāi)始信號(hào)(S): 當(dāng)SCL為高電平時(shí),SDA由高電平向低電平跳變,表示將要開(kāi)始傳輸數(shù)據(jù)>>結(jié)束信號(hào)(P):當(dāng)SCL為高電平時(shí),SDA由低電平向高電平跳變,表示結(jié)束傳輸數(shù)據(jù)>>響應(yīng)信號(hào)(ACK): 從機(jī)接收到8位數(shù)據(jù)后,在第9個(gè)周期,拉低SDA電平,表示已經(jīng)收到數(shù)據(jù)。這個(gè)信號(hào)稱(chēng)為應(yīng)答信號(hào)開(kāi)始信號(hào)和結(jié)束信號(hào)的波形如下圖:主機(jī):IIC總線(xiàn)中發(fā)送命令的設(shè)備,對(duì)于ARM處理器來(lái)說(shuō),主機(jī)就是IIC控制器從機(jī):接受命令的設(shè)備 主機(jī)向從機(jī)發(fā)送數(shù)據(jù):主機(jī)通過(guò)數(shù)據(jù)線(xiàn)SDA向從機(jī)發(fā)送數(shù)據(jù)。當(dāng)總線(xiàn)空閑時(shí),SDA和SCL信號(hào)都處于高電平。主機(jī)
4、向從機(jī)發(fā)送數(shù)據(jù)的過(guò)程:1,當(dāng)主機(jī)檢測(cè)到總線(xiàn)空閑時(shí),主機(jī)發(fā)出開(kāi)始信號(hào)2,主機(jī)發(fā)送8位數(shù)據(jù)。這8位數(shù)據(jù)的前7位表示從機(jī)地址,第8位表示數(shù)據(jù)的傳輸方向。這時(shí),第8位為0,表示向從機(jī)發(fā)送數(shù)據(jù)3,被選中的從機(jī)發(fā)出響應(yīng)信號(hào)ACK4,從機(jī)傳輸一系列的字節(jié)和響應(yīng)位5,主機(jī)接受這些數(shù)據(jù),并發(fā)出結(jié)束信號(hào)P,完成本次數(shù)據(jù)傳輸 由上圖可知,IIC控制器主要是由4個(gè)寄存器來(lái)完成所有的IIC操作的。IICCON:控制是否發(fā)出ACK信號(hào),是否開(kāi)啟IIC中斷IICSTAT:IICADD:掛載到總線(xiàn)上的從機(jī)地址。該寄存器的7:1表示從機(jī)地址。IICADD寄存器在串行輸出使能位IICSTAT4為0時(shí),才可以寫(xiě)入;在任何
5、時(shí)候可以讀出IICDS:保存將要發(fā)送或者接收到的數(shù)據(jù)。IICCDS在串行輸出使能IICSTAT4為1時(shí),才可以寫(xiě)入;在任何時(shí)間都可以讀出 因?yàn)镮IC設(shè)備種類(lèi)太多,如果每一個(gè)IIC設(shè)備寫(xiě)一個(gè)驅(qū)動(dòng)程序,那么顯得內(nèi)核非常大。不符合軟件工程代碼復(fù)用,所以對(duì)其層次話(huà):這里簡(jiǎn)單的將IIC設(shè)備驅(qū)動(dòng)分為設(shè)備層、總線(xiàn)層。理解這兩個(gè)層次的重點(diǎn)是理解4個(gè)數(shù)據(jù)結(jié)構(gòu),這4個(gè)數(shù)據(jù)結(jié)構(gòu)是i2c_driver、i2c_client、i2c_algorithm、i2c_adapter。i2c_driver、i2c_client屬于設(shè)備層;i2c_algorithm、i2c_adapter屬于總線(xiàn)型。如下圖:設(shè)備層關(guān)系
6、到實(shí)際的IIC設(shè)備,如芯片AT24C08就是一個(gè)IIC設(shè)備??偩€(xiàn)層包括CPU中的IIC總線(xiàn)控制器和控制總線(xiàn)通信的方法。值得注意的是:一個(gè)系統(tǒng)中可能有很多個(gè)總線(xiàn)層,也就是包含多個(gè)總線(xiàn)控制器;也可能有多個(gè)設(shè)備層,包含不同的IIC設(shè)備由IIC總線(xiàn)規(guī)范可知,IIC總線(xiàn)由兩條物理線(xiàn)路組成,這兩條物理線(xiàn)路是SDA和SCL。只要連接到SDA和SCL總線(xiàn)上的設(shè)備都可以叫做IIC設(shè)備。一個(gè)IIC設(shè)備由i2c_client數(shù)據(jù)結(jié)構(gòu)進(jìn)行描述:struct i2c_clientunsigned short flags;
7、160; /標(biāo)志位 unsigned short addr; /設(shè)備的地址,低7位為芯片地址char nameI2C_NAME_SIZE; /設(shè)備的名稱(chēng),最大為20個(gè)字節(jié)struct i2c_adapter *adapter;/依附的適配器i2c_adapter,適配器指明所屬的總線(xiàn)st
8、ruct i2c_driver *driver;/指向設(shè)備對(duì)應(yīng)的驅(qū)動(dòng)程序struct device dev;/設(shè)備結(jié)構(gòu)體int irq;/設(shè)備申請(qǐng)的中斷號(hào)struct list_head list;/連接到總線(xiàn)上的所有設(shè)備struct list_head detected;/已經(jīng)被發(fā)現(xiàn)的設(shè)備鏈表struct completionreleased;/是否已經(jīng)釋放的完成量; 設(shè)備結(jié)構(gòu)體i2c_client中addr的低8位表示設(shè)備地址。設(shè)備地址由讀寫(xiě)位、器件類(lèi)型和自定義地址組成,如下圖:第7位是R/W位,0表示寫(xiě),2表示讀,所以I2C設(shè)備通常有兩個(gè)地址
9、,即讀地址和寫(xiě)地址類(lèi)型器件由中間4位組成,這是由半導(dǎo)體公司生產(chǎn)的時(shí)候就已經(jīng)固化了。自定義類(lèi)型由低3位組成。由用戶(hù)自己設(shè)置,通常的做法如EEPROM這些器件是由外部I芯片的3個(gè)引腳所組合電平?jīng)Q定的(A0,A1,A2)。A0,A1,A2 就是自定義的地址碼。自定義的地址碼只能表示8個(gè)地址,所以同一IIC總線(xiàn)上同一型號(hào)的芯片最多只能掛載8個(gè)。AT24C08的自定義地址碼如圖:A0,A1,A2接低電平,所以自定義地址碼為0;如果在兩個(gè)不同IIC總線(xiàn)上掛接了兩塊類(lèi)型和地址相同的芯片,那么這兩塊芯片的地址相同。這顯然是地址沖突,解決的辦法是為總線(xiàn)適配器指定一個(gè)ID號(hào),那么新的芯片地址就由總線(xiàn)適配器的ID和
10、設(shè)備地址組成除了地址之外,IIC設(shè)備還有一些重要的注意事項(xiàng):1,i2c_client數(shù)據(jù)結(jié)構(gòu)是描述IIC設(shè)備的“模板”,驅(qū)動(dòng)程序的設(shè)備結(jié)構(gòu)中應(yīng)包含該結(jié)構(gòu)2,adapter指向設(shè)備連接的總線(xiàn)適配器,系統(tǒng)可能有多個(gè)總線(xiàn)適配器。內(nèi)核中靜態(tài)指針數(shù)組adapters記錄所有已經(jīng)注冊(cè)的總線(xiàn)適配器設(shè)備3,driver是指向設(shè)備驅(qū)動(dòng)程序,這個(gè)驅(qū)動(dòng)程序是在系統(tǒng)檢測(cè)到設(shè)備存在時(shí)賦值的 IIC設(shè)備驅(qū)動(dòng) i2c_driver:struct i2c_driverint id;
11、160; /驅(qū)動(dòng)標(biāo)識(shí)IDunsigned int class; /驅(qū)動(dòng)的類(lèi)型int (*attach_adapter)(struct i2c_adapter *);
12、160; /當(dāng)檢測(cè)到適配器時(shí)調(diào)用的函數(shù) int (*detach_adapter)(struct i2c_adapter*); /卸載適配器時(shí)調(diào)用的函數(shù)int (*detach_client)(struct i2c_client *) _deprecated;
13、160; /卸載設(shè)備時(shí)調(diào)用的函數(shù) /以下是一種新類(lèi)型驅(qū)動(dòng)需要的函數(shù),這些函數(shù)支持IIC設(shè)備動(dòng)態(tài)插入和拔出。如果不想支持只實(shí)現(xiàn)上面3個(gè)。要不實(shí)現(xiàn)上面3個(gè)。要么實(shí)現(xiàn)下面5個(gè)。不能同時(shí)定義 int (*probe)(struct i2c_client *,const struct i2c_device_id *);&
14、#160; /新類(lèi)型設(shè)備探測(cè)函數(shù) int (*remove)(struct i2c_client *); /新類(lèi)型設(shè)備的移除函數(shù)
15、160; void (*shutdown)(struct i2c_client *); /關(guān)閉IIC設(shè)備 int (*suspend)(struct i2c_client *,pm_messge_t mesg);
16、160; /掛起IIC設(shè)備 int (*resume)(struct i2c_client *); /恢復(fù)IIC設(shè)備
17、160; int (*command)(struct i2c_client *client,unsigned int cmd,void *arg); /使用命令使設(shè)備完成特殊的功能。類(lèi)似ioctl()函數(shù) struct devcie_driver driver; &
18、#160; /設(shè)備驅(qū)動(dòng)結(jié)構(gòu)體 const struct i2c_device_id *id_table;
19、160; /設(shè)備ID表 int (*detect)(struct i2c_client *,int kind,struct i2c_board_info *); /自動(dòng)探測(cè)設(shè)備的回調(diào)函數(shù) const struct i
20、2c_client_address_data *address_data; /設(shè)備所在的地址范圍 struct list_head clients;
21、0; /指向驅(qū)動(dòng)支持的設(shè)備;結(jié)構(gòu)體i2c_driver和i2c_client的關(guān)系較為簡(jiǎn)單,其中i2c_driver表示一個(gè)IIC設(shè)備驅(qū)動(dòng),i2c_client表示一個(gè)IIC設(shè)備。關(guān)系如下圖:IIC總線(xiàn)適配器就是一個(gè)IIC總線(xiàn)控制器,在物理上連接若干個(gè)IIC設(shè)備。IIC總線(xiàn)適配器本質(zhì)上是一個(gè)物理設(shè)備,其主要功能是完成IIC總線(xiàn)控制器相關(guān)的數(shù)據(jù)通信:struct i2c_adapte
22、r struct module *owner; /模塊計(jì)數(shù) unsigned int id;
23、160; /alogorithm的類(lèi)型,定義于i2c_id.h中 unsigned int class;
24、160; /允許探測(cè)的驅(qū)動(dòng)類(lèi)型 const struct i2c_algorithm *algo; /指向適配器的驅(qū)動(dòng)程序
25、; void *algo_data; /指向適配器的私有數(shù)據(jù),根據(jù)不同的情況使用方法不同
26、0; int (*client_register)(struct i2c_client *); /設(shè)備client注冊(cè)時(shí)調(diào)用 int (*client_unregister(struct i2c_client *); /設(shè)備client注銷(xiāo)時(shí)調(diào)用
27、60; u8 level;
28、; struct mutex bus_lock;
29、 /對(duì)總線(xiàn)進(jìn)行操作時(shí),將獲得總線(xiàn)鎖 struct mutex clist_lock ; /鏈表操作的互斥鎖 &
30、#160; int timeout;
31、 /超時(shí)int retries;
32、160; /重試次數(shù) struct device dev; &
33、#160; /指向 適配器的設(shè)備結(jié)構(gòu)體 int nr ;
34、160; struct list_head clients;
35、 /連接總線(xiàn)上的設(shè)備的鏈表 char name48;
36、0; /適配器名稱(chēng) struct completion dev_released; &
37、#160; /用于同步的完成量;每一個(gè)適配器對(duì)應(yīng)一個(gè)驅(qū)動(dòng)程序,該驅(qū)動(dòng)程序描述了適配器與設(shè)備之間的通信方法:struct i2c_algorithm int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msg, int num); &
38、#160; /傳輸函數(shù)指針,指向?qū)崿F(xiàn)IIC總線(xiàn)通信協(xié)議的函數(shù),用來(lái)確定適配器支持那些傳輸類(lèi)型 int (*smbus_xfer)(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size,
39、union i2c_smbus_data *data); /smbus方式傳輸函數(shù)指針,指向?qū)崿F(xiàn)SMBus總線(xiàn)通信協(xié)議的函數(shù)。SMBus和IIC之間可以通過(guò)軟件方式兼容,所以這里提供了一個(gè)函數(shù),但是一般都賦值為NULL u32 (*functionality)(struct i2c_adapter *);
40、60; /返回適配器支持的功能; IIC設(shè)備驅(qū)動(dòng)程序大致可以分為設(shè)備層和總線(xiàn)層。設(shè)備層包括一個(gè)重要的數(shù)據(jù)結(jié)構(gòu),i2c_client。總線(xiàn)層包括兩個(gè)重要的數(shù)據(jù)結(jié)構(gòu),分別是i2c_adapter和i2c_algorithm。一個(gè)i2c_algorithm結(jié)構(gòu)表示適配器對(duì)應(yīng)的傳輸數(shù)據(jù)方法。3個(gè)數(shù)據(jù)結(jié)構(gòu)關(guān)系: IIC設(shè)備層次結(jié)構(gòu)較為簡(jiǎn)單,但是寫(xiě)IIC設(shè)備驅(qū)動(dòng)程序卻相當(dāng)復(fù)雜。IIC設(shè)備驅(qū)動(dòng)程序的步驟:IIC子系統(tǒng):IIC子系統(tǒng)是作為模塊加載到系統(tǒng)中的。初始化函數(shù):static int _i
41、nit i2c_init(void) int retval; /返回值,成功0,錯(cuò)誤返回負(fù)值 retval = bus_register(&i2c_bus_type); /注冊(cè)一條IIC的BUS總線(xiàn) if (retval)
42、0; return retval; retval = class_register(&i2c_adapter_class); /注冊(cè)適配器類(lèi),用于實(shí)現(xiàn)sys文件系統(tǒng)的部分功能 if (retval) goto bus_err; retval = i2c_add_driver(&dummy_driver);
43、 /將一個(gè)空驅(qū)動(dòng)程序注冊(cè)到IIC總線(xiàn)中 if (retval) goto class_err; return 0;class_err: class_unregister(&i2c_adapter_class);
44、0; /類(lèi)注銷(xiāo)bus_err: bus_unregister(&i2c_bus_type);
45、0; /總線(xiàn)注銷(xiāo) return retval; struct bus_type i2c_bus_type = .name
46、; = "i2c", .dev_attrs = i2c_dev_attrs, .match = i2c_device_match, .uevent = i2c_device_uevent, .probe
47、 = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown, .suspend = i2c_device_suspend, .resume
48、0; = i2c_device_resume,;static struct class i2c_adapter_class = .owner = THIS_MODULE, .name = "i2c-adapter",
49、160; .dev_attrs = i2c_adapter_attrs,;static struct i2c_driver dummy_driver = . = "dummy", .probe = dummy_probe, .remove &
50、#160; = dummy_remove, .id_table = dummy_id,; IIC子系統(tǒng)退出函數(shù):static void _exit i2c_exit(void) i2c_del_driver(&dummy_driver); /注銷(xiāo)IIC設(shè)備驅(qū)動(dòng)程序,主要功能是去掉總線(xiàn)中的該設(shè)備驅(qū)動(dòng)程序
51、class_unregister(&i2c_adapter_class); /注銷(xiāo)適配器類(lèi) bus_unregister(&i2c_bus_type);
52、 /注銷(xiāo)I2C總線(xiàn) 適配器驅(qū)動(dòng)程序是IIC設(shè)備驅(qū)動(dòng)程序需要實(shí)現(xiàn)的主要驅(qū)動(dòng)程序,這個(gè)驅(qū)動(dòng)程序需要根據(jù)具體的適配器硬件來(lái)編寫(xiě)。I2c_adapter結(jié)構(gòu)體為描述各種IIC適配器提供了“模板",它定義了注冊(cè)總線(xiàn)上所有設(shè)備的clients鏈表、指向具體IIC適配器的總線(xiàn)通信方法I2c_algorithm的algo指針、實(shí)現(xiàn)i2c總線(xiàn)的操作原子性的lock信號(hào)量。但i2c_adapter結(jié)構(gòu)體只是所有適配器的共有屬性,并不能代表所有類(lèi)型的適配器 s3c2440對(duì)應(yīng)的適配器為:struct s3c24xx_i2c
53、spinlock_t lock; /lock自旋鎖 wait_queue_head_t wait; /等待隊(duì)列頭。由于IIC設(shè)備是低速設(shè)備,所以可以采取“阻塞-中斷”的驅(qū)動(dòng)模型,即讀寫(xiě)i2c設(shè)備的用戶(hù)程序在IIC設(shè)備操作期間進(jìn)入阻塞狀態(tài),待IIC操作完成后,總線(xiàn)
54、適配器將引發(fā)中斷,再將相應(yīng)的中斷處理函數(shù)中喚醒受阻的用戶(hù)進(jìn)程。該隊(duì)列用來(lái)放阻塞的進(jìn)程 unsigned int suspended:1; /設(shè)備是否掛起 struct i2c_msg *msg; /從適配器到設(shè)備
55、一次傳輸?shù)膯挝?,用這個(gè)結(jié)構(gòu)體將數(shù)據(jù)包裝起來(lái)便于操作 , unsigned int msg_num; /表示消息的個(gè)數(shù) unsigned int msg_idx; /表示第幾個(gè)消
56、息。當(dāng)完成一個(gè)消息后,該值增加 unsigned int msg_ptr; /總是指向當(dāng)前交互中要傳送、接受的下一個(gè)字節(jié),在i2c_msg.buf中的偏移量位置 unsigned int tx_setup;
57、60; /表示寫(xiě)IIC設(shè)備寄存器的一個(gè)時(shí)間,這里被設(shè)置為50ms unsigned int irq; /適配器申請(qǐng)的中斷號(hào)
58、0; enum s3c24xx_i2c_state state; /表示IIC設(shè)備目前的狀態(tài) unsigned long clkrate; /時(shí)鐘速率 void _iomem
59、160; *regs; /IIC設(shè)備寄存器地址 struct clk *clk;
60、 /對(duì)應(yīng)的時(shí)鐘 struct device *dev; /適配器對(duì)應(yīng)的設(shè)備結(jié)構(gòu)體 struct resource *ioarea;
61、; /適配器的資源 struct i2c_adapter adap; /適配器主體結(jié)構(gòu)體#ifdef CONFIG_CPU_FREQ struct notifier_block
62、160; freq_transition;#endif;enum s3c24xx_i2c_state STATE_IDLE, STATE_START, STATE_READ, STATE_WRITE, STATE_STOP; struct i2c_msg _u16
63、 addr; /IIC設(shè)備地址。 這個(gè)字段說(shuō)明一個(gè)適配器在獲得總線(xiàn)控制權(quán)后,可以與多個(gè)IIC設(shè)備進(jìn)行交互。 _u16
64、160; flags; /消息類(lèi)型標(biāo)志 。 #define I2C_M_TEN
65、0; 0x0010 /這是有10位地址芯片#define I2C_M_RD 0x0001 /表示從 從機(jī)到主機(jī)讀數(shù)據(jù)#define I2C_M_NOSTART 0x4000
66、0; / FUNC_PROTOCOL_MANLING協(xié)議的相關(guān)標(biāo)志#define I2C_M_REV_DIR_ADDR 0x2000 /FUNC_PROTOCOL_MANLING協(xié)議的相關(guān)標(biāo)志#define I2C_M_IGNORE_NAK
67、 0x1000 /FUNC_PROTOCOL_MANLING協(xié)議的相關(guān)標(biāo)志#define I2C_M_NO_RD_ACK 0x0800 /FUNC_PROTOCOL_MANLING協(xié)議的相關(guān)標(biāo)
68、志#define I2C_M_RECV_LEN 0x0400 /第一次接收的字節(jié)長(zhǎng)度 _u16 len;
69、160; /消息字節(jié)長(zhǎng)度 _u8
70、160; * buf; &
71、#160; /指向消息數(shù)據(jù)的緩沖區(qū); 當(dāng)拿到一塊新的電路板,并研究了響應(yīng)的IIC適配器之后,就應(yīng)該使用內(nèi)核提供的框架函數(shù)向IIC子系統(tǒng)添加一個(gè)新的適配器過(guò)程:1,分配一個(gè)IIC適配器,并初始化相應(yīng)的變量2,使用i2c_add_adapter()函數(shù)向IIC子系統(tǒng)添加適配器結(jié)構(gòu)體i2c_adapter。這個(gè)結(jié)構(gòu)體已經(jīng)在第一步初始化了:int i2c_add_adapter(struct i2c_adapter *adapter) int id, res = 0;retry: if
72、 (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) = 0) /存放分配ID號(hào)的內(nèi)存 return -ENOMEM;
73、60; /內(nèi)存分配失敗 mutex_lock(&core_lock); /鎖定內(nèi)核鎖 /* "above" here means "above or equal to", sigh */ res = idr_get_new_above(&i2c_adapt
74、er_idr, adapter, _i2c_first_dynamic_bus_num, &id); /分配ID號(hào),并將ID號(hào)和指針關(guān)聯(lián) mutex_unlock(&core_lock);
75、60; /釋放內(nèi)核鎖 if (res < 0) if (res = -EAGAIN) goto retry;
76、; /分配失
77、敗,重試 return res; adapter->nr = id; return i2c_register_adapter(adapter);
78、/ 注冊(cè)適配器設(shè)備 關(guān)于IDR機(jī)制,請(qǐng)參考:ack/archive/2012/09/15/2686557.htmlstatic DEFINE_IDR(i2c_adapter_idr);通過(guò)ID號(hào)獲得適配器指針:struct i2c_adapter* i2c_get_adapter(int id) struct i2c_adapter *adapter;
79、0; /適配器指針 mutex_lock(&core_lock); /鎖定內(nèi)核鎖 adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); /通過(guò)ID號(hào),查詢(xún)適配器指針 if (
80、adapter && !try_module_get(adapter->owner) /適配器引用計(jì)數(shù)+1 adapter = NULL; mutex_unlock(&core_lock);
81、60; /釋放內(nèi)核鎖 return adapter;適配器卸載函數(shù):主要任務(wù):注銷(xiāo)適配器的數(shù)據(jù)結(jié)構(gòu),刪除總線(xiàn)上的所有設(shè)備的I2c_client數(shù)據(jù)結(jié)構(gòu)和對(duì)應(yīng)的i2c_driver驅(qū)動(dòng)程序,并減少其代表總線(xiàn)上所有設(shè)備的相應(yīng)驅(qū)動(dòng)程序數(shù)據(jù)結(jié)構(gòu)的引用計(jì)數(shù)(如果到達(dá)0,則卸載設(shè)備驅(qū)動(dòng)程序):int i2c_del_adapter(struct i2c_adapter
82、*adap) struct i2c_client *client, *_n; int res = 0; mutex_lock(&core_lock); /* First make sure that this adapter was ever added */ if (idr_find(&i2c_adapter_idr, adap->nr) != adap)
83、 /查找要卸載的適配器 pr_debug("i2c-core: attempting to delete unregistered "
84、60; "adapter %sn", adap->name); res = -EINVAL; goto out_unlock; /* Tell drivers about this removal */ res = bus_for_each_drv(&i2c_bus_type, NULL, adap,
85、60; i2c_do_del_adapter); if (res) goto out_unlock; /* detach any active clients. This must be done first, because * it ca
86、n fail; in which case we give up. */ list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) struct i2c_driver *driver; driver = client->driver;
87、; /* new style, follow standard driver model */ if (!driver | is_newstyle_driver(driver) i2c_unregister_device(client); continue;
88、60; /* legacy drivers create and remove clients themselves */ if (res = driver->detach_client(client) dev_err(&adap->dev, "detac
89、h_client failed for client " "%s at address 0x%02xn", client->name, client->addr);
90、60; goto out_unlock; /* clean up the sysfs representation */ init_completion(&adap->dev_released); device_unregister(&adap->dev);
91、0; 設(shè)備注銷(xiāo) /* wait for sysfs to drop all references */ wait_for_completion(&adap->dev_released); /* free bus id */
92、160; idr_remove(&i2c_adapter_idr, adap->nr); /刪除IDR,ID號(hào) dev_dbg(&adap->dev, "adapter %s unregisteredn", adap->name);&
93、#160; /* Clear the device structure in case this adapter is ever going to be added again */ memset(&adap->dev, 0, sizeof(adap->dev); out_unlock: mutex_unlock(&core_lock); return res;II
94、C總線(xiàn)通信方法s3c24xx_i2c_algorithm結(jié)構(gòu)體:static const struct i2c_algorithm s3c24xx_i2c_algorithm = .master_xfer = s3c24xx_i2c_xfer, .functionality = s3c24xx_i2c_func,;這里只實(shí)現(xiàn)了IIC總線(xiàn)通信協(xié)議通信方法因不同的適配器有所不同,
95、要跟據(jù)具體的硬件來(lái)實(shí)現(xiàn)協(xié)議支持函數(shù)s3c24xx_i2c_func()該函數(shù)返回總線(xiàn)支持的協(xié)議,如I2C_FUNC_I2C、I2C_FUNC_SMBUS_EMUL、I2C_FUNC_PROTOCOL_MANGLING協(xié)議:static u32 s3c24xx_i2c_func(struct i2c_adapter *adap) return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;傳輸函數(shù)s3c24xx_i2c_xfer():static int s3c24xx_i2c_
96、xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data; /從適配器的私有數(shù)據(jù)中獲得適配器s3c24xx_i2c結(jié)構(gòu)體 int retry; &
97、#160; &
98、#160; /傳輸錯(cuò)誤重發(fā)次數(shù) int ret;
99、
100、 /返回值 for (retry = 0; retry < adap->
101、retries; retry+) ret = s3c24xx_i2c_doxfer(i2c, msgs, num);
102、 /傳輸?shù)絀IC設(shè)備的具體函數(shù) if (ret != -EAGAIN) return ret; dev_dbg(i2c->dev, "Retrying transmission (%d)n", retry);
103、; /重試信息 udelay(100);
104、60;
105、60; /延時(shí)100us return -EREMOTEIO;
106、0; / I/O錯(cuò)誤真正的傳輸函數(shù):static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
107、; struct i2c_msg *msgs, int num) unsigned long timeout;
108、60;
109、60; /定義一個(gè)傳輸超時(shí)時(shí)間 int ret;
110、
111、 /返回值,傳輸消息的個(gè)數(shù) if (i2c->suspended)
112、
113、 /如果適配器處于掛起省電狀態(tài),則返回 return -EIO; ret = s3c24xx_i2c_set_master(i2c);
114、0; /將適配器設(shè)為主機(jī)發(fā)送狀態(tài),判斷總線(xiàn)忙閑狀態(tài) if (ret != 0)
115、160;
116、160; /如果總線(xiàn)繁忙,則傳輸失敗
117、; dev_err(i2c->dev, "cannot get bus (error %d)n", ret); ret = -EAGAIN; goto out; spin_lock_irq(&i2c->lock);
118、160; /操作適配器的自旋鎖鎖定,每次只允許一個(gè)進(jìn)程傳輸數(shù)據(jù),其他進(jìn)程無(wú)法獲得總線(xiàn) i2c->msg
119、 = msgs;
120、0; /傳輸?shù)南⒅羔?#160; i2c->msg_num = num;
121、160; /傳輸?shù)南€(gè)數(shù) i2c->msg_ptr = 0;
122、160; /當(dāng)前要傳輸?shù)淖止?jié)在消息中的偏移 i2c->msg_idx = 0;
123、 /消息數(shù)組的索引 i2c->state = STAT
124、E_START; s3c24xx_i2c_enable_irq(i2c); /啟動(dòng)適配器中斷信號(hào),允許適配器發(fā)出中斷
125、160; s3c24xx_i2c_message_start(i2c, msgs); /當(dāng)調(diào)用該函數(shù)啟動(dòng) 數(shù)據(jù)發(fā)送后,當(dāng)前進(jìn)程進(jìn)入睡眠狀態(tài),等待中斷到來(lái),所以通過(guò)wait_event_timeout()函數(shù)將自己掛起到s3c24xx_i2c.wait等待隊(duì)列上,直到等待的條件"i2c->msg_num = 0"
126、;為真,或者5s超時(shí)后才能喚醒。注意一次i2c操作可能要涉及多個(gè)字節(jié),只有第一個(gè)字節(jié)發(fā)送是在當(dāng)前進(jìn)程的文件系統(tǒng)操作執(zhí)行流中進(jìn)行的,該字節(jié)操作的完成及后繼字節(jié)的寫(xiě)入都由中斷處理程序來(lái)完成。在此期間當(dāng)前進(jìn)程掛起在s3c24xx_i2c.wait等待隊(duì)列上 spin_unlock_irq(&i2c->lock); timeout = wait_event_timeout(i2c->wait, i2c->msg_num = 0, HZ * 5); ret = i2c-&
127、gt;msg_idx; /* having these next two as dev_err() makes life very * noisy when doing an i2cdetect */ if (timeout = 0)
128、160; /在規(guī)定的時(shí)間內(nèi),沒(méi)有成功的寫(xiě)入數(shù)據(jù) dev_dbg(i2c->dev, "timeoutn"); else if (ret != num)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 計(jì)算機(jī)科學(xué)核心知識(shí)試題及答案
- 法學(xué)概論與人文社會(huì)科學(xué)的交融試題及答案
- 山東省威海文登區(qū)四校聯(lián)考2025屆七下數(shù)學(xué)期末綜合測(cè)試模擬試題含解析
- 信息處理技術(shù)員考試復(fù)習(xí)問(wèn)題集試題及答案
- 增強(qiáng)班級(jí)合作意識(shí)的工作措施計(jì)劃
- 法治文化的內(nèi)涵與外延試題及答案
- 班級(jí)理論知識(shí)競(jìng)賽的組織與實(shí)施計(jì)劃
- 企業(yè)治理與決策科學(xué)的總結(jié)計(jì)劃
- 如何提升工作效率的策略計(jì)劃
- 基于數(shù)據(jù)分析的急診業(yè)務(wù)提升計(jì)劃
- 【MOOC】理解馬克思-南京大學(xué) 中國(guó)大學(xué)慕課MOOC答案
- JGT266-2011 泡沫混凝土標(biāo)準(zhǔn)規(guī)范
- 液化氣站2022年應(yīng)急預(yù)案演練計(jì)劃
- 電纜井工程及電纜鋼管敷設(shè)施工方案
- 各種面試方法詳解
- 窄線(xiàn)寬光纖激光器研究俞本立
- 人教版六年級(jí)下冊(cè)數(shù)學(xué)第五、六單元測(cè)試題及答案
- 常用H型鋼理論重量表格
- 浙江省溫州市2022年初中科學(xué)中考試題及參考答案
- 臨檢、免檢、微檢 知識(shí)點(diǎn)整理
- 食品經(jīng)營(yíng)操作流程圖
評(píng)論
0/150
提交評(píng)論