www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 嵌入式 > 嵌入式軟件
[導(dǎo)讀]作者:劉洪濤,華清遠(yuǎn)見(jiàn)嵌入式學(xué)院講師。四、在內(nèi)核里寫(xiě)i2c設(shè)備驅(qū)動(dòng)的兩種方式前文介紹了利用/dev/i2c-0在應(yīng)用層完成對(duì)i2c設(shè)備的操作,但很多時(shí)候我們還是習(xí)慣為i2c設(shè)備在內(nèi)

作者:劉洪濤,華清遠(yuǎn)見(jiàn)嵌入式學(xué)院講師。

四、在內(nèi)核里寫(xiě)i2c設(shè)備驅(qū)動(dòng)的兩種方式

前文介紹了利用/dev/i2c-0在應(yīng)用層完成對(duì)i2c設(shè)備的操作,但很多時(shí)候我們還是習(xí)慣為i2c設(shè)備在內(nèi)核層編寫(xiě)驅(qū)動(dòng)程序。目前內(nèi)核支持兩種編寫(xiě)i2c驅(qū)動(dòng)程序的方式。下面分別介紹這兩種方式的實(shí)現(xiàn)。這里分別稱(chēng)這兩種方式為“Adapter方式(LEGACY)”和“Probe方式(new style)”。

(1) Adapter方式(LEGACY)

(下面的實(shí)例代碼是在2.6.27內(nèi)核的pca953x.c基礎(chǔ)上修改的,原始代碼采用的是本文將要討論的第2種方式,即Probe方式)

● 構(gòu)建i2c_driver

static struct i2c_driver pca953x_driver = {

.driver = {

.nAME= "pca953x", //名稱(chēng)

},

.id= ID_PCA9555,//id號(hào)

.attach_adapter= pca953x_attach_adapter, //調(diào)用適配器連接設(shè)備

.detach_client= pca953x_detach_client,//讓設(shè)備脫離適配器

};

● 注冊(cè)i2c_driver

static int __init pca953x_init(void)

{

return i2c_add_driver(&pca953x_driver);

}

module_init(pca953x_init);

● attach_adapter動(dòng)作

執(zhí)行i2c_add_driver(&pca953x_driver)后會(huì),如果內(nèi)核中已經(jīng)注冊(cè)了i2c適配器,則順序調(diào)用這些適配器來(lái)連接我們的i2c設(shè)備。此過(guò)程是通過(guò)調(diào)用i2c_driver中的attach_adapter方法完成的。具體實(shí)現(xiàn)形式如下:

static int pca953x_attach_adapter(struct i2c_adapter *adapter)

{

return i2c_probe(adapter, &addr_data, pca953x_detect);

/*

adapter:適配器

addr_data:地址信息

pca953x_detect:探測(cè)到設(shè)備后調(diào)用的函數(shù)

*/

}

地址信息addr_data是由下面代碼指定的。

/* Addresses to scan */

static unsigned short normal_i2c[] = {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,I2C_CLIENT_END};

I2C_CLIENT_INSMOD;

注意:normal_i2c里的地址必須是你i2c芯片的地址。否則將無(wú)法正確探測(cè)到設(shè)備。而I2C_ CLIENT_INSMOD是一個(gè)宏,它會(huì)利用normal_i2c構(gòu)建addr_data。

● 構(gòu)建i2c_client,并注冊(cè)字符設(shè)備驅(qū)動(dòng)

i2c_probe在探測(cè)到目標(biāo)設(shè)備后,后調(diào)用pca953x_detect,并把當(dāng)時(shí)的探測(cè)地址address作為參數(shù)傳入。

static int pca953x_detect(struct i2c_adapter *adapter, int address, int kind)

{

struct i2c_client *new_client;

struct pca953x_chip *chip; //設(shè)備結(jié)構(gòu)體

int err = 0,result;

dev_t pca953x_dev=MKDEV(pca953x_major,0);//構(gòu)建設(shè)備號(hào),根據(jù)具體情況設(shè)定,這里我只考慮了normal_i2c中只有一個(gè)地址匹配的情況。

if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA| I2C_FUNC_SMBUS_WORD_DATA))//判定適配器能力

goto exit;

if (!(chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL))) {

err = -ENOMEM;

goto exit;

}

/****構(gòu)建i2c-client****/

chip->client=kzalloc(sizeof(struct i2c_client),GFP_KERNEL);

new_client = chip->client;

i2c_set_clientdata(new_client, chip);

new_client->addr = address;

new_client->adapter = adapter;

new_client->driver = &pca953x_driver;

new_client->flags = 0;

strlcpy(new_client->name, "pca953x", I2C_NAME_SIZE);

if ((err = i2c_attach_client(new_client)))//注冊(cè)i2c_client

goto exit_kfree;

if (err)

goto exit_detach;

if(pca953x_major)

{

result=register_chrdev_region(pca953x_dev,1,"pca953x");

}

else{

result=alloc_chrdev_region(&pca953x_dev,0,1,"pca953x");

pca953x_major=MAJOR(pca953x_dev);

}

if (result < 0) {

printk(KERN_NOTICE "Unable to get pca953x region, error %d\n", result);

return result;

}

pca953x_setup_cdev(chip,0); //注冊(cè)字符設(shè)備,此處不詳解

return 0;

exit_detach:

i2c_detach_client(new_client);

exit_kfree:

kfree(chip);

exit:

return err;

}

i2c_check_functionality用來(lái)判定設(shè)配器的能力,這一點(diǎn)非常重要。你也可以直接查看對(duì)應(yīng)設(shè)配器的能力,如

static const struct i2c_algorithm smbus_algorithm = {

.smbus_xfer= i801_access,

.functionality= i801_func,

};

static u32 i801_func(struct i2c_adapter *adapter)

{

return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |

I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |

I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK

| (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);

}

● 字符驅(qū)動(dòng)的具體實(shí)現(xiàn)

struct file_operations pca953x_fops = {

.owner = THIS_MODULE,

.ioctl= pca953x_ioctl,

.open= pca953x_open,

.release =pca953x_release,

};

字符設(shè)備驅(qū)動(dòng)本身沒(méi)有什么好說(shuō)的,這里主要想說(shuō)一下,如何在驅(qū)動(dòng)中調(diào)用i2c設(shè)配器幫我們完成數(shù)據(jù)傳輸。

目前設(shè)配器主要支持兩種傳輸方法:smbus_xfer和master_xfer。一般來(lái)說(shuō),如果設(shè)配器支持了master_xfer那么它也可以模擬支持smbus的傳輸。但如果只實(shí)現(xiàn)smbus_xfer,則不支持一些i2c的傳輸。

int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs,int num);

int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,

unsigned short flags, char read_write,

u8 command, int size, union i2c_smbus_data * data);

master_xfer中的參數(shù)設(shè)置,和前面的用戶(hù)空間編程一致?,F(xiàn)在只是要在驅(qū)動(dòng)中構(gòu)建相關(guān)的參數(shù)然后調(diào)用i2c_transfer來(lái)完成傳輸既可。

int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)

smbus_xfer中的參數(shù)設(shè)置及調(diào)用方法如下:

static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)

{

int ret;

ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);

if (ret < 0) {

dev_err(&chip->client->dev, "failed writing register\n");

return -EIO;

}

return 0;

}

上面函數(shù)完成向芯片的地址為reg的寄存器寫(xiě)一個(gè)16bit的數(shù)據(jù)。i2c_smbus_write_word_data的實(shí)現(xiàn)如下:

s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)

{

union i2c_smbus_data data;

data.word = value;

return i2c_smbus_xfer(client->adapter,client->addr,client->flags,

I2C_SMBUS_WRITE,command,

I2C_SMBUS_WORD_DATA,&data);

}

從中可以看出smbus傳輸一個(gè)16位數(shù)據(jù)的方法。其它操作如:字符寫(xiě)、字符讀、字讀、塊操作等,可以參考內(nèi)核的i2c-core.c中提供的方法。

● 注銷(xiāo)i2c_driver

static void __exit pca953x_exit(void)

{

i2c_del_driver(&pca953x_driver);

}

module_exit(pca953x_exit);

● detach_client動(dòng)作

順序調(diào)用內(nèi)核中注冊(cè)的適配器來(lái)斷開(kāi)我們注冊(cè)過(guò)的i2c設(shè)備。此過(guò)程通過(guò)調(diào)用i2c_driver中的attach_adapter方法完成的。具體實(shí)現(xiàn)形式如下:

static int pca953x_detach_client(struct i2c_client *client)

