1. 程式人生 > >Linux I2C驅動分析與實現--例子

Linux I2C驅動分析與實現--例子

通過上篇《Linux I2C驅動分析與實現(二)》,我們對Linux子系統已經不陌生,那麼如何實現I2C驅動呢?

編寫客戶驅動的方法

在核心中有兩種方式的i2c客戶驅動的編寫方法,一種叫legacy傳統方式,另一種是newstyle方式. 前

一種legacy是一種舊式的方法,在2.6核心以後的標準驅動模型編寫中逐漸被newstyle方式取代。本文程式設計例項是基於newstyle方式的來實現at24c02的驅

動。

客戶驅動程式開發的一般步驟

(1)註冊板載i2c裝置資訊

(2)定義i2c驅動裝置id

(3)定義i2c_driver結構並完成其相應函式

(4)模組初始化時新增/撤銷時刪除i2c_driver

(5)/dev  entry 訪問方法 /sysfs訪問方法

客戶裝置驅動開發例項

核心為linux-2.6.30.4

基於arm9 S3c2440平臺

開發一個at24c02 eeprom的客戶驅動

開發一個應用程式訪問I2C裝置

-----------------------------------------------------------------

根據開發客戶驅動程式步驟實現對i2c裝置at24c02的讀寫操作。

(分析at24c02 datasheet)

(1)

註冊板載資訊

mach-smdk2440.c檔案中靜態宣告一個I2C裝置

  1. staticstruct i2c_board_info i2c_devices[] __initdata = {  
  2.     {I2C_BOARD_INFO("24c02", 0x50), },  
  3.      {}  
  4. };  

smdk2440_machine_init()函式中,向匯流排註冊I2C裝置資訊:

  1. i2c_register_board_info(0,i2c_devices,ARRAY_SIZE(i2c_devices));  

