Android 驅動(二) IIC簡介

來源:互聯網
上載者:User

一、 I2C簡介


I2C(Inter-Integrated Circuit)匯流排是一種由 Philips 公司開發的兩線式串列匯流排,用於串連微控制器及其外圍裝置。I2C 匯流排最主要的優點就是簡單性和有效性,簡單體現在接線簡單,只有兩根線資料線(SCL)和時鐘線(SDA),而且 控制簡單。所以一些封裝較小的器件多使用I2C匯流排,常見的使用I2C匯流排的裝置有EEPROM、RTC及一些感應器。這裡我們介紹下基於linux的I2C裝置驅動的編寫。


  • I2C裝置驅動的編寫有多種方式


    一種是直接操作CPU的I2C控制器,正對於某一個裝置寫一個字元驅動,這種驅動相對來說比較直接,不需要太依賴於核心相關配置,但是這類裝置驅動依賴CPU,可移植性較差。

    一種是基於linux核心I2C子系統完成裝置驅動的編寫,一般核心會繼承相關CPU的控制器驅動即使沒有也可以通過支援人員可以獲得,所以我們只需要使用linux下I2C子系統提供的相關介面來構建我們的裝置驅動就行了。這樣我們的裝置驅動並不依賴於某一個特定的CPU,可移植性較好。

    IIC驅動主要分為Master和Slave,Master就是主機控制器,像A10內部的IIC控制器就是一個Master, Slave就是IIC從機裝置,它要被掛接到Master上才能工作
    智能手機和平板電腦上用的sensor幾乎都是IIC裝置,最常用的IIC裝置就是電容觸控螢幕和網路攝影機,接下來,我們將針對觸控螢幕、EEPROM、網路攝影機等驅動來分析。

    • I2C匯流排工作原理

      I2C 匯流排是由資料線 SDA 和時鐘 SCL 構成的串列匯流排,各種被控制器件均

      並聯在這條匯流排上,每個器件都有一個唯一的地址識別,可以作為匯流排上的一個


      發送器件或接收器件(具體由器件的功能決定)。I2C 匯流排的介面電路結構 1所示


      • I2C 匯流排的幾種訊號狀態

        1. 空閑狀態:SDA 和 SCL 都為高電平。

        2. 開始條件(S):SCL 為高電平時,SDA 由高電平向低電平跳變,開始傳送資料。

        3. 結束條件(P):SCL 為高電平時,SDA 由低電平向高電平跳變,結束傳送資料。

        4. 資料有效:在 SCL 的高電平期間,SDA 保持穩定,資料有效。SDA 的改變只能發生在 SCL 的低電平期間。

        5. ACK 訊號:資料轉送的過程中,接收器件每接收一個位元組資料要產生一個 ACK 訊號,向發送器件發出特定的低電平脈衝,表示已經收到資料。


        • I2C 匯流排基本操作

          I2C 匯流排必須由主器件(通常為微控制器)控制,主器件產生串列時鐘(SCL),同時控制匯流排的傳輸方向,併產生開始和停止條件。

          資料轉送中,首先由主器件產生開始條件,隨後是器件的控制位元組(前七位是從器件的地址,最後一位為讀寫位)。接下來是讀寫操作的資料,以及 ACK響應訊號。資料轉送結束時,主器件產生停止條件。具體的過程 2 所示。





          二、Linux 系統 I2C 驅動程式
          • I2C驅動階層
            Linux 系統對 I2C 裝置具有很好的支援,Linux 系統下的 I2C 驅動程式從邏 輯上可以分為 3 個部分: 1. I2C 核心(I2C core):實現對 I2C 匯流排、I2C adapter 及 I2C driver 的管理。 2. I2C 控制器驅動 I2C adapter :針對不同類型的 I2C 控制器 ,實現對 I2C 匯流排訪問的具體方法。 3. I2C 裝置驅動 I2C driver:針對特定的 I2C 裝置,實現具體的功能,包括read,write 以及 ioctl 等對使用者層操作的介面。
            這三個部分的層次關係 3 和圖 4 所示。








            • I2C 核心(I2C core)
              I2C core 是 Linux 核心用來維護和管理 I2C 的核心部分,其中維護了兩個靜 態的 List,分別記錄系統中的 I2C driver 結構和 I2C adapter 結構。I2C core 提供 介面函數,允許一個 I2C adapter,I2C driver 和 I2C client 初始化時在I2C core 中 進行註冊,以及退出時進行登出。同時還提供了 I2C 匯流排讀寫訪問的一般介面(具 體的實現在與 I2C 控制器相關的 I2C adapter 中實現),主要應用在 I2C 裝置驅動中。
              • I2C 控制器驅動(I2C adapter)
                I2C adapter 是針對不同類型 I2C 控制器硬體,實現比較底層的對 I2C 匯流排訪 問的具體方法。I2C adapter 構造一個對 I2C core 層介面的資料結構,並通過介面函數向 I2C core 註冊一個控制器。 I2C adapter 主要實現對 I2C 匯流排訪問的演算法,master_xfer()函數就是 I2C adapter 底層對 I2C 匯流排讀寫方法的實現。同時 I2C adapter 中還實現了對 I2C 控制器中斷的處理函數。

                • I2C 裝置驅動(I2C driver)
                  I2C driver 是對 I2C 從裝置的軟體實現。I2C driver 中提供了一個通用的 I2C 裝置的驅動程式,實現了字元類型裝置的提供者,對裝置的具體訪問是通過 I2C adapter 來實現的。I2C driver 構造一個對 I2C core 層介面的資料結構,通過 介面函數向 I2C Core 註冊一個 I2C 裝置驅動。同時 I2C driver 構造一個對使用者層介面的資料結構,並通過介面函數向核心註冊為一個主裝置號為 89 的字元類型裝置。I2C driver 實現使用者層對 I2C 裝置的訪問,包括 open,read,write,ioctl,release 等常規檔案操作,可以通過 open 函數開啟 I2C 裝置檔案,通過 ioctl 函數設定要訪問 I2C 裝置的地址,然後就可以通過 read 和 write 函數完成對 I2C 裝置的讀寫操作。通過 I2C driver 提供的通用方法可以訪問任何一個 I2C 的裝置,但是其中實 現的 read,write 及 ioctl 等功能完全是基於一般裝置的實現,所有的操作資料都是基於位元組流,沒有明確的格式和意義。為了更方便和有效地使用 I2C 裝置,可 以為一個具體的 I2C 裝置開發特定的 I2C 裝置驅動程式,在驅動中完成對特定的資料格式的解釋以及實現一些專用的功能。

                  三、 基於 SUNXI 平台的 I2C 控制器驅動
                  位於drivers/i2c/busses目錄下的檔案i2c-sunxi.c,是基於sunxi平台實現的I2C 匯流排控制器驅動。它的職責是為系統中 3 條 I2C 匯流排實現相應的讀寫方法,但是控制器驅動本身並不會進行任何的通訊,而是等待裝置驅動調用其函數。 圖 5 是基於 SUNXI 平台的 I2C 驅動層次架構圖,圖中有 3 塊 I2C adapter,分別對應 SUNXI 平台上的 3 塊 I2C 控制器源碼結構
                  在 drivers/i2c/目錄下,包含有幾個重要檔案和目錄,如下:1. 檔案 i2c-core.c:I2C 子系統核心功能的實現; 2. 檔案 i2c-dev.c:通用的從裝置驅動實現; 3. 目錄 busses:裡麵包括基於不同平台實現的 I2C 匯流排控制器驅動; 4. 目錄 algos:裡面實現了一些 I2C 匯流排控制器的 algorithm。
                  四、I2C 裝置驅動程式的開發
                  • I2C 裝置驅動一般結構
                    一個具體的 I2C 裝置驅動需要實現兩個方面的介面,一方面是對 I2C core 層的介面,用以掛接 I2C adapter 來實現對 I2C 匯流排及 I2C 裝置具體的存取方法, 包括要實現 probe,remove,detect 等介面函數;另一方面是對使用者應用程式層的接 口,提供使用者程式訪問 I2C 裝置的介面,包括實現 open,release,read,write 以及最重要的 ioctl 等標準檔案操作的介面函數。 對 I2C core 層的介面函數的具體功能解釋如下:
                    probe:I2C driver 進行裝置綁定的回呼函數。remove:I2C driver 解除裝置綁定的回呼函數。detect:I2C 裝置探測回呼函數,它會識別所支援的裝置(返回 0 表示支援, 否則返回-ENODEV);此外,需要定義一個供探測的地址清單(address_list)和 一個裝置類型(class),這樣使那些僅匹配裝置類型的 i2c 匯流排被探測到。例如, 對 於 一 個 自 動 監 測 硬 件 芯 片 的 驅 動 將 會 設 置 它 的 class 域 為 I2C_CLASS_HWMON,只有那些 class 域為 I2C_CLASS_HWMON 的控制器能 夠被驅動探測。
                    • 常用資料結構解析
                      i2c_adapter
                      struct i2c_adapter {
                      struct module *owner; /* 所屬模組 */ unsigned int id; /* algorithm 的類型,定義於 i2c-id.h,以 I2C_ALGO_開始 */ unsigned int class;const struct i2c_algorithm *algo; /* 匯流排通訊方法結構體指標 */void *algo_data; /* algorithm 資料 */ struct rt_mutex bus_lock;int timeout; /* 逾時時間,以 jiffies 為單位 */ int retries; /* 重試次數 */ struct device dev; /* 控制器裝置 */ int nr;char name[48]; /* 控制器名稱 */ struct completion dev_released; /* 用於同步 */ struct mutex userspace_clients_lock;struct list_head userspace_clients;
                      };
                      i2c_adapter 對應於物理上的一個控制器。一個 I2C 控制器需要 i2c_algorithm 中提供的通訊函數來控制控制器上產生特定的訪問周期。

                      i2c_algorithm
                      struct i2c_algorithm {
                      /* I2C 傳輸函數指標 */int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);/* smbus 傳輸函數指標 */int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data); /* 返回控制器支援的功能 */u32 (*functionality) (struct i2c_adapter *);
                      };i2c_algorithm中的關鍵函數master_xfer()用於產生I2C訪問周期需要的訊號, 以 i2c_msg(即 I2C 訊息)為單位。

                      i2c_msg
                      struct i2c_msg {
                      __u16 addr; /* 從裝置地址 */ __u16 flags; /* 訊息類型 */ __u16 len; /* 訊息長度 */ __u8 *buf; /* 訊息資料 */
                      };
                      i2c_msg 是 I2C 傳輸的基本單位,它包含了從裝置的具體地址,訊息的類型 以及要傳輸的具體資料資訊。每個 I2C 訊息傳輸前,都會產生一個開始位,緊接 著傳送從裝置地址,然後開始資料的發送或接收,對最後的訊息還需產生一個停止位。
                      i2c_client
                      struct i2c_client {
                      unsigned short flags; /* 標誌 */ unsigned short addr; /* 低 7 位的晶片地址 */ char name[I2C_NAME_SIZE]; /* 裝置名稱 */ struct i2c_adapter *adapter; /* 依附的 i2c_adapter */ struct i2c_driver *driver; /* 依附的 i2c_driver */ struct device dev; int irq; /* 裝置使用的中斷號 */ struct list_head detected;
                      };
                      i2c_client 對應於真實的物理裝置,每個 I2C 裝置都需要一個 i2c_client 來描述。
                      i2c_driver
                      struct i2c_driver {
                      unsigned int class;int (*attach_adapter)(struct i2c_adapter *); /* 依附 i2c_adapter 函數指標 */ int (*detach_adapter)(struct i2c_adapter *); /* 脫離 i2c_adapter 函數指標 */ int (*probe)(struct i2c_client *, const struct i2c_device_id *);int (*remove)(struct i2c_client *);void (*shutdown)(struct i2c_client *);int (*suspend)(struct i2c_client *, pm_message_t mesg);int (*resume)(struct i2c_client *);void (*alert)(struct i2c_client *, unsigned int data);int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);struct device_driver driver;const struct i2c_device_id *id_table; /* 該驅動所支援的裝置識別碼 表 */ int (*detect)(struct i2c_client *, struct i2c_board_info *); /* 裝置探測函數 */ const unsigned short *address_list; /* 驅動支援的裝置地址 */ struct list_head clients; /* 掛接探測到的支援的裝置 */
                      };
                      i2c_driver 對應一套驅動方法,其主要成員函數是 probe()、remove()、 suspend()、resume()等,另外id_table是該驅動所支援的I2C裝置的ID表。i2c_driver 與 i2c_client 的關係是一對多,一個 i2c_driver 上可以支援多個同等類型的 i2c_client。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.