用戶空間訪問I2C設備驅動

2012-01-11 15:33:43
標簽:Linux I2C 字符設備 設備驅動 用戶空間
原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://ticktick.blog.51cto.com/823160/761830

??? 關于Linux下如何編寫芯片的I2C驅動,本系列第一篇文章《手把手教你寫Linux I2C設備驅動》對編寫I2C Client 設備驅動的關鍵代碼給出了初步的講述和示例,第二篇文章《Linux下讀寫芯片的I2C寄存器》對于具體如何在驅動層封裝讀寫芯片I2C寄存器也進行了詳細的描述,這兩篇文章的代碼整合到一起,就構成了I2C設備驅動的主要部分,本文則致力于將該驅動進一步封裝,為用戶空間提供訪問的接口。

??? 如果希望在用戶空間訪問我們寫的I2C設備驅動,最常用的做法就是為該I2C驅動編寫一套字符設備驅動,這樣,用戶空間則可以通過對字符設備驅動的訪問,間接地實現對I2C芯片寄存器的讀寫控制。下面,我們在前兩篇文章的代碼的基礎上,封裝一層字符設備驅動,并給出在用戶空間的使用示例。

1.? 編寫字符設備驅動

??? 關于字符設備驅動的編寫,我依然從實例應用的角度來展開描述,關于原理性的東西,網上有許多文章,可以搜索參考。

??? (1)首先,創建一個包含有cdev對象的結構體及對象,代表著本實例的字符設備對象。

  1. struct?tvp5158_dev{?????? ?
  2. ????struct?cdev?cdev;??
  3. int major;???? ?
  4. ????struct?semaphore?semLock;?????? ? ?
  5. }; ?
  6. //?global?dev?object ?
  7. struct?tvp5158_dev?g_tvp5158_dev;?

??? cdev即字符設備對象,major為分配的字符設備主設備號,semaphore用于互斥,保護i2c讀寫過程。

??? (2)第二步,創建文件操作結構體對象

  1. struct?file_operations?tvp5158_dev_FileOps?=?{ ?
  2. ????????.owner???=?THIS_MODULE, ?
  3. ????????.open????=?tvp5158_devOpen, ?
  4. ????????.release?=?tvp5158_devRelease, ?
  5. ????????.ioctl???=?tvp5158_devIoctl, ?
  6. };?

??? 我們把對I2C寄存器的讀寫操作放到 ioctl 命令中執行,不需要實現 read 和 write 函數,故這里只實現文件的打開、釋放、以及 ioctl 操作。

??? (3) 實現設備打開和關閉函數

  1. static?int?tvp5158_devOpen(struct?inode?*inode,?struct?file?*filp) ?
  2. { ?
  3. printk(KERN_INFO?"I2C:?tvp5158_devOpen,?%4d,?%2d?\n",?major,?minor); ?
  4. ?
  5. ????filp->private_data?=?NULL; ?
  6. ?
  7. ????return?0; ?
  8. } ?
  9. ?
  10. static?int?tvp5158_devRelease(struct?inode?*inode,?struct?file?*filp) ?
  11. { ?
  12. ????printk(KERN_INFO?"I2C:?tvp5158_devRelease"); ?
  13. ?
  14. ????return?0; ?
  15. }?

??? (4)實現 IOCTL 函數

??? 這里的ioctl 函數的實現很關鍵,是驅動層與用戶層交互的核心部分,這里將會定義相關的I2C讀寫命令枚舉,并且調用前面文章中封裝好的I2C讀寫代碼。

  1. #define?I2C_CMD_READ???????(0x01) ?
  2. #define?I2C_CMD_WRITE??????(0x02) ?
  3. ?
  4. struct?I2C_Param{ ?
  5. ????uint8_t?*reg; ?
  6. ????uint8_t?*value; ?
  7. }; ?
  8. ?
  9. static?int?tvp5158_devIoctl(struct?inode?*inode,?struct?file?*filp,?unsigned?int?cmd,?unsigned?long?arg) ?
  10. { ?
  11. uint8_t?reg,data;
  12. ????struct? I2C_Param?param; ?
  13. ???? ?
  14. ????down_interruptible(&g_tvp5158_dev.semLock); ?
  15. ???? ?
  16. ????//?get?i2c?param?from?userspace ?
  17. ????copy_from_user(&param,?(void?*)arg,?sizeof(param)); ?
  18. ???? ?
  19. ????switch(cmd){ ?
  20. ????case?I2C_CMD_WRITE: ?
  21. ????????{ ?
  22. copy_from_user(&reg, param.reg,sizeof(uint8_t));
  23. copy_from_user(&data,param.value,sizeof(uint8_t));
  24. ????????????tvp5158_i2c_write(&g_tvp5158_obj->client,?reg,?data); ?
  25. ????????????break; ?
  26. ????????} ?
  27. ????case?I2C_CMD_READ: ?
  28. ????????{ ?
  29. copy_from_user(&reg, param.reg,sizeof(uint8_t));
  30. ????????????tvp5158_i2c_read(&g_tvp5158_obj->client,?reg,?&data); ?
  31. ????????????copy_to_user(param.value,&data,sizeof(uint8_t)); ?
  32. ????????????break; ?
  33. ????????} ?
  34. ????default: ?
  35. ????????break; ?
  36. ????} ?
  37. ????up(&g_tvp5158_dev.semLock); ?
  38. ???? ?
  39. ????return?0; ?
  40. }?