(2)定義i2c驅動裝置id:

  1. staticstruct i2c_device_id foo_idtable[] = {  
  2.     { “24c01", 0x51 },  
  3.     {“20402”,0x50 },  
  4.     {}  
  5. };  

(3)定義i2c_driver結構並完成其相應函式:

  1. staticstruct i2c_driver my_i2c_driver = {  
  2.     .driver = {  
  3.       .name = "i2c_demo",  
  4.       .owner = THIS_MODULE,  
  5.     },  
  6.     .probe = my_i2c_probe,  
  7.     .remove = my_i2c_remove,  
  8.     .id_table = my_ids,  
  9. };  

(4)模組初始化時新增/撤銷時刪除i2c_driver

  1. staticint __init  my_i2c_client(void)  
  2. {  
  3.    return i2c_add_driver(&my_i2c_driver);  
  4. }  
  5. staticvoid __exit my_i2c_exit(void)  
  6. {  
  7.    i2c_del_driver(&my_i2c_driver);  
  8. }  

(5)使用/dev entry 訪問方法

註冊字元裝置

  1. register_chrdev(I2C_MAJOR,DEVICE_NAME,&i2c_fops);  
  2. 建立類class_create(THIS_MODULE, DEVICE_NAME);  
  3. 在/dev下建立裝置節點  
  4. device_create(my_dev_class, &client->dev,MKDEV(I2C_MAJOR, 0), NULL, DEVICE_NAME);  

"實現程式碼附件下載",有需要請留言,郵件發~

誰能告訴我csdn為什麼不可以上傳附件?

程式碼測試結果:

  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <linux/slab.h>
  5. #include <linux/init.h>
  6. #include <linux/list.h>
  7. #include <linux/i2c.h>
  8. #include <linux/i2c-dev.h>
  9. #include <linux/smp_lock.h>
  10. #include <linux/jiffies.h>
  11. #include <asm/uaccess.h>
  12. #include <linux/delay.h>
  13. #define DEBUG 1
  14. #ifdef DEBUG
  15. #define dbg(x...) printk(x)
  16. #else 
  17. #define dbg(x...) (void)(0)
  18. #endif
  19. #define I2C_MAJOR 89
  20. #define DEVICE_NAME "at24c02"
  21. staticstructclass *my_dev_class;  
  22. staticstruct i2c_client *my_client;  
  23. staticstruct i2c_driver my_i2c_driver;  
  24. staticstruct i2c_device_id my_ids[] = {  
  25.     {"24c01",0x50},  
  26.     {"24c02",0x50},  
  27.     {"24c08",0x50},  
  28.     {}  
  29. };  
  30. MODULE_DEVICE_TABLE(i2c,my_ids);  
  31. staticint my_i2c_probe(struct i2c_client *client, conststruct i2c_device_id *id)  
  32. {  
  33.     int res;  
  34.     struct device *dev;  
  35.     dbg("probe:name = %s,flag =%d,addr = %d,adapter = %d,driver = %s\n",client->name,  
  36.          client->flags,client->addr,client->adapter->nr,client->driver->driver.name );  
  37.     dev = device_create(my_dev_class, &client->dev,  
  38.                      MKDEV(I2C_MAJOR, 0), NULL,  
  39.                      DEVICE_NAME);  
  40.     if (IS_ERR(dev))  
  41.     {  
  42.         dbg("device create error\n");  
  43.         goto out;  
  44.     }  
  45.     my_client = client;  
  46.     return 0;  
  47. out:  
  48.     return -1;  
  49. }  
  50. staticint  my_i2c_remove(struct i2c_client *client)  
  51. {  
  52.     dbg("remove\n");  
  53.     return 0;  
  54. }  
  55. static ssize_t at24c02_read(struct file *fd, char *buf, ssize_t count, loff_t *offset)  
  56. {  
  57.     char *tmp;  
  58.     int ret;  
  59.     char data_byte;  
  60.     char reg_addr = 0,i;  
  61.     struct i2c_client *client = (struct i2c_client*) fd->private_data;  
  62.     struct i2c_msg msgs[2];  
  63.     dbg("read:count = %d,offset = %ld\n",count,*offset);  
  64.     tmp = kmalloc(count,GFP_KERNEL);  
  65.     if (!tmp)  
  66.     {  
  67.         dbg("malloc error in read function\n");  
  68.         goto out;  
  69.     }  
  70.     reg_addr = *offset;  
  71.     msgs[0].addr = client->addr;  
  72.     msgs[0].flags = client->flags & (I2C_M_TEN|I2C_CLIENT_PEC) ;  
  73.     msgs[0].len = 1;  
  74.     msgs[0].buf = (char *)®_addr;  
  75.     msgs[1].addr= client->addr;  
  76.     msgs[1].flags = client->flags & (I2C_M_TEN|I2C_CLIENT_PEC);  
  77.     msgs[1].flags |= I2C_M_RD;  
  78. 相關推薦

    Linux I2C驅動分析實現--例子

    通過上篇《Linux I2C驅動分析與實現(二)》,我們對Linux子系統已經不陌生,那麼如何實現I2C驅動呢? 編寫客戶驅動的方法 在核心中有兩種方式的i2c客戶驅動的編寫方法,一種叫legacy傳統方式,另一種是newstyle方式. 前 一種legacy是一種舊式的方法,在2.

    linux驅動學習(八) i2c驅動架構(史上最全) davinc dm368 i2c驅動分析

    預備知識 在閱讀本文最好先熟悉一種i2c裝置的驅動程式,並且瀏覽一下i2c-core.c以及晶片提供商的提供的i2c匯流排驅動(i2c-davinci.c)。標題黨請見諒! 其實i2c介面非常的簡單,即使用51單片的gpio來模擬i2c,編寫一個e2prom或者其他i2c介

    LinuxI2C驅動分析(一)

            最近在做一個基於全志A33晶片的android移植時發現嵌入式裝置很多都用到了I2C匯流排通訊,比如說攝像頭,G-sensor,觸控式螢幕等,為此我覺得很好的理解I2C裝置驅動在今後的嵌入式開發中是非常有好處的,而目前我也是處於學習階段,便將這些學習的過程給

    跳躍表的分析實現

    insert text 站點 avi 初始 解析 鏈接 solid water ----《大規模分布式存儲系統:原理解析與架構實戰》讀書筆記 在了解了 Bitcask存儲模型後,又開始研究LSM樹存儲引擎。LSM在實現的過程中使用了一個非常有意思的數

    linux系統故障分析排查

    使用 權限 建立 shel 自動識別 了解 緊急 rhel5 1.4 在處理Linux系統出現的各種故障時,故障的癥狀是最先發現的,而導致這以故障的原因才是最終排除故障的關鍵。熟悉Linux系統的日誌管理,了解常見故障的分析與解決辦法,將有助於管理員快速定位故障點。“對癥下

    Linux系統故障分析排查--日誌分析

    獲得 cat cron stl 文本格式 etc 服務的啟動 網絡 調試   處理Linux系統出現的各種故障時,故障的癥狀是最先發現的,而導致這以故障的原因才是最終排除故障的關鍵。熟悉Linux系統的日誌管理,了解常見故障的分析與解決辦法,將有助於管理員快速定位故障點,“

    Linux內核設計實現》讀書筆記(八)- 中斷下半部的處理

    sym dmesg 重新編譯 warn dad style lsp 之前 res 在前一章也提到過,之所以中斷會分成上下兩部分,是由於中斷對時限的要求非常高,需要盡快的響應硬件。 主要內容: 中斷下半部處理 實現中斷下半部的機制 總結中斷下半部的實現 中斷實現

    Linux內核設計實現》讀書筆記(十二)- 內存管理

    enable vmalloc 緩沖 turn lean png border 編譯 不一致 內核的內存使用不像用戶空間那樣隨意,內核的內存出現錯誤時也只有靠自己來解決(用戶空間的內存錯誤可以拋給內核來解決)。 所有內核的內存管理必須要簡潔而且高效。 主要內容: 內

    Linux內核設計實現》讀書筆記(十六)- 頁高速緩存和頁回寫

    第一次 源碼 進行 lose 減少 文件緩存 掩碼 recycle 創建 主要內容: 緩存簡介 頁高速緩存 頁回寫 1. 緩存簡介 在編程中,緩存是很常見也很有效的一種提高程序性能的機制。 linux內核也不例外,為了提高I/O性能,也引入了緩存機

    Linux crontab 命令格式詳細例子

    linux c 編輯 行程 目前 一封信 列表 art 表示 能夠 基本格式 : *  *  *  *  *  command 分 時 日 月 周 命令 第1列表示分鐘1~59 每分鐘用*或者 */1表示 第2列表示小時1~23(0表示0點) 第3列表示日期1~31 第4

    Java排序算法分析實現:快排、冒泡排序、選擇排序、插入排序、歸並排序(二)

    第一個元素 spa insert 循環 冒泡排序 author 高級算法 ins -s 一、概述:   上篇博客介紹了常見簡單算法:冒泡排序、選擇排序和插入排序。本文介紹高級排序算法:快速排序和歸並排序。在開始介紹算法之前,首先介紹高級算法所需要的基礎知識:劃分、遞歸,並順

    信息摘要算法之五:HMAC算法分析實現

    UC str 就是 n) auth 如果 輸出 返回 digest MAC(Message Authentication Code,消息認證碼算法)是含有密鑰散列函數算法,兼容了MD和SHA算法的特性,並在此基礎上加上了密鑰。因此MAC算法也經常被稱作HMAC算法。 1、H

    信息摘要算法之六:HKDF算法分析實現

    .com 方式 ems class 偽隨機 不一定 urn 如果 生成 HKDF是一種特定的鍵衍生函數(KDF),即初始鍵控材料的功能,KDF從其中派生出一個或多個密碼強大的密鑰。在此我們想要描述的是基於HMAC的HKDF。 1、HKDF概述 密鑰派生函數(KDF)是密碼系

    線程上下文類加載器分析實現

    背景 需求 clas htm ima ref 好的 技術分享 ren 在上一次【https://www.cnblogs.com/webor2006/p/9246850.html】分析源碼中發現有兩處設置線程上下文類加載器的代碼,如下: 因為它是非常重要的東東,所以

    數據壓縮算法---LZ77算法 的分析實現

    發現 如何 存儲 sse 而已 以及 turn 集合 alt LZ77簡介 Ziv和Lempel於1977年發表題為“順序數據壓縮的一個通用算法(A Universal Algorithm for Sequential Data Compression )”的論文,論文中描

    [轉載] Linux Futex的設計實現

    kernel 鎖機制 差異 做了 對齊 休眠 而是 () 解決 Linux Futex的設計與實現 引子 在編譯2.6內核的時候,你會在編譯選項中看到[*] Enable futex support這一項,上網查,有的資料會告訴你"不選這個內核不一定能正確的運行使用glib

    Android-貪吃蛇小遊戲-分析實現-Kotlin語言描述

    otl bject vid oid 小遊戲 同時 們的 http 畫布 Android-貪吃蛇小遊戲-分析與實現-Kotlin語言描述 Overview 本章的主要的內容是貪吃蛇小遊戲的分析和實現,關於實現的具體代碼可以在,文章底部的github的鏈接中找到。 整個遊戲通過

    Linux 8250驅動分析

    com for 目前 lin .html www. http ibm mat 1. 介紹 8250是IBM PC及兼容機使用的一種串口芯片; 16550是一種帶先進先出(FIFO)功能的8250系列串口芯片; 16550A則是16550的升級版本, 修復了FIFO相關BUG

    Linux I2C驅動--用戶態驅動簡單示例

    圖片 irq 代碼 eth pri 根據 debug disable sla 1. Linux內核支持I2C通用設備驅動(用戶態驅動:由應用層實現對硬件的控制可以稱之為用戶態驅動),實現文件位於drivers/i2c/i2c-dev.c,設備文件為/dev/i2c-0

    Linux內核設計實現高清版pdf免費下載

    以及 處理機 指定 ddr 中斷處理 回寫 2.3 結合 用處 下載地址:網盤下載 備用地址:網盤下載 內容簡介編輯《Linux內核設計與實現(原書第3版)》基於Linux 2.6.34內核詳細介紹了Linux內核系統,覆蓋了從核心內核系統的應用到內核設計與實