I2C裝置驅動的編寫 二

2021-06-12 19:18:34 字數 4656 閱讀 2079

前面我們說了如何i2c使用者模式驅動,這種驅動基於i2c子系統,但是他對於應用程式開發人員的要求較高,需要應用程式開發人員了解硬體的一些東西,比如時序,位址等等,而多數時候應用程式開發人員是按照操作檔案的方法操作裝置,所以我們更希望用一些更簡單的介面去訪問。也就是我們今天的內容——基於i2c子系統的字元驅動。

i2c子系統的**分為三部分如圖:

host:主機控制器驅動

device:裝置驅動**

core: 核心**,提供裝置與控制器的介面

一、主機控制器驅動

linux下主機控制器驅動,大多數是bsp提供的,這裡不多說,簡單說下它主要幹的活。i2c主機控制器在核心裡又叫介面卡,用結構i2c_adapter描述。

struct i2c_adapter ;

struct i2c_algorithm 提供裝置訪問控制器的介面,定義如下:

struct i2c_algorithm ;

其中master_xfer就是我們給裝置端提供的介面,這部分內容按照晶元手冊中暫存器的操作實現資料的收發。

最終我們將i2c_adapter註冊到系統中,使用如下函式:

int i2c_add_numbered_adapter(struct i2c_adapter *);

二、核心**

這部分就不說了,剛才我們介紹的函式全部是核心**提供,它主要是提供標準的統一的介面。

三、裝置**

基於i2c的字元驅動的編寫首先我們需要了解幾個特定的結構。

1、i2c_bus_type

i2c匯流排結構定義了一些匯流排相關的方法,這裡我們關係的是i2c_driver和i2c_client的配備規則,為什麼匹配呢,i2c_client攜帶硬體資訊,而i2c_driver只負責操作裝置而不管操作的是那個裝置它需要的硬體資訊有i2c_client提供,所以需要i2c_client和i2c_driver協同操作,而乙個系統中i2c_driver和i2c_client都可能有多個,如何得到自己的另一半就是我所說的匹配規則,i2c_bus_type的匹配規則定義如下:

struct bus_type i2c_bus_type = ;

static int i2c_device_match(struct device *dev, struct device_driver *drv)

我們發現i2c匯流排的匹配規則是id或name兩種,id優先順序高。

2、板級結構:

struct i2c_board_info ;

板子上沒有乙個i2c的裝置,我們就要註冊乙個這樣的結構體,到核心裡邊,這部分**一般新增在平台**裡邊,註冊函式如下:

i2c_register_board_info(int busnum, struct i2c_board_info const *info,unsigned n);

busnum 現在很多cpu有多條i2c匯流排,這個引數表示第幾條匯流排

info 是乙個結構體資料,表示我們要註冊的i2c裝置

n 表示我們註冊了幾個i2c裝置

通過上面函式就能把裝置註冊到系統中。結構如圖:

這個結構我們不需要操作,是作業系統即核心**自動完成,這個過程其實是在註冊i2c_adapter的時候完成的。即在函式i2c_add_numbered_adapter中完成,最終i2c_client攜帶者i2c_board_info和i2c_adapter的資訊。

4、i2c_driver

這部分**主要負責註冊i2c_driver和匹配相應的i2c_client。i2c_driver定義如下:

struct i2c_driver ;

註冊函式如下:

int i2c_add_driver(struct i2c_driver *driver);

這個函式負責註冊i2c_driver並匹配i2c_client,當匹配到了對於的i2c_client,probe函式被執行,並且i2c_client被以引數的形式傳遞過來。我們可以通過i2c_client提供的硬體資訊和操作介面操作我們想要的裝置。

5、資料傳輸

資料傳輸結構:

struct i2c_msg ;

訊息的封裝與上節使用者模式驅動相似,封裝好訊息使用如下函式提交給核心**,最終通過控制器驅動傳送給具體的裝置。

int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);

adap 介面卡,由client->adapter獲得。

msgs 訊息

num 訊息個數

通過上面內容我們就可以構建我們的基於linux下i2c子系統的裝置驅動了,例程如下:

平台**新增:

static struct i2c_board_info i2c_devs0 __initdata = ,

};i2c_register_board_info(0, i2c_devs0, array_size(i2c_devs0));

驅動**:

#include < linux/module.h>

#include < linux/kernel.h>

#include < linux/init.h>

#include < linux/fs.h>

#include < linux/cdev.h>

#include < linux/i2c.h>

#include < linux/slab.h>

#include < asm/uaccess.h>

module_license ("gpl");

#define lm75_reg_conf         0x01

static const u8 lm75_reg_temp[3] = ;

struct lm75_data

;static int lm75_major = 250;

static int lm75_minor = 0;

static int number_of_devices = 1;

static dev_t devno = 0;

static struct cdev cdev;

static struct i2c_client *new_client;

struct lm75_data *data;

static int lm75_read_value(struct i2c_client *client)

static ssize_t lm75_read(struct file *file, char __user *buff, size_t count, loff_t *offset)

printk("status = %x\n", status);

if(copy_to_user(buff, (char *)&status, sizeof(status)))

return -efault;

return 0;

}static int lm75_open(struct inode *inode, struct file *file)

static int lm75_release(struct inode *inode, struct file *file)

static struct file_operations lm75_fops = ;

static int lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)

cdev_init(&cdev, &lm75_fops);

cdev.owner = this_module;

ret = cdev_add(&cdev, devno, number_of_devices);

if(ret)

return 0;

err_cdev_add:

unregister_chrdev_region(devno, number_of_devices);

err_register_chrdev_region:

kfree(data);

return ret;

}static int lm75_remove(struct i2c_client *client)

enum lm75_type ;

static const struct i2c_device_id lm75_ids = ,,};

static struct i2c_driver lm75_driver = ,

.probe = lm75_probe,

.remove = lm75_remove,

.id_table = lm75_ids,

};static int __init s5pc100_lm75_init(void)

static void __exit s5pc100_lm75_exit(void)

module_init(s5pc100_lm75_init);

module_exit(s5pc100_lm75_exit);

I2C裝置驅動的編寫

前面我們說了如何i2c使用者模式驅動,這種驅動基於i2c子系統,但是他對於應用程式開發人員的要求較高,需要應用程式開發人員了解硬體的一些東西,比如時序,位址等等,而多數時候應用程式開發人員是按照操作檔案的方法操作裝置,所以我們更希望用一些更簡單的介面去訪問。也就是我們今天的內容 基於i2c子系統的字...

核心中編寫i2c裝置驅動

二 核心中編寫i2c裝置驅動 核心編寫i2c裝置驅動支援兩種方式 adapter方式 legacy 和probe方式 new style 1.legacy方式 此方法驅動需要自己建立i2c client,並且要知道晶元的位址,在核心目錄documentation i2c upgrading clie...

i2c裝置驅動

1,i2c 裝置註冊 static struct i2c board info i2c2 devices i2c裝置一般在板級 中註冊 static void msm8916 add i2c deivces void 2,i2c驅動註冊 include static const struct i2c...