版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、IIC設(shè)備驅(qū)動程序IIC設(shè)備是一種通過IIC總線連接的設(shè)備,由于其簡單性,被廣泛引用于電子系統(tǒng)中。在現(xiàn)代電子系統(tǒng)中,有很多的IIC設(shè)備需要進(jìn)行相互之間通信IIC總線是由PHILIPS公司開發(fā)的兩線式串行總線,用于連接微處理器和外部IIC設(shè)備。IIC設(shè)備產(chǎn)生于20世紀(jì)80年代,最初專用與音頻和視頻設(shè)備,現(xiàn)在在各種電子設(shè)備中都廣泛應(yīng)用IIC總線有兩條總線線路,一條是串行數(shù)據(jù)線(SDA),一條是串行時鐘線(SCL)。SDA負(fù)責(zé)數(shù)據(jù)傳輸,SCL負(fù)責(zé)數(shù)據(jù)傳輸?shù)臅r鐘同步。IIC設(shè)備通過這兩條總線連接到處理器的IIC總線控制器上。一種典型的設(shè)備連接如圖:與其他總線相比,IIC總線有很多重要的特點。在選擇一種
2、設(shè)備來完成特定功能時,這些特點是選擇IIC設(shè)備的重要依據(jù)。主要特點:1,每一個連接到總線的設(shè)備都可以通過唯一的設(shè)備地址單獨訪問2,串行的8位雙向數(shù)據(jù)傳輸,位速率在標(biāo)準(zhǔn)模式下可達(dá)到100kb/s;快速模式下可以達(dá)到400kb/s;告訴模式下可以達(dá)到3.4Mb/s3,總線長度最長7.6m左右4,片上濾波器可以增加抗干擾能力,保證數(shù)據(jù)的完成傳輸5,連接到一條IIC總線上的設(shè)備數(shù)量只受到最大電容400pF的限制6,它是一個多主機(jī)系統(tǒng),在一條總線上可以同時有多個主機(jī)存在,通過沖突檢測方式和延時等待防止數(shù)據(jù)不被破壞。同一時間只能有一個主機(jī)占用總線 IIC總線在傳輸數(shù)據(jù)的過程中有3種類型的信號:開
3、始信號、結(jié)束信號、和應(yīng)答信號>>開始信號(S): 當(dāng)SCL為高電平時,SDA由高電平向低電平跳變,表示將要開始傳輸數(shù)據(jù)>>結(jié)束信號(P):當(dāng)SCL為高電平時,SDA由低電平向高電平跳變,表示結(jié)束傳輸數(shù)據(jù)>>響應(yīng)信號(ACK): 從機(jī)接收到8位數(shù)據(jù)后,在第9個周期,拉低SDA電平,表示已經(jīng)收到數(shù)據(jù)。這個信號稱為應(yīng)答信號開始信號和結(jié)束信號的波形如下圖:主機(jī):IIC總線中發(fā)送命令的設(shè)備,對于ARM處理器來說,主機(jī)就是IIC控制器從機(jī):接受命令的設(shè)備 主機(jī)向從機(jī)發(fā)送數(shù)據(jù):主機(jī)通過數(shù)據(jù)線SDA向從機(jī)發(fā)送數(shù)據(jù)。當(dāng)總線空閑時,SDA和SCL信號都處于高電平。主機(jī)
4、向從機(jī)發(fā)送數(shù)據(jù)的過程:1,當(dāng)主機(jī)檢測到總線空閑時,主機(jī)發(fā)出開始信號2,主機(jī)發(fā)送8位數(shù)據(jù)。這8位數(shù)據(jù)的前7位表示從機(jī)地址,第8位表示數(shù)據(jù)的傳輸方向。這時,第8位為0,表示向從機(jī)發(fā)送數(shù)據(jù)3,被選中的從機(jī)發(fā)出響應(yīng)信號ACK4,從機(jī)傳輸一系列的字節(jié)和響應(yīng)位5,主機(jī)接受這些數(shù)據(jù),并發(fā)出結(jié)束信號P,完成本次數(shù)據(jù)傳輸 由上圖可知,IIC控制器主要是由4個寄存器來完成所有的IIC操作的。IICCON:控制是否發(fā)出ACK信號,是否開啟IIC中斷IICSTAT:IICADD:掛載到總線上的從機(jī)地址。該寄存器的7:1表示從機(jī)地址。IICADD寄存器在串行輸出使能位IICSTAT4為0時,才可以寫入;在任何
5、時候可以讀出IICDS:保存將要發(fā)送或者接收到的數(shù)據(jù)。IICCDS在串行輸出使能IICSTAT4為1時,才可以寫入;在任何時間都可以讀出 因為IIC設(shè)備種類太多,如果每一個IIC設(shè)備寫一個驅(qū)動程序,那么顯得內(nèi)核非常大。不符合軟件工程代碼復(fù)用,所以對其層次話:這里簡單的將IIC設(shè)備驅(qū)動分為設(shè)備層、總線層。理解這兩個層次的重點是理解4個數(shù)據(jù)結(jié)構(gòu),這4個數(shù)據(jù)結(jié)構(gòu)是i2c_driver、i2c_client、i2c_algorithm、i2c_adapter。i2c_driver、i2c_client屬于設(shè)備層;i2c_algorithm、i2c_adapter屬于總線型。如下圖:設(shè)備層關(guān)系
6、到實際的IIC設(shè)備,如芯片AT24C08就是一個IIC設(shè)備??偩€層包括CPU中的IIC總線控制器和控制總線通信的方法。值得注意的是:一個系統(tǒng)中可能有很多個總線層,也就是包含多個總線控制器;也可能有多個設(shè)備層,包含不同的IIC設(shè)備由IIC總線規(guī)范可知,IIC總線由兩條物理線路組成,這兩條物理線路是SDA和SCL。只要連接到SDA和SCL總線上的設(shè)備都可以叫做IIC設(shè)備。一個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è)備的名稱,最大為20個字節(jié)struct i2c_adapter *adapter;/依附的適配器i2c_adapter,適配器指明所屬的總線st
8、ruct i2c_driver *driver;/指向設(shè)備對應(yīng)的驅(qū)動程序struct device dev;/設(shè)備結(jié)構(gòu)體int irq;/設(shè)備申請的中斷號struct list_head list;/連接到總線上的所有設(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è)備地址由讀寫位、器件類型和自定義地址組成,如下圖:第7位是R/W位,0表示寫,2表示讀,所以I2C設(shè)備通常有兩個地址
9、,即讀地址和寫地址類型器件由中間4位組成,這是由半導(dǎo)體公司生產(chǎn)的時候就已經(jīng)固化了。自定義類型由低3位組成。由用戶自己設(shè)置,通常的做法如EEPROM這些器件是由外部I芯片的3個引腳所組合電平?jīng)Q定的(A0,A1,A2)。A0,A1,A2 就是自定義的地址碼。自定義的地址碼只能表示8個地址,所以同一IIC總線上同一型號的芯片最多只能掛載8個。AT24C08的自定義地址碼如圖:A0,A1,A2接低電平,所以自定義地址碼為0;如果在兩個不同IIC總線上掛接了兩塊類型和地址相同的芯片,那么這兩塊芯片的地址相同。這顯然是地址沖突,解決的辦法是為總線適配器指定一個ID號,那么新的芯片地址就由總線適配器的ID和
10、設(shè)備地址組成除了地址之外,IIC設(shè)備還有一些重要的注意事項:1,i2c_client數(shù)據(jù)結(jié)構(gòu)是描述IIC設(shè)備的“模板”,驅(qū)動程序的設(shè)備結(jié)構(gòu)中應(yīng)包含該結(jié)構(gòu)2,adapter指向設(shè)備連接的總線適配器,系統(tǒng)可能有多個總線適配器。內(nèi)核中靜態(tài)指針數(shù)組adapters記錄所有已經(jīng)注冊的總線適配器設(shè)備3,driver是指向設(shè)備驅(qū)動程序,這個驅(qū)動程序是在系統(tǒng)檢測到設(shè)備存在時賦值的 IIC設(shè)備驅(qū)動 i2c_driver:struct i2c_driverint id;
11、160; /驅(qū)動標(biāo)識IDunsigned int class; /驅(qū)動的類型int (*attach_adapter)(struct i2c_adapter *);
12、160; /當(dāng)檢測到適配器時調(diào)用的函數(shù) int (*detach_adapter)(struct i2c_adapter*); /卸載適配器時調(diào)用的函數(shù)int (*detach_client)(struct i2c_client *) _deprecated;
13、160; /卸載設(shè)備時調(diào)用的函數(shù) /以下是一種新類型驅(qū)動需要的函數(shù),這些函數(shù)支持IIC設(shè)備動態(tài)插入和拔出。如果不想支持只實現(xiàn)上面3個。要不實現(xiàn)上面3個。要么實現(xiàn)下面5個。不能同時定義 int (*probe)(struct i2c_client *,const struct i2c_device_id *);&
14、#160; /新類型設(shè)備探測函數(shù) int (*remove)(struct i2c_client *); /新類型設(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è)備完成特殊的功能。類似ioctl()函數(shù) struct devcie_driver driver; &
18、#160; /設(shè)備驅(qū)動結(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 *); /自動探測設(shè)備的回調(diào)函數(shù) const struct i
20、2c_client_address_data *address_data; /設(shè)備所在的地址范圍 struct list_head clients;
21、0; /指向驅(qū)動支持的設(shè)備;結(jié)構(gòu)體i2c_driver和i2c_client的關(guān)系較為簡單,其中i2c_driver表示一個IIC設(shè)備驅(qū)動,i2c_client表示一個IIC設(shè)備。關(guān)系如下圖:IIC總線適配器就是一個IIC總線控制器,在物理上連接若干個IIC設(shè)備。IIC總線適配器本質(zhì)上是一個物理設(shè)備,其主要功能是完成IIC總線控制器相關(guān)的數(shù)據(jù)通信:struct i2c_adapte
22、r struct module *owner; /模塊計數(shù) unsigned int id;
23、160; /alogorithm的類型,定義于i2c_id.h中 unsigned int class;
24、160; /允許探測的驅(qū)動類型 const struct i2c_algorithm *algo; /指向適配器的驅(qū)動程序
25、; void *algo_data; /指向適配器的私有數(shù)據(jù),根據(jù)不同的情況使用方法不同
26、0; int (*client_register)(struct i2c_client *); /設(shè)備client注冊時調(diào)用 int (*client_unregister(struct i2c_client *); /設(shè)備client注銷時調(diào)用
27、60; u8 level;
28、; struct mutex bus_lock;
29、 /對總線進(jìn)行操作時,將獲得總線鎖 struct mutex clist_lock ; /鏈表操作的互斥鎖 &
30、#160; int timeout;
31、 /超時int retries;
32、160; /重試次數(shù) struct device dev; &
33、#160; /指向 適配器的設(shè)備結(jié)構(gòu)體 int nr ;
34、160; struct list_head clients;
35、 /連接總線上的設(shè)備的鏈表 char name48;
36、0; /適配器名稱 struct completion dev_released; &
37、#160; /用于同步的完成量;每一個適配器對應(yīng)一個驅(qū)動程序,該驅(qū)動程序描述了適配器與設(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é)議的函數(shù),用來確定適配器支持那些傳輸類型 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é)議的函數(shù)。SMBus和IIC之間可以通過軟件方式兼容,所以這里提供了一個函數(shù),但是一般都賦值為NULL u32 (*functionality)(struct i2c_adapter *);
40、60; /返回適配器支持的功能; IIC設(shè)備驅(qū)動程序大致可以分為設(shè)備層和總線層。設(shè)備層包括一個重要的數(shù)據(jù)結(jié)構(gòu),i2c_client??偩€層包括兩個重要的數(shù)據(jù)結(jié)構(gòu),分別是i2c_adapter和i2c_algorithm。一個i2c_algorithm結(jié)構(gòu)表示適配器對應(yīng)的傳輸數(shù)據(jù)方法。3個數(shù)據(jù)結(jié)構(gòu)關(guān)系: IIC設(shè)備層次結(jié)構(gòu)較為簡單,但是寫IIC設(shè)備驅(qū)動程序卻相當(dāng)復(fù)雜。IIC設(shè)備驅(qū)動程序的步驟:IIC子系統(tǒng):IIC子系統(tǒng)是作為模塊加載到系統(tǒng)中的。初始化函數(shù):static int _i
41、nit i2c_init(void) int retval; /返回值,成功0,錯誤返回負(fù)值 retval = bus_register(&i2c_bus_type); /注冊一條IIC的BUS總線 if (retval)
42、0; return retval; retval = class_register(&i2c_adapter_class); /注冊適配器類,用于實現(xiàn)sys文件系統(tǒng)的部分功能 if (retval) goto bus_err; retval = i2c_add_driver(&dummy_driver);
43、 /將一個空驅(qū)動程序注冊到IIC總線中 if (retval) goto class_err; return 0;class_err: class_unregister(&i2c_adapter_class);
44、0; /類注銷bus_err: bus_unregister(&i2c_bus_type);
45、0; /總線注銷 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); /注銷IIC設(shè)備驅(qū)動程序,主要功能是去掉總線中的該設(shè)備驅(qū)動程序
51、class_unregister(&i2c_adapter_class); /注銷適配器類 bus_unregister(&i2c_bus_type);
52、 /注銷I2C總線 適配器驅(qū)動程序是IIC設(shè)備驅(qū)動程序需要實現(xiàn)的主要驅(qū)動程序,這個驅(qū)動程序需要根據(jù)具體的適配器硬件來編寫。I2c_adapter結(jié)構(gòu)體為描述各種IIC適配器提供了“模板",它定義了注冊總線上所有設(shè)備的clients鏈表、指向具體IIC適配器的總線通信方法I2c_algorithm的algo指針、實現(xiàn)i2c總線的操作原子性的lock信號量。但i2c_adapter結(jié)構(gòu)體只是所有適配器的共有屬性,并不能代表所有類型的適配器 s3c2440對應(yīng)的適配器為:struct s3c24xx_i2c
53、spinlock_t lock; /lock自旋鎖 wait_queue_head_t wait; /等待隊列頭。由于IIC設(shè)備是低速設(shè)備,所以可以采取“阻塞-中斷”的驅(qū)動模型,即讀寫i2c設(shè)備的用戶程序在IIC設(shè)備操作期間進(jìn)入阻塞狀態(tài),待IIC操作完成后,總線
54、適配器將引發(fā)中斷,再將相應(yīng)的中斷處理函數(shù)中喚醒受阻的用戶進(jìn)程。該隊列用來放阻塞的進(jìn)程 unsigned int suspended:1; /設(shè)備是否掛起 struct i2c_msg *msg; /從適配器到設(shè)備
55、一次傳輸?shù)膯挝唬眠@個結(jié)構(gòu)體將數(shù)據(jù)包裝起來便于操作 , unsigned int msg_num; /表示消息的個數(shù) unsigned int msg_idx; /表示第幾個消
56、息。當(dāng)完成一個消息后,該值增加 unsigned int msg_ptr; /總是指向當(dāng)前交互中要傳送、接受的下一個字節(jié),在i2c_msg.buf中的偏移量位置 unsigned int tx_setup;
57、60; /表示寫IIC設(shè)備寄存器的一個時間,這里被設(shè)置為50ms unsigned int irq; /適配器申請的中斷號
58、0; enum s3c24xx_i2c_state state; /表示IIC設(shè)備目前的狀態(tài) unsigned long clkrate; /時鐘速率 void _iomem
59、160; *regs; /IIC設(shè)備寄存器地址 struct clk *clk;
60、 /對應(yīng)的時鐘 struct device *dev; /適配器對應(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è)備地址。 這個字段說明一個適配器在獲得總線控制權(quán)后,可以與多個IIC設(shè)備進(jìn)行交互。 _u16
64、160; flags; /消息類型標(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é)長度 _u16 len;
69、160; /消息字節(jié)長度 _u8
70、160; * buf; &
71、#160; /指向消息數(shù)據(jù)的緩沖區(qū); 當(dāng)拿到一塊新的電路板,并研究了響應(yīng)的IIC適配器之后,就應(yīng)該使用內(nèi)核提供的框架函數(shù)向IIC子系統(tǒng)添加一個新的適配器過程:1,分配一個IIC適配器,并初始化相應(yīng)的變量2,使用i2c_add_adapter()函數(shù)向IIC子系統(tǒng)添加適配器結(jié)構(gòu)體i2c_adapter。這個結(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號的內(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號,并將ID號和指針關(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、/ 注冊適配器設(shè)備 關(guān)于IDR機(jī)制,請參考:ack/archive/2012/09/15/2686557.htmlstatic DEFINE_IDR(i2c_adapter_idr);通過ID號獲得適配器指針: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); /通過ID號,查詢適配器指針 if (
80、adapter && !try_module_get(adapter->owner) /適配器引用計數(shù)+1 adapter = NULL; mutex_unlock(&core_lock);
81、60; /釋放內(nèi)核鎖 return adapter;適配器卸載函數(shù):主要任務(wù):注銷適配器的數(shù)據(jù)結(jié)構(gòu),刪除總線上的所有設(shè)備的I2c_client數(shù)據(jù)結(jié)構(gòu)和對應(yīng)的i2c_driver驅(qū)動程序,并減少其代表總線上所有設(shè)備的相應(yīng)驅(qū)動程序數(shù)據(jù)結(jié)構(gòu)的引用計數(shù)(如果到達(dá)0,則卸載設(shè)備驅(qū)動程序):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è)備注銷 /* 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號 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總線通信方法s3c24xx_i2c_algorithm結(jié)構(gòu)體:static const struct i2c_algorithm s3c24xx_i2c_algorithm = .master_xfer = s3c24xx_i2c_xfer, .functionality = s3c24xx_i2c_func,;這里只實現(xiàn)了IIC總線通信協(xié)議通信方法因不同的適配器有所不同,
95、要跟據(jù)具體的硬件來實現(xiàn)協(xié)議支持函數(shù)s3c24xx_i2c_func()該函數(shù)返回總線支持的協(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; /傳輸錯誤重發(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; /延時100us return -EREMOTEIO;
106、0; / I/O錯誤真正的傳輸函數(shù):static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
107、; struct i2c_msg *msgs, int num) unsigned long timeout;
108、60;
109、60; /定義一個傳輸超時時間 int ret;
110、
111、 /返回值,傳輸消息的個數(shù) if (i2c->suspended)
112、
113、 /如果適配器處于掛起省電狀態(tài),則返回 return -EIO; ret = s3c24xx_i2c_set_master(i2c);
114、0; /將適配器設(shè)為主機(jī)發(fā)送狀態(tài),判斷總線忙閑狀態(tài) if (ret != 0)
115、160;
116、160; /如果總線繁忙,則傳輸失敗
117、; dev_err(i2c->dev, "cannot get bus (error %d)n", ret); ret = -EAGAIN; goto out; spin_lock_irq(&i2c->lock);
118、160; /操作適配器的自旋鎖鎖定,每次只允許一個進(jìn)程傳輸數(shù)據(jù),其他進(jìn)程無法獲得總線 i2c->msg
119、 = msgs;
120、0; /傳輸?shù)南⒅羔?#160; i2c->msg_num = num;
121、160; /傳輸?shù)南€數(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); /啟動適配器中斷信號,允許適配器發(fā)出中斷
125、160; s3c24xx_i2c_message_start(i2c, msgs); /當(dāng)調(diào)用該函數(shù)啟動 數(shù)據(jù)發(fā)送后,當(dāng)前進(jìn)程進(jìn)入睡眠狀態(tài),等待中斷到來,所以通過wait_event_timeout()函數(shù)將自己掛起到s3c24xx_i2c.wait等待隊列上,直到等待的條件"i2c->msg_num = 0"
126、;為真,或者5s超時后才能喚醒。注意一次i2c操作可能要涉及多個字節(jié),只有第一個字節(jié)發(fā)送是在當(dāng)前進(jìn)程的文件系統(tǒng)操作執(zhí)行流中進(jìn)行的,該字節(jié)操作的完成及后繼字節(jié)的寫入都由中斷處理程序來完成。在此期間當(dāng)前進(jìn)程掛起在s3c24xx_i2c.wait等待隊列上 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ī)定的時間內(nèi),沒有成功的寫入數(shù)據(jù) dev_dbg(i2c->dev, "timeoutn"); else if (ret != num)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- NB/T 11539-2024礦用物位傳感器通用技術(shù)要求
- 中醫(yī)醫(yī)學(xué)經(jīng)絡(luò)腧穴學(xué)課件-奇穴
- 《學(xué)前社會教育》課件
- 2025屆海南省部分學(xué)校高三上學(xué)期全真模擬(二)歷史試卷(解析版)
- 2024-2025學(xué)年浙江省臺州市十校聯(lián)考高一上學(xué)期期中考試歷史試題(解析版)
- 《物流倉儲管理》課件
- 單位管理制度集合大全員工管理篇
- 《物流管理運輸管理》課件
- 單位管理制度匯編大全員工管理
- 單位管理制度合并匯編【職工管理】
- 2025年濟(jì)南鐵路局招聘筆試參考題庫含答案解析
- 兒童涂色畫空白填色圖(100張文本打印版)
- 2024版合同及信息管理方案
- 壓縮空氣(教學(xué)設(shè)計)-2024-2025學(xué)年三年級上冊科學(xué)教科版
- JGT266-2011 泡沫混凝土標(biāo)準(zhǔn)規(guī)范
- 健康證體檢表
- 大氣課程設(shè)計---袋式除塵器
- 市政橋梁工程施工
- 長線法節(jié)段梁預(yù)制施工方案wgm
- ProE5.0全套教程(完整版)
- 鋼筋混凝土框架結(jié)構(gòu)施工工藝(附施工圖)
評論
0/150
提交評論