0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

關(guān)于Linux驅(qū)動開發(fā)的IIC設(shè)備驅(qū)動的投機(jī)取巧

Rice嵌入式開發(fā)技術(shù)分享 ? 來源: Rice嵌入式開發(fā)技術(shù)分享 ? 作者: Rice嵌入式開發(fā)技 ? 2022-08-09 11:18 ? 次閱讀

前言

  • Linux的IIC驅(qū)動想必大家都耳熟能詳,網(wǎng)上也有很多相關(guān)的教程。
  • 網(wǎng)上的教程總結(jié),比如:
方法 問題描述
Linux 3.X.X版本之后,設(shè)備樹+驅(qū)動 此方法是比較符合linux驅(qū)動的寫法的。當(dāng)對于不熟悉設(shè)備樹的小伙伴,寫起來比較棘手
使用 i2c-tools,并通過腳本或者應(yīng)用程序編寫設(shè)備驅(qū)動(簡單粗暴) 此方法是將設(shè)備驅(qū)動丟到用戶態(tài)中,對于一些的設(shè)備除了I2C通信還有一些引腳也要控制的,此方法寫起來將非常痛苦
直接操作i2c總線驅(qū)動。(簡單粗暴) 此方法是將設(shè)備驅(qū)動丟到用戶態(tài)中,對于一些的設(shè)備除了I2C通信還有一些引腳也要控制的,此方法寫起來將非常痛苦。他將會操作多個文件
  • 上面的做法都有些困難及弊端存在,經(jīng)過摸索了一遍Linux的I2C驅(qū)動框架,我發(fā)現(xiàn)可以很精簡的寫一個I2C設(shè)備的設(shè)備驅(qū)動。而且是放在內(nèi)核態(tài)中,這樣處理一下GPIO或者中斷什么的都很方便。

投機(jī)取巧的I2C驅(qū)動

I2C設(shè)備驅(qū)動說明

  • 投機(jī)取巧的I2C驅(qū)動是參考I2C總線驅(qū)動代碼實(shí)現(xiàn)的。
  • 投機(jī)取巧的I2C驅(qū)動不需要設(shè)備樹,這也讓一些不熟悉設(shè)備樹的小伙伴能編寫一個設(shè)備驅(qū)動。
  • 投機(jī)取巧的I2C驅(qū)動精簡,方便理解。

分析I2C總線驅(qū)動說明

  • I2C總線驅(qū)動的代碼在linux的源碼中--i2c-dev.c中。

  • 在代碼中可以看到他提供一套文件操作接口,open,read,write,close接口。實(shí)際在上面描述的直接操作i2c總線驅(qū)動的方法,最終就是調(diào)用到這里。

  • 通過整個源碼的分析,我們主要看看open和ioctl接口。其中:

  • open接口,代碼分析:通過inode獲取設(shè)備子設(shè)備號,根據(jù)子設(shè)備號獲取I2C適配器。然后申請一個從設(shè)備對象。并將I2C適配器句柄映射到從設(shè)備對象中。

staticinti2cdev_open(structinode*inode,structfile*file)
{
unsignedintminor=iminor(inode);
structi2c_client*client;
structi2c_adapter*adap;

adap=i2c_get_adapter(minor);
if(!adap)
return-ENODEV;

/*Thiscreatesananonymousi2c_client,whichmaylaterbe
*pointedtosomeaddressusingI2C_SLAVEorI2C_SLAVE_FORCE.
*
*Thisclientis**NEVERREGISTERED**withthedrivermodel
*orI2Ccorecode!!Itjustholdsprivatecopiesofaddressing
*informationandmaybeaPECflag.
*/
client=kzalloc(sizeof(*client),GFP_KERNEL);
if(!client){
i2c_put_adapter(adap);
return-ENOMEM;
}
snprintf(client->name,I2C_NAME_SIZE,"i2c-dev%d",adap->nr);

client->adapter=adap;
file->private_data=client;

return0;
}

  • ioctl接口(只提取有用信息): 獲取從設(shè)備對象句柄,然后將用戶態(tài)傳輸?shù)膬?nèi)容傳輸?shù)絠2cdev_ioctl_rdwr()接口。i2cdev_ioctl_rdwr()接口是i2c總線驅(qū)動對從設(shè)備操作的進(jìn)一步封裝,我們進(jìn)一步看一下這個函數(shù)。
