代码示例_i2c读写e2prom驱动_2

 

 

 

 

i2c_eeprom.c


 

 

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/fs.h>
  4 #include <linux/device.h>
  5 #include <linux/slab.h>
  6 #include <linux/gpio.h>
  7 #include <linux/i2c.h>
  8 #include <linux/mod_devicetable.h>
  9 
 10 
 11 #include <asm/io.h>
 12 #include <asm/uaccess.h>
 13 
 14 
 15 //设计一个全局的设备类型
 16 struct i2c_e2prom{
 17     int dev_major;
 18     struct class *cls;
 19     struct device *dev;
 20     struct i2c_client *client;  //记录当前匹配的client
 21 };
 22 struct i2c_e2prom *at24_dev;
 23 
 24 int at24_e2prom_drv_open(struct inode *inode , struct file * filp)
 25 {
 26     printk("---------^_^ %s-----------\n",__FUNCTION__);
 27     return 0;
 28 }
 29 
 30 //编写一个封装了i2c_transfer的类似于i2c_master_recv的函数
 31 int at24_i2c_read(const struct i2c_client *client, const char *buf,int size)
 32 {
 33     int ret;
 34     struct i2c_adapter *adapter;
 35     struct i2c_msg msg;
 36     printk("---------^_^ %s-----------\n",__FUNCTION__);
 37 
 38     adapter = at24_dev->client->adapter;
 39 
 40     msg.addr = at24_dev->client->addr;
 41     msg.flags |= I2C_M_RD;
 42     msg.len = size;
 43     msg.buf = buf;
 44 
 45     //参数1 ---- 适配器
 46     //参数2 ---- 数据包
 47     //参数3 ---- 数据的个数
 48     ret = i2c_transfer(adapter, &msg, 1);
 49 
 50     return ret == 1?size:ret;
 51     
 52 }
 53 //编写一个封装了i2c_transfer的类似于i2c_master_send的函数
 54 int at24_i2c_write(const struct i2c_client *client, const char *buf,int size)
 55 {
 56     int ret;
 57     struct i2c_adapter *adapter;
 58     struct i2c_msg msg;
 59     printk("---------^_^ %s-----------\n",__FUNCTION__);
 60 
 61     adapter = at24_dev->client->adapter;
 62 
 63     msg.addr = at24_dev->client->addr;
 64     msg.flags = 0;
 65     msg.len = size;
 66     msg.buf = buf;
 67 
 68     //参数1 ---- 适配器
 69     //参数2 ---- 数据包
 70     //参数3 ---- 数据的个数
 71     ret = i2c_transfer(adapter, &msg, 1);
 72 
 73     return ret == 1?size:ret;
 74     
 75 }
 76 
 77 
 78 ssize_t at24_e2prom_drv_read (struct file *filp , char __user *buf , size_t count, loff_t * flags)
 79 {
 80     int ret;
 81     char *tmp;
 82     printk("---------^_^ %s-----------\n",__FUNCTION__);
 83 //    if(count < 0 || count > 256)
 84     //    return -EINVAL;        
 85 
 86     tmp = kzalloc(count, GFP_KERNEL);
 87     
 88     // 1, 从硬件中获取数据
 89     ret = at24_i2c_read(at24_dev->client, tmp, count);
 90     if(ret < 0){
 91         printk("at24_i2c_read error\n");
 92         goto err_kfree;
 93     }
 94 
 95     // 2, 将数据给由用户
 96     ret = copy_to_user(buf, tmp, count);
 97     if(ret > 0){
 98         printk("copy_to_user error\n");
 99         goto err_kfree;
100     }
101 
102     kfree(tmp);
103     return count;
104 err_kfree:
105     kfree(tmp);
106     return ret;
107         
108 }
109 ssize_t at24_e2prom_drv_write(struct file *filp, const char __user *buf, size_t count , loff_t * flags)
110 {
111     int ret;
112     char *tmp;
113     printk("---------^_^ %s-----------\n",__FUNCTION__);
114 //    if(size < 0 || size > 256)
115 //        return -EINVAL;        
116 
117     tmp = kzalloc(count, GFP_KERNEL);
118     
119     // 1, 获取用户空间的数据
120     ret = copy_from_user(tmp, buf, count);
121     if(ret > 0){
122         printk("copy_from_user error\n");
123         goto err_kfree;
124     }
125     
126     // 2,将数据写入到硬件(从设备)中
127     ret = at24_i2c_write(at24_dev->client, tmp, count);
128     if(ret < 0){
129         printk("at24_i2c_write error\n");
130         goto err_kfree;
131     }
132 
133     kfree(tmp);
134     return count;
135 err_kfree:
136     kfree(tmp);
137     return ret;
138     
139 }
140 int at24_e2prom_drv_close(struct inode *inode , struct file *filp)
141 {
142     printk("---------^_^ %s-----------\n",__FUNCTION__);
143     return 0;
144 }
145 
146 const struct file_operations at24_fops = {
147     .open = at24_e2prom_drv_open,
148     .read = at24_e2prom_drv_read,
149     .write = at24_e2prom_drv_write,
150     .release = at24_e2prom_drv_close,
151 };
152 
153 int at24_drv_probe(struct i2c_client * client, const struct i2c_device_id * id)
154 {
155     printk("-------id->name = %s, id->driver_data = 0x%x-----------\n",id->name,id->driver_data);
156     //0,实例化设备对象
157     at24_dev = kzalloc(sizeof(struct i2c_e2prom), GFP_KERNEL);
158     
159     //1, 申请设备号
160     at24_dev->dev_major = register_chrdev(0, "at24_drv", &at24_fops);
161     
162     //2,创建设备节点
163     at24_dev->cls = class_create(THIS_MODULE, "at24_cls");
164     at24_dev->dev = device_create(at24_dev->cls, NULL, MKDEV(at24_dev->dev_major, 0), NULL, "at24_e2prom");
165 
166     //保存当前client
167     at24_dev->client = client;
168 
169     
170     //3,硬件初始化 ----- e2prom只要上电就可以工作
171     //4,实现fops
172 
173     return 0;
174 }
175 int at24_drv_remove(struct i2c_client * client)
176 {
177     device_destroy(at24_dev->cls, MKDEV(at24_dev->dev_major, 0));
178     class_destroy(at24_dev->cls);
179     unregister_chrdev(at24_dev->dev_major, "at24_drv");
180     kfree(at24_dev);
181 
182     return 0;
183 }
184 
185 const struct i2c_device_id at24_id_table[] = {
186     {"at24c02a", 0x2222},
187     {"at24c04a", 0x2222},
188     {"at24c08a", 0x2222},
189 };
190 
191 
192 struct i2c_driver at24_drv = {
193     .probe =    at24_drv_probe,
194     .remove =     at24_drv_remove,
195     .driver = {
196             .name = "at24_e2prom_drv",        //不会用于比对
197                 //   /sys/i2c/driver/at24_e2prom_drv
198     },
199     .id_table = at24_id_table,
200 };
201 
202 
203 static int __init at24_drv_init(void)
204 {
205     //注册一个i2c_driver
206     return i2c_add_driver(&at24_drv);
207 }
208 
209 
210 static void __exit at24_drv_exit(void)
211 {
212     i2c_del_driver(&at24_drv);
213 }
214 
215 
216 module_init(at24_drv_init);
217 module_exit(at24_drv_exit);
218 MODULE_LICENSE("GPL");

 

 

