I2C驱动程序框架probe道路
基于Linux的I2C驅(qū)動(dòng)器。采納probe道路。根據(jù)這個(gè)框架,如下面就可以寫任何支持I2C總線設(shè)備Linux驅(qū)動(dòng)器。
I2C設(shè)備連接到cpu具體i2c接口。被安裝在cpu的i2c適配器。i2c設(shè)備和cpu信息交流需要通過cpu操作適配器互動(dòng)。cpu上有1個(gè)或多個(gè)適配器。每一個(gè)適配器上能夠掛載256個(gè)設(shè)備地址不一樣的i2c器件,通過i2c驅(qū)動(dòng)就能夠讓cpu和適配器上的多個(gè)不一樣的i2c器件通信而不會(huì)產(chǎn)生沖突。
驅(qū)動(dòng)包含兩個(gè)文件,dev.c和drive.c,當(dāng)中dev.c是構(gòu)建I2C設(shè)備,即創(chuàng)建I2C_Client結(jié)構(gòu)體。而driver.c是在probe中獲取dev.c中構(gòu)建的i2c_client,然后構(gòu)建fileoperation。詳細(xì)步驟結(jié)合代碼例如以下。
1、在dev的入口函數(shù)中構(gòu)建I2C-CLient
static unsigned short addr_list[] = {0x60, 0x50, I2C_CLIENT_END //這個(gè)數(shù)組包括了設(shè)備地址,以I2C_CLIENT_END為數(shù)組結(jié)尾</span>}; static struct i2c_client *at24cxx_client; //創(chuàng)建I2C_Client結(jié)構(gòu)體 static int at24cxx_dev_init(void) {/*構(gòu)建I2C_Client*/struct i2c_adapter *adapter;struct i2c_board_info info; adapter=i2c_get_adapter(0); //獲取適配器,由于有些cpu有多個(gè)I2C適配器。參數(shù)0為適配器編號(hào)memset(&info, 0, sizeof(struct i2c_board_info));strlcpy(info.type, "at24cxx", I2C_NAME_SIZE); //這個(gè)是I2C_NAME,是和i2c_driver匹配的keywordat24cxx_client=i2c_new_probed_device(adapter, &info, addr_list);//假設(shè)數(shù)組中地址的設(shè)備存在則成功返回i2c_client結(jié)構(gòu)體//這個(gè)函數(shù)終于會(huì)調(diào)用device_create創(chuàng)建設(shè)備i2c_put_adapter(adapter);if(at24cxx_client)return 0;else return -ENODEV; }2、在driver.c的入口函數(shù)中注冊(cè)I2C_driver結(jié)構(gòu)體
static const struct i2c_device_id = { { "at24cxx", 0 }, { } }; static struct i2c_driver at24cxx_driver = {.driver = {.name = "100ask",.owner = THIS_MODULE,},.probe = at24cxx_probe,.remove = __devexit_p(at24cxx_remove),.id_table = at24cxx_ids,//id_table中name是和dev創(chuàng)建i2c_client的name匹配,若匹配則會(huì)調(diào)用probe設(shè)備方法 };static int at24cxx_drv_init(void) {/*×¢2ái2c_driver*/return i2c_add_driver(&at24cxx_driver);}3、在probe設(shè)備方法中構(gòu)建file_operation注冊(cè)字符設(shè)備 static struct file_operations at24cxx_fops = {.owner = THIS_MODULE,.read = at24cxx_read,.write = at24cxx_write,};static int at24cxx_probe(struct i2c_client *client, const struct i2c_device_id *id) {printk("%s %s %d.\n",__FILE__,__FUNCTION__,__LINE__);at24cxx_client = client;//將dev中構(gòu)建的i2c_client結(jié)構(gòu)體傳遞過來,由于這個(gè)結(jié)構(gòu)體在read,write等設(shè)備方法中傳遞信息時(shí)須要用到major = register_chrdev(0,"at24cxx",&at24cxx_fops);//注冊(cè)字符設(shè)備class = class_create(THIS_MODULE,"at24cxx");device_create(class,NULL,MKDEV(major,0),NULL,"at24cxx");return 0; }4、構(gòu)建write和read等設(shè)備方法中傳遞I2C消息
static ssize_t at24cxx_read(struct file *file, char __user *buf, size_t count, loff_t *off) {unsigned char addr,data;copy_from_user(&addr,buf,1);data = i2c_smbus_read_byte_data(at24cxx_client,addr);//這里用i2c_smbus_read_byte_data函數(shù)來和實(shí)際的I2C設(shè)備進(jìn)行信息交互</span> //這里詳細(xì)用哪個(gè)函數(shù)來傳遞消息須要結(jié)合詳細(xì)的器件的時(shí)序。不同的時(shí)序有不同的傳遞函數(shù),查看Linux源代碼中的說明文檔有關(guān)于傳遞函數(shù)的說明。copy_to_user(buf,&data,1); return 0; } static ssize_t at24cxx_write(struct file *file, const char __user *buf, size_t count , loff_t *off) { unsigned char ker_buf[2]; unsigned char addr,data; copy_from_user(ker_buf,buf,2); addr = ker_buf[0]; data = ker_buf[1]; if(!i2c_smbus_write_byte_data(at24cxx_client,addr,data)) return 2; else return -EIO; }
假設(shè)i2c總線中掛載了實(shí)際的i2c設(shè)備,并且設(shè)備地址在以上的addr_list中,則不管是先載入dev.ko還是先載入driver.ko都會(huì)成功的運(yùn)行probe函數(shù),然后創(chuàng)建字符設(shè)備。在應(yīng)用程序中open設(shè)備,并調(diào)用read和write則會(huì)對(duì)應(yīng)的調(diào)用driver中的read和write設(shè)備方法。
測(cè)試應(yīng)用程序 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>/* i2c_test r addr* i2c_test w addr val*/void print_usage(char *file) {printf("%s r addr\n", file);printf("%s w addr val\n", file); }int main(int argc, char **argv) {int fd;unsigned char buf[2];if ((argc != 3) && (argc != 4)){print_usage(argv[0]);return -1;}fd = open("/dev/at24cxx", O_RDWR);if (fd < 0){printf("can't open /dev/at24cxx\n");return -1;}if (strcmp(argv[1], "r") == 0){buf[0] = strtoul(argv[2], NULL, 0);printf("before data: %c, %d, 0x%2x\n", buf[0], buf[0], buf[0]);read(fd, buf, 1);printf("data: %c, %d, 0x%2x\n", buf[0], buf[0], buf[0]);}else if ((strcmp(argv[1], "w") == 0) && (argc == 4)){buf[0] = strtoul(argv[2], NULL, 0);buf[1] = strtoul(argv[3], NULL, 0);if (write(fd, buf, 2) != 2)printf("write err, addr = 0x%02x, data = 0x%02x\n", buf[0], buf[1]);}else{print_usage(argv[0]);return -1;}return 0; }2014--12--17
征途開始
興許補(bǔ)充
轉(zhuǎn)載于:https://www.cnblogs.com/mfrbuaa/p/4593267.html
總結(jié)
以上是生活随笔為你收集整理的I2C驱动程序框架probe道路的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP实现同服务器多个二级域名共享 SE
- 下一篇: win10为什么所有的视频都看不了怎么办