staticlongi2cdev_ioctl(structfile*file,unsignedintcmd,unsignedlongarg)
{
structi2c_client*client=file->private_data;
unsignedlongfuncs;

......

switch(cmd){
.....

caseI2C_RDWR:
returni2cdev_ioctl_rdwr(client,arg);

......
}
return0;
}
  • i2cdev_ioctl_rdwr接口:通過接口可以看出,從用戶態(tài)拷貝數(shù)據(jù),然后通過i2c_transfer接口進(jìn)入從設(shè)備數(shù)據(jù)讀寫,然后判斷標(biāo)志是否讀操作,如果為讀操作,將i2c_transfer接口接收回來的數(shù)據(jù)拷貝到用戶態(tài)。
staticnoinlineinti2cdev_ioctl_rdwr(structi2c_client*client,
unsignedlongarg)
{
structi2c_rdwr_ioctl_datardwr_arg;
structi2c_msg*rdwr_pa;
u8__user**data_ptrs;
inti,res;

if(copy_from_user(&rdwr_arg,
(structi2c_rdwr_ioctl_data__user*)arg,
sizeof(rdwr_arg)))
return-EFAULT;

......

res=i2c_transfer(client->adapter,rdwr_pa,rdwr_arg.nmsgs);
while(i-->0){
if(res>=0&&(rdwr_pa[i].flags&I2C_M_RD)){
if(copy_to_user(data_ptrs[i],rdwr_pa[i].buf,
rdwr_pa[i].len))
res=-EFAULT;
}
kfree(rdwr_pa[i].buf);
}
......

returnres;
}

投機(jī)取巧的I2C驅(qū)動寫法

  • 通過i2c總線驅(qū)動的源碼分析,實(shí)際我們的設(shè)備驅(qū)動可以通過這種模仿這個總線驅(qū)動來寫。
  • 代碼模板如下:
#include"rice_i2c.h"

#defineCLASS_NAME"rice_i2c"
#defineDEVICE_NAME"rice_i2c"

typedefstruct{
intmajor_number;
structdevice*device;
structclass*class;
structi2c_client*client;
}Rice_Driver;

Rice_Driverrice_drv;

staticinti2c_test(void)
{
structi2c_msgi2c_msg[2]={0};
uint8_treg_addr=0x75;
uint8_tbuff[2]={0};

i2c_msg[0].addr=0x69;
i2c_msg[0].flags=0;
i2c_msg[0].len=1;
i2c_msg[0].buf=(uint8_t*)?_addr;
i2c_msg[1].addr=0x69;
i2c_msg[1].flags=I2C_M_RD;
i2c_msg[1].len=1;
i2c_msg[1].buf=buff;

i2c_transfer(rice_drv.client->adapter,i2c_msg,2);

printk(KERN_ALERT"i2creaddata:0x%02x!!\n",buff[0]);
}

staticint__initrice_i2c_init(void){
structi2c_client*client;
structi2c_adapter*adap;

rice_drv.major_number=register_chrdev(0,DEVICE_NAME,NULL);

if(rice_drv.major_number0){
printk(KERN_ALERT"Registerfail!!\n");
returnrice_drv.major_number;
}

printk(KERN_ALERT"Registesuccess,majornumberis%d\n",rice_drv.major_number);

rice_drv.class=class_create(THIS_MODULE,CLASS_NAME);

if(IS_ERR(rice_drv.class)){
unregister_chrdev(rice_drv.major_number,DEVICE_NAME);
returnPTR_ERR(rice_drv.class);
}

rice_drv.device=device_create(rice_drv.class,NULL,MKDEV(rice_drv.major_number,0),NULL,DEVICE_NAME);

if(IS_ERR(rice_drv.device)){
class_destroy(rice_drv.class);
unregister_chrdev(rice_drv.major_number,DEVICE_NAME);
returnPTR_ERR(rice_drv.device);
}

//1為設(shè)備掛在的i2c總線的子設(shè)備號
adap=i2c_get_adapter(1);
if(!adap)
return-ENODEV;

rice_drv.client=kzalloc(sizeof(*rice_drv.client),GFP_KERNEL);
if(!rice_drv.client){
i2c_put_adapter(adap);
return-ENOMEM;
}
snprintf(rice_drv.client->name,I2C_NAME_SIZE,"i2c-dev%d",adap->nr);

rice_drv.client->adapter=adap;

i2c_test();

printk(KERN_ALERT"ricei2ckoinit!!\n");

return0;
}