??? 其中,I2C_Param是與用戶空間交互用的參數結構體,用戶空間必須定義相同的結構體以保證交互的正確性。g_tvp5158_obj 和 tvp5158_i2c_read/write 均為前面文章中定義的變量和函數。

??? (5)在__init 代碼中注冊本字符設備驅動

  1. static?int?__init?tvp5158_i2c_init(void) ?
  2. { ?
  3. ????int?result; ?
  4. ????dev_t?dev?=?0; ?
  5. ????result?=?alloc_chrdev_region(&dev,?0,?1,?“tvp5158_dev”); ?
  6. ????if?(result?<?0)?{ ?
  7. ????????printk(KERN_WARNING?"I2C:?can't?get?device?major?num?\n"); ?
  8. ????????return?result; ?
  9. ????} ?
  10. g_tvp5158_dev.major = MAJOR(dev);???? ?
  11. ?
  12. ????sema_init(&g_tvp5158_dev.semLock,?1); ?
  13. ????cdev_init(&g_tvp5158_dev.cdev,?&tvp5158_dev_FileOps); ?
  14. ???? ?
  15. ????g_tvp5158_dev.cdev.owner?=?THIS_MODULE; ?
  16. ????g_tvp5158_dev.cdev.ops???=?&tvp5158_dev_FileOps; ?
  17. ?
  18. ????cdev_add(&g_tvp5158_dev.cdev,?dev,?1);??? ?
  19. ???? ?
  20. ????return?i2c_add_driver(&tvp5158_i2c_driver);; ?
  21. } ?
?

?? (6)在 __exit 代碼中注銷本字符設備驅動

  1. static?void?__exit?tvp5158_i2c_exit(void) ?
  2. { ?
  3. ????dev_t?devno?=?MKDEV(g_tvp5158_dev.major,?0); ?
  4. ?
  5. ????i2c_del_driver(&tvp5158_i2c_driver); ?
  6. ?
  7. ????cdev_del(&g_tvp5158_dev.cdev); ?
  8. ?
  9. ????unregister_chrdev_region(devno,?1); ?
  10. }?

??????? 注意,本初始化代碼和逆初始化在第一篇文章中已經出現過,這里補充完整了,將字符設備驅動的代碼添加進來了。

2.? 用戶空間的使用方法

??? 首先,編寫Makefile將驅動編譯成模塊,然后在用戶空間對生成的模塊(*.ko)進行加載(insmod),然后再 /dev 目錄下創建設備節點 /dev/tvp5158_dev ,最后,在用戶空間即可編寫測試代碼,打開該設備文件,通過 ioctl 命令進行訪問。

? ? 上面這個過程示例如下:

  1. //?假設生成的模塊.ko名稱為?tvp5158.ko?
  2. 第一步:insmod?tvp5158.ko?
  3. ?
  4. //?假設上面tvp5158_i2c_init函數中?g_tvp5158_dev.major?的值為?74?
  5. 第二步:mknod?/dev/tvp5158_dev?c?74?0?

