吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于Linux驅動開發的IIC設備驅動的投機取巧

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

前言

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

投機取巧的I2C驅動

I2C設備驅動說明

  • 投機取巧的I2C驅動是參考I2C總線驅動代碼實現的。
  • 投機取巧的I2C驅動不需要設備樹,這也讓一些不熟悉設備樹的小伙伴能編寫一個設備驅動。
  • 投機取巧的I2C驅動精簡,方便理解。

分析I2C總線驅動說明

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

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

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

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

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接口(只提取有用信息): 獲取從設備對象句柄,然后將用戶態傳輸的內容傳輸到i2cdev_ioctl_rdwr()接口。i2cdev_ioctl_rdwr()接口是i2c總線驅動對從設備操作的進一步封裝,我們進一步看一下這個函數。
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接口:通過接口可以看出,從用戶態拷貝數據,然后通過i2c_transfer接口進入從設備數據讀寫,然后判斷標志是否讀操作,如果為讀操作,將i2c_transfer接口接收回來的數據拷貝到用戶態。
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;
}

投機取巧的I2C驅動寫法

  • 通過i2c總線驅動的源碼分析,實際我們的設備驅動可以通過這種模仿這個總線驅動來寫。
  • 代碼模板如下:
#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為設備掛在的i2c總線的子設備號
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");

  • 運行結果
Registesuccess,majornumberis240
i2creaddata:0x67!!
ricei2ckoinit!!

總結

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

審核編輯 黃昊宇


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 驅動
    +關注

    關注

    12

    文章

    1851

    瀏覽量

    85642
  • Linux
    +關注

    關注

    87

    文章

    11345

    瀏覽量

    210399
  • IIC
    IIC
    +關注

    關注

    11

    文章

    302

    瀏覽量

    38504
  • 驅動開發
    +關注

    關注

    0

    文章

    130

    瀏覽量

    12111
收藏 人收藏

    評論

    相關推薦

    Linux驅動開發:字符設備驅動開發理論

    大部分學習者的最終目的就是學習 Linux驅動開發Linux中的外設驅動可以分為:字符設備
    發表于 10-26 09:53 ?1179次閱讀

    怎么投機取巧移植RT-Thread到國產MCU上

    KEIL5,IAR。串口助手使用的是SecureCRT。BSP基礎工程其實移植RT-THREAD到一些比較通用的內核還是比較方便的,因為可以投機取巧。那接下來告訴你怎么投機取巧移植RT-Thread到國產
    發表于 06-09 10:57

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

    KEIL5,IAR。串口助手使用的是SecureCRT。BSP基礎工程其實移植RT-THREAD到一些比較通用的內核還是比較方便的,因為可以投機取巧。那接下來告訴你怎么投機取巧移植RT-Thread到國產
    發表于 09-23 15:51

    嵌入式Linux設備驅動開發

    嵌入式Linux設備驅動開發 Linux 設備驅動
    發表于 09-10 13:10 ?82次下載
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>設備</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>

    ARM-Linux-IIC設備的添加與驅動實現

    本文分析了ARM-LinuxIIC總線及其設備驅動的層次結構,指出了IIC設備添加與
    發表于 06-13 14:37 ?57次下載
    ARM-<b class='flag-5'>Linux-IIC</b><b class='flag-5'>設備</b>的添加與<b class='flag-5'>驅動</b>實現

    Linux設備驅動開發詳解》第23章、Linux設備驅動的移植

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

    Linux設備驅動開發詳解》第17章、Linux音頻設備驅動

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

    Linux設備驅動開發詳解》第16章、Linux網絡設備驅動

    Linux設備驅動開發詳解》第16章、Linux網絡設備
    發表于 10-27 11:17 ?5次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設備</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>詳解》第16章、<b class='flag-5'>Linux</b>網絡<b class='flag-5'>設備</b><b class='flag-5'>驅動</b>

    Linux設備驅動開發詳解》第14章、Linux終端設備驅動

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

    Linux設備驅動開發詳解》第13章、Linux設備驅動

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

    Linux設備驅動開發詳解》第9章、Linux設備驅動中的異步通知與異步IO

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

    Linux設備驅動開發詳解》第8章、Linux設備驅動中的阻塞與非阻塞IO

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

    Linux設備驅動開發詳解》第7章、Linux設備驅動中的并發控制

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

    Linux設備驅動開發詳解

    Linux設備驅動開發詳解
    發表于 10-28 11:03 ?51次下載

    ARM-Linux-IIC設備的添加與驅動實現

    電子發燒友網站提供《ARM-Linux-IIC設備的添加與驅動實現.pdf》資料免費下載
    發表于 10-24 09:55 ?0次下載
    ARM-<b class='flag-5'>Linux-IIC</b><b class='flag-5'>設備</b>的添加與<b class='flag-5'>驅動</b>實現
    乐天堂百家乐娱乐网| 大发888真人关键词| 新濠峰百家乐官网的玩法技巧和规则 | 金沙百家乐官网的玩法技巧和规则 | 大发娱乐城| 百家乐怎样看点| 百家乐三路秘诀| 百家乐官网大小技巧| 大发888娱乐下载网址| 百家乐博彩资讯论坛| 百家乐官网百胜注码法| 视频棋牌游戏| 博盈开户| 百家乐官网庄牌| 太阳城娱乐管理网| 百家乐平台注册送现金| 克拉克百家乐的玩法技巧和规则 | 百家乐方法技巧| 大发888官方6222.co| 百家乐官网电投网站| 百家乐免费下| 威尼斯人娱乐代理注册| 易发百家乐| 百家乐投注双赢技巧| 澳博线上娱乐| 缅甸百家乐官网玩假吗| 百家乐打水论坛| 哈尔滨百家乐官网赌场| 百家乐的桌子| 百家乐官网赌场老千| 百家乐神仙道官网| 博彩百家乐组选六六组| 百家乐官网保单详图| 时时博百家乐的玩法技巧和规则| 百家乐官网21点| 大发888官方网站| 国美百家乐官网的玩法技巧和规则| 属猪的人做生意摆放什么聚财| 太阳城娱乐网sss977| 百家乐群121398015| 博彩网百家乐官网全讯网|