app.c


 

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <unistd.h>
 5 #include <sys/types.h>
 6 #include <sys/stat.h>
 7 #include <sys/ioctl.h>
 8 #include <fcntl.h>
 9 #include <linux/i2c-dev.h>
10 
11 
12 int main(int argc,char **argv)
13 {
14     int fd;
15     unsigned char val;  //8bit变量
16     char register_addr = 0x08;     //片内地址
17     int res;
18     char wbuf[10];
19     char rbuf[10];
20 
21     if(argc < 2){
22     printf("%s r :read at24c02 address 0\n",argv[0]);
23     printf("%s w  val:write at24c02 address 0\n",argv[0]);
24     exit(1);
25     }
26 
27     //打开设备
28     fd = open("/dev/at24_e2prom",O_RDWR);
29     if(fd < 0){
30     perror("open");
31     exit(1);
32     }
33 
34     if(!strncmp(argv[1],"r",1)){  //从硬件中读数据  
35 
36     //先将片内地址写给控制器
37     if(write(fd,&register_addr,1) != 1){
38         perror("write");
39         exit(1);
40     }
41     //再去读取硬件中的数据
42     if(read(fd,rbuf,1) != 1){
43         perror("read");
44         exit(1);
45     }else{
46         printf("rbuf = 0x%x\n",rbuf[0]);
47     }
48 
49     }else if((argc == 3) && !strncmp(argv[1],"w",1)){  //向硬件中写数据:argv[2]
50     // ./at24_e2prom_app  w 0x99
51 
52     val = strtoul(argv[2],NULL,0);
53     wbuf[0] = register_addr; //片内地址0x08
54     wbuf[1] = val;
55 
56     if(write(fd,wbuf,2) != 2){
57         perror("write");
58         exit(1);
59     }
60     printf("write data ok!\n");
61     }
62 
63     close(fd);
64     return 0;
65 }

 

 

makefile


 

 

 1 CRAOSS_COMPILE = arm-none-linux-gnueabi-
 2 CC = $(CRAOSS_COMPILE)gcc
 3 
 4 MODULE_NAME1 = at24_i2c_e2prom
 5 #MODULE_NAME2 = plat_input_dev
 6 MYAPP =  at24_i2c_app
 7 
 8 #指定内核源码的路径
 9 KERNEL_DIR = /home/lpf/s5pv210/kernel/linux-3.0.8
10 CUR_DIR = ${shell pwd}
11 
12 all:
13     #make进入内核源码目录,并告诉内核将当前路径下的源码编译为内核的模块
14     make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
15     $(CC) -o $(MYAPP) $(MYAPP).c
16 clean:
17     #删除编译过程中生成的文件
18     make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
19     $(RM) $(MYAPP) .*.sw?
20 install:
21     cp *.ko $(MYAPP) /opt/rootfs/drv_module
22 
23 #指定将哪个源文件编程为内核模块
24 obj-m := $(MODULE_NAME1).o
25 #obj-m += $(MODULE_NAME2).o
26     

 

 


 

posted @ 2019-07-02 09:42  panda_w  阅读(842)  评论(0编辑  收藏  举报