? ? 下面給出最后在用戶空間的測試代碼示例。

  1. #include?<stdio.h> ?
  2. ?
  3. int?main() ?
  4. { ?
  5. ????int?status; ?
  6. ????struct?I2C_Param?param; ?
  7. ?
  8. unit8_t reg = 0x08;
  9. unit8_t value = 0;
  10. ?
  11. ????int?fd?=?open("/dev/tvp5158_dev",?O_RDWR); ?
  12. ????if(?fd?<?0) ?
  13. ????{ ?
  14. ????????return?-1; ?
  15. ????} ?
  16. ???? ?
  17. ????param.reg????=?&reg; ?
  18. ????param.value? =?&value; ?
  19. ????status?=?ioctl(fd,I2C_CMD_READ,&param); ?
  20. ????if(?status?<?0) ?
  21. ????{ ?
  22. ????????printf("read?fail!\n"); ?
  23. ????????return?-1; ?
  24. ????} ?
  25. ????printf("the?0x80?reg?'s?value?=?%d\n",value); ?
  26. ???? ?
  27. ????close(fd); ?
  28. ???? ?
  29. ????return?0; ?
  30. }?

?3.?? 總結

??? 到此為止,Linux下的I2C設備驅動基本編寫過程已經講述完畢,以后凡是拿到新的芯片,需要在Linux下讀寫I2C寄存器,均可參考本系列的代碼進行編寫。當然,這里只是講述了I2C設備驅動編寫的一些最基本的方法,關于I2C設備驅動的原理部分并沒有涉及,希望自己以后更加深入地了解了Linux設備驅動原理后再進一步闡述。本文希望對初學者有所幫助,文中有什么講述不正確的地方,歡迎留言或者來信lujun.hust@gmail.com交流。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/253588.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/253588.shtml
英文地址,請注明出處:http://en.pswp.cn/news/253588.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

097實戰 關于ETL的幾種運行方式

一&#xff1a;代碼部分 1.新建maven項目 2.添加需要的java代碼   3.書寫mapper類 4.書寫runner類 二&#xff1a;運行方式 1.本地運行 2.集群運行 3.本地提交集群運行 三&#xff1a;本地運行方式 1.解壓hadoop到本地 2.修改配置文件HADOOP_HOME 3.解壓common的壓縮包 4.將壓…

模擬ssh, hashlib模塊, struct模塊, subprocess模塊

一. 模擬ssh # 服務器端 import socket import subprocess # 系統操作server socket.socket()server.bind((127.0.0.1,8008))server.listen(5)while True:print("server is working.....")conn,addr server.accept()# 字節類型while True:# 針對window系統try:…

使用pssh進行并行批量操作

假如同時給上千臺服務器執行一個命令,拷貝一個文件,殺一個進程等,有什么簡化運維管理的工具呢?在小型使用中我都是使用for循 環,數量巨大,一方面不確定操作是否成功,一方面for循環語句性能不好估計且是不是同步并行執行.&#xff0c;這類工具比如 pdsh&#xff0c;mussh&#…

圖像清晰度評價函數

概述 圖像清晰度是用來指導調焦機構找到正焦位置的評價函數。理想的清晰度評價曲線如下圖所示,其中P 是評價函數最大值的位置,其對應正焦位置,P1 和P2 為正焦位置焦前和焦后采集到圖像的清晰度評價結果。 為了指導調焦機構找到正焦位置,清晰度曲線須具有以下特點: 單…

Linux下讀寫芯片的I2C寄存器

Linux下讀寫芯片的I2C寄存器 2012-01-10 11:40:18 標簽&#xff1a;Linux 寄存器 驅動 讀寫 I2C 原創作品&#xff0c;允許轉載&#xff0c;轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://ticktick.blog.51cto.com/823160/76096…

列表和表格---學習筆記02

第7章 列表和表格 7.1 有序列表<ol type"A"><li>這里是第1個li</li><li>這里是第2個li</li><li>這里是第3個li</li></ol> ol屬性&#xff1a;type : 數字(1),大小寫字母(A,a),大小寫羅馬數字(I,i)start: "起始…

(下)挖掘傳統行業日志大數據的無限價值

&#xfffc;8 月 27 日晚上八點&#xff0c;七牛云高級解決方案架構師程雪松在 IT 大咖說進行了題為《挖掘傳統行業日志大數據的無限價值》的直播&#xff0c;對傳統行業運維常見困境和統一日志管理的必要性進行了深入解析&#xff0c;并通過 Pandora 的一些真實用戶案例和大家…

CMOS圖像傳感器 —— ISOCELL

最近,外媒曝光了三星最新的CIS傳感器路線圖,路線圖顯示,三星在2億像素之外已經規劃2025年推出576MP像素的傳感器,也就是5億7千6百萬像素。 若5.76億像素的傳感器推出,意味著手機傳感器可媲美中高端單反水平了。三星沒有提及這個5.76億像素的傳感器是怎樣實現的。因…