staticvoid__exitrice_i2c_exit(void){
device_destroy(rice_drv.class,MKDEV(rice_drv.major_number,0));
class_unregister(rice_drv.class);
class_destroy(rice_drv.class);
unregister_chrdev(rice_drv.major_number,DEVICE_NAME);
i2c_put_adapter(rice_drv.client->adap);

printk(KERN_ALERT"ricei2ckoexit!!\n");
}

module_init(rice_i2c_init);
module_exit(rice_i2c_exit);
MODULE_AUTHOR("RieChen");
MODULE_LICENSE("GPL");

  • 運(yùn)行結(jié)果
Registesuccess,majornumberis240
i2creaddata:0x67!!
ricei2ckoinit!!

總結(jié)

  • 通過投機(jī)取巧的方法,不需要設(shè)備樹的存在,就可以在內(nèi)核態(tài)中編寫設(shè)備驅(qū)動,而且很靈活。
  • 雖然這是一種可以讓我們快速開發(fā)驅(qū)動的方法,但是還是建議大家要去了解框架的邏輯。這樣不僅對自己的編碼能力,以及開發(fā)很有幫助。
  • 希望本篇文章能夠幫助到大家。

審核編輯 黃昊宇


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 驅(qū)動
    +關(guān)注

    關(guān)注

    12

    文章

    1820

    瀏覽量

    85110
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11210

    瀏覽量

    208721
  • IIC
    IIC
    +關(guān)注

    關(guān)注

    11

    文章

    298

    瀏覽量

    38241
  • 驅(qū)動開發(fā)
    +關(guān)注

    關(guān)注

    0

    文章

    130

    瀏覽量

    12059
