代码示例_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,®ister_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
Stay hungry, stay foolish
待续。。。