LeetCode 153. Find Minimum in Rotated Sorted Array (在旋轉有序數組中找到最小值)

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). Find the minimum element. You may assume no duplicate exists in the array. 題目標簽&#xff1a;Array, Binary Se…

YUV圖像

YUV420P&#xff0c;Y&#xff0c;U&#xff0c;V三個分量都是平面格式&#xff0c;分為 I420 和 YV12 。 I420 格式和 YV12 格式的不同處在U平面和V平面的位置不同。在I420格式中&#xff0c;U平面緊跟在Y平面之后&#xff0c;然后才是V平面&#xff08;即&#xff1a;YUV&…

色調映射(Tone Mapping)

一、概述 雖然HDR 圖像有較大的動態范圍,能更細致地反映真實場景,但他的缺點也很明顯。一是同尺寸的數據比低動態范圍圖像大,需要更大的存儲空間與傳輸帶寬。二是難以輸出,目前大多數顯示器、打印機等圖形輸出設備的動態范圍要比普通的高動態范圍圖像小得多。。因此,色調映…

實用軟件工具

1.突破百度網盤下載速度現在&#xff0c;使用 Aria2下載 Aria2-不限速全平臺下載利器但是百度網盤賬號會被限速 &#xff0c;沖會員解除正常限制網速2.Safari 預覽&#xff0c;將網頁轉化為自定義尺寸 PDF 3.清除Xcode 緩存 刪除模擬器運行緩存&#xff0c;找到Developer->…

[原創]Toolbar setNavigationIcon無效

最近在做一個Toolbar&#xff0c;setNavigationIcon()這個方法一直無效&#xff0c;說什么的都有&#xff0c;什么getSupportActionBar().setNavigationIcon()的&#xff0c;說設置style的&#xff0c;說放到setSupportActionBar()之后的。 其實沒有說全&#xff0c;還應該放到…

YUV格式詳解

分類&#xff1a; H.264 MPEG TV 2008-05-14 09:24 16181人閱讀 評論(21) 收藏 舉報 YUV是指亮度參量和色度參量分開表示的像素格式&#xff0c;而這樣分開的好處就是不但可以避免相互干擾&#xff0c;還可以降低色度的采樣率而不會對圖像質量影響太大。YUV是一個比較籠統地說…

KVM安裝、鏡像創建(一)

環境準備 VMware Workstation Pro啟動虛擬化 查看啟動的系統是否支持vmx或svm grep -E (vmx|svm) /proc/cpuinfo 備注&#xff1a;操作系統centos 7 KVM安裝 1、yum查看kvm安裝包 yum list |grep kvm 2、安裝 yum install -y qemu-kvm qemu-kvm-tools libvirt3、啟動libvirtd s…

Sensor 結構——前照、背照、堆棧

優異的工藝和技術可以使得即便不使用更新結構的CMOS,同樣擁有更好的量子效率、固有熱噪聲、增益、滿阱電荷、寬容度、靈敏度等關鍵型指標。在相同技術和工藝下,底大一級的確壓死人(全畫幅和aps-c)。人類的進步就是在不斷發現問題,解決問題。背照式以及堆棧式CMOS的出現,也…

少犯非智力錯誤

工作節省時間最重要的方法之一就是少犯非智力錯誤。 同事反饋說不能預覽&#xff0c;排查半天找不到問題&#xff0c;最后發現是IP地址配錯了。 現場問題同事搞半天找不出原因&#xff0c;結果一看是網域配錯了。 還有些問題開始排查定位不到原因&#xff0c;回頭看時才發現端口…

搭建分布式hadoop2.x集群

前期準備&#xff1a; 1.我這里用了三臺虛擬機&#xff0c;.默認已經配置好靜態IP和IP域名映射&#xff0c;它們相互之間可以ping通 第一臺&#xff1a;192.168.174.131 hadoopNumber01.medal.com 第二臺&#xff1a;192.168.174.132 hadoopNumber02.meda.com 第三臺…

ortp庫使用入門

原創作品&#xff0c;允許轉載&#xff0c;轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://ticktick.blog.51cto.com/823160/345642 我們知道&#xff0c; RTP&#xff08;Real-timeTransportProtocol&#xff09;是用于Internet上…

可測性設計技術

傳統的設計過程和測試過程是分開的&#xff0c;而且測試往往只在設計階段的后期才被考慮。近年來&#xff0c;測試越來越早地被考慮并出現在設計過程中&#xff0c;被稱為“可測性設計”。可測性設計的主要思路就是在設計之初就考慮關于測試方面的設計&#xff0c;并在設計階段…