{

int err;

struct pca953x_chip *data;

if ((err = i2c_detach_client(client)))//斷開(kāi)i2c_client

return err;

data=i2c_get_clientdata(client);

cdev_del(&(data->cdev));

unregister_chrdev_region(MKDEV(pca953x_major, 0), 1);

kfree(data->client);

kfree(data);

return 0;

}

(2) Probe方式(new style)

● 構(gòu)建i2c_driver

和LEGACY方式一樣,也需要構(gòu)建i2c_driver,但是內(nèi)容有所不同。

static struct i2c_driver pca953x_driver = {

.driver = {

.name= "pca953x",

},

.probe= pca953x_probe, //當(dāng)有i2c_client和i2c_driver匹配時(shí)調(diào)用

.remove= pca953x_remove,//注銷(xiāo)時(shí)調(diào)用

.id_table= pca953x_id,//匹配規(guī)則

};

● 注冊(cè)i2c_driver

static int __init pca953x_init(void)

{

return i2c_add_driver(&pca953x_driver);

}

module_init(pca953x_init);

在注冊(cè)i2c_driver的過(guò)程中,是將driver注冊(cè)到了i2c_bus_type的總線上。此總線的匹配規(guī)則是:

static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,

const struct i2c_client *client)

{

while (id->name[0]) {

if (strcmp(client->name, id->name) == 0)

return id;

id++;

}

return NULL;

}

可以看出是利用i2c_client的名稱(chēng)和id_table中的名稱(chēng)做匹配的。本驅(qū)動(dòng)中的id_table為

static const struct i2c_device_id pca953x_id[] = {

{ "pca9534", 8, },

{ "pca9535", 16, },

{ "pca9536", 4, },

{ "pca9537", 4, },

{ "pca9538", 8, },

{ "pca9539", 16, },

{ "pca9554", 8, },

{ "pca9555", 16, },

{ "pca9557", 8, },

{ "max7310", 8, },

{ }

};

看到現(xiàn)在我們應(yīng)該會(huì)有這樣的疑問(wèn),在Adapter模式中,i2c_client是我們自己構(gòu)造出來(lái)的,而現(xiàn)在的i2c_client是從哪來(lái)的呢?看看下面的解釋

● 注冊(cè)i2c_bOArd_info

對(duì)于Probe模式,通常在平臺(tái)代碼中要完成i2c_board_info的注冊(cè)。方法如下:

static struct i2c_board_info __initdata test_i2c_devices[] = {

{

I2C_BOARD_INFO("pca9555", 0x27),//pca9555為芯片名稱(chēng),0x27為芯片地址

.platform_data = &pca9555_data,

}, {

I2C_BOARD_INFO("mt9v022", 0x48),

.platform_data = &iclink[0], /* With extender */

}, {

I2C_BOARD_INFO("mt9m001", 0x5d),

.platform_data = &iclink[0], /* With extender */

},

};

i2c_register_board_info(0, test_i2c_devices,ARRAY_SIZE(test_i2c_devices)); //注冊(cè)

i2c_client就是在注冊(cè)過(guò)程中構(gòu)建的。但有一點(diǎn)需要注意的是i2c_register_board_info并沒(méi)有EXPORT_SYMBOL給模塊使用。

● 字符驅(qū)動(dòng)注冊(cè)

在Probe方式下,添加字符驅(qū)動(dòng)的位置在pca953x_probe中。

static int __devinit pca953x_probe(struct i2c_client *client,const struct i2c_device_id *id)

{

……

/****字符設(shè)備驅(qū)動(dòng)注冊(cè)位置****/

……

return 0;

}

● 注銷(xiāo)i2c_driver

static void __exit pca953x_exit(void)

{

i2c_del_driver(&pca953x_driver);

}

module_exit(pca953x_exit);

● 注銷(xiāo)字符設(shè)備驅(qū)動(dòng)

在Probe方式下,注銷(xiāo)字符驅(qū)動(dòng)的位置在pca953x_remove中。

static int __devinit pca953x_remove (struct i2c_client *client)

{

……

/****字符設(shè)備驅(qū)動(dòng)注銷(xiāo)的位置****/

……

return 0;

}

● I2C設(shè)備的數(shù)據(jù)交互方法(即:調(diào)用適配器操作設(shè)備的方法)和Adapter方式下相同。

“本文由華清遠(yuǎn)見(jiàn)http://www.embedu.org/index.htm提供”



華清遠(yuǎn)見(jiàn)

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶(hù)希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱(chēng),數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱(chēng)"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