收藏 人收藏

    評論

    相關(guān)推薦

    Linux驅(qū)動開發(fā):字符設(shè)備驅(qū)動開發(fā)理論

    大部分學(xué)習(xí)者的最終目的就是學(xué)習(xí) Linux驅(qū)動開發(fā),Linux中的外設(shè)驅(qū)動可以分為:字符設(shè)備
    發(fā)表于 10-26 09:53 ?1064次閱讀

    怎么投機(jī)取巧移植RT-Thread到國產(chǎn)MCU上

    KEIL5,IAR。串口助手使用的是SecureCRT。BSP基礎(chǔ)工程其實(shí)移植RT-THREAD到一些比較通用的內(nèi)核還是比較方便的,因?yàn)榭梢?b class='flag-5'>投機(jī)取巧。那接下來告訴你怎么投機(jī)取巧移植RT-Thread到國產(chǎn)
    發(fā)表于 06-09 10:57

    告訴你怎么投機(jī)取巧移植RT-Thread到HC32L136芯片上

    KEIL5,IAR。串口助手使用的是SecureCRT。BSP基礎(chǔ)工程其實(shí)移植RT-THREAD到一些比較通用的內(nèi)核還是比較方便的,因?yàn)榭梢?b class='flag-5'>投機(jī)取巧。那接下來告訴你怎么投機(jī)取巧移植RT-Thread到國產(chǎn)
    發(fā)表于 09-23 15:51

    嵌入式Linux設(shè)備驅(qū)動開發(fā)

    嵌入式Linux設(shè)備驅(qū)動開發(fā) Linux 設(shè)備驅(qū)動
    發(fā)表于 09-10 13:10 ?82次下載
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>

    ARM-Linux-IIC設(shè)備的添加與驅(qū)動實(shí)現(xiàn)

    本文分析了ARM-LinuxIIC總線及其設(shè)備驅(qū)動的層次結(jié)構(gòu),指出了IIC設(shè)備添加與
    發(fā)表于 06-13 14:37 ?57次下載
    ARM-<b class='flag-5'>Linux-IIC</b><b class='flag-5'>設(shè)備</b>的添加與<b class='flag-5'>驅(qū)動</b>實(shí)現(xiàn)

    Linux設(shè)備驅(qū)動開發(fā)詳解》第23章、Linux設(shè)備驅(qū)動的移植

    Linux設(shè)備驅(qū)動開發(fā)詳解》第23章、Linux設(shè)備驅(qū)動
    發(fā)表于 10-27 10:58 ?9次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>詳解》第23章、<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b>的移植

    Linux設(shè)備驅(qū)動開發(fā)詳解》第17章、Linux音頻設(shè)備驅(qū)動

    Linux設(shè)備驅(qū)動開發(fā)詳解》第17章、Linux音頻設(shè)備驅(qū)
    發(fā)表于 10-27 11:14 ?17次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>詳解》第17章、<b class='flag-5'>Linux</b>音頻<b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b>

    Linux設(shè)備驅(qū)動開發(fā)詳解》第16章、Linux網(wǎng)絡(luò)設(shè)備驅(qū)動

    Linux設(shè)備驅(qū)動開發(fā)詳解》第16章、Linux網(wǎng)絡(luò)設(shè)備驅(qū)
    發(fā)表于 10-27 11:17 ?5次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>詳解》第16章、<b class='flag-5'>Linux</b>網(wǎng)絡(luò)<b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b>

    Linux設(shè)備驅(qū)動開發(fā)詳解》第14章、Linux終端設(shè)備驅(qū)動

    Linux設(shè)備驅(qū)動開發(fā)詳解》第14章、Linux終端設(shè)備驅(qū)
    發(fā)表于 10-27 11:22 ?8次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>詳解》第14章、<b class='flag-5'>Linux</b>終端<b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b>

    Linux設(shè)備驅(qū)動開發(fā)詳解》第13章、Linux設(shè)備驅(qū)動

    Linux設(shè)備驅(qū)動開發(fā)詳解》第13章、Linux設(shè)備驅(qū)動
    發(fā)表于 10-27 11:24 ?18次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>詳解》第13章、<b class='flag-5'>Linux</b>塊<b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b>

    Linux設(shè)備驅(qū)動開發(fā)詳解》第9章、Linux設(shè)備驅(qū)動中的異步通知與異步IO

    Linux設(shè)備驅(qū)動開發(fā)詳解》第9章、Linux設(shè)備驅(qū)動
    發(fā)表于 10-27 11:33 ?0次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>詳解》第9章、<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b>中的異步通知與異步IO

    Linux設(shè)備驅(qū)動開發(fā)詳解》第8章、Linux設(shè)備驅(qū)動中的阻塞與非阻塞IO

    Linux設(shè)備驅(qū)動開發(fā)詳解》第8章、Linux設(shè)備驅(qū)動
    發(fā)表于 10-27 11:35 ?9次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>詳解》第8章、<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b>中的阻塞與非阻塞IO

    Linux設(shè)備驅(qū)動開發(fā)詳解》第7章、Linux設(shè)備驅(qū)動中的并發(fā)控制

    Linux設(shè)備驅(qū)動開發(fā)詳解》第7章、Linux設(shè)備驅(qū)動
    發(fā)表于 10-27 11:37 ?10次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>詳解》第7章、<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動</b>中的并發(fā)控制

    Linux設(shè)備驅(qū)動開發(fā)詳解

    Linux設(shè)備驅(qū)動開發(fā)詳解
    發(fā)表于 10-28 11:03 ?50次下載

    ARM-Linux-IIC設(shè)備的添加與驅(qū)動實(shí)現(xiàn)

    電子發(fā)燒友網(wǎng)站提供《ARM-Linux-IIC設(shè)備的添加與驅(qū)動實(shí)現(xiàn).pdf》資料免費(fèi)下載
    發(fā)表于 10-24 09:55 ?0次下載
    ARM-<b class='flag-5'>Linux-IIC</b><b class='flag-5'>設(shè)備</b>的添加與<b class='flag-5'>驅(qū)動</b>實(shí)現(xiàn)