2014-04-05 i2c设备驱动程序读写EEPROM(smbus协议)

来源:互联网 发布:php工程师工资低 编辑:程序博客网 时间:2024/06/05 03:43

实验描述:

i2c设备驱动程序读写EEPROM


注意事项:

注意设备号起始开始的设置


内核版本:

Linux 2.6.38


开发板: 

 Mini 6410


实验结果截图:



驱动程序:

i2c_eeprom.c

#include <linux/init.h>  #include <linux/module.h>  #include <linux/device.h>#include <linux/cdev.h> #include <linux/i2c.h>#include <linux/fs.h> #include <asm/uaccess.h>  //we can learn the code from linux-2.6.38\drivers\misc\eeprom\at24.c#define DEVICE_NAME "i2c_eep"struct i2c_eep{struct i2c_client *client;struct cdev eep_cdev;};static struct i2c_eep my_eep;static dev_t devt_number;static struct class *i2c_epp_class;ssize_t epp_read (struct file *file, char __user *buf, size_t size, loff_t *offset){unsigned char address, data;copy_from_user(&address, buf, 1);printk(KERN_ALERT"kernel hello read!address:%d\n", address);data = i2c_smbus_read_word_data(my_eep.client, address);printk(KERN_ALERT"kernel hello read!data%d\n", data);copy_to_user(buf, &data, 1);}ssize_t epp_write (struct file *file, const char __user *buf, size_t size, loff_t *offset){unsigned char data[2];copy_from_user(data, buf, 2);printk(KERN_ALERT"kernel hello write!address:%d, data:%d\n", data[0], data[1]);i2c_smbus_write_byte_data(my_eep.client, data[0], data[1]);}int epp_open (struct inode *node, struct file *file){printk(KERN_ALERT"hello open!\n");return 0;}struct file_operations eep_ops = {.owner = THIS_MODULE,.read = epp_read,.write = epp_write,.open = epp_open,};int eep_probe(struct i2c_client *client, const struct i2c_device_id *device_id_tables){my_eep.client = client;printk(KERN_ALERT"my eep register!\n");return 0;}int eep_remove(struct i2c_client *client){printk(KERN_ALERT"my eep remove!\n");return 0;}static const struct i2c_device_id eep_id[] = {{ "at24c08", 0 },{ }};static struct i2c_driver i2c_epp_driver = {.driver = {.name = "my_eep",.owner = THIS_MODULE,},.probe = eep_probe,.remove = eep_remove,.id_table = eep_id,};static int eeprom_init(void)  {   if(alloc_chrdev_region(&devt_number, 2, 1, DEVICE_NAME) < 0){//the firstnor very impotantprintk(KERN_ALERT"Sorry, Can not register this device!\n");return -1;}cdev_init(&my_eep.eep_cdev, &eep_ops);if(cdev_add(&my_eep.eep_cdev, devt_number, 1)){printk(KERN_ALERT"Sorry, bad kmalloc!\n");return 1;}i2c_epp_class = class_create(THIS_MODULE, DEVICE_NAME);device_create(i2c_epp_class, NULL, MKDEV(MAJOR(devt_number), 2), NULL, DEVICE_NAME);int err;err = i2c_add_driver(&i2c_epp_driver);if(err){printk(KERN_ALERT"Sorry, register i2c failure!\n");return err;}printk(KERN_ALERT"Success!\n");return 0;  }  static int eeprom_exit(void)  {    i2c_del_driver(&i2c_epp_driver);device_destroy(i2c_epp_class, MKDEV(MAJOR(devt_number), 2));class_destroy(i2c_epp_class);cdev_del(&my_eep.eep_cdev);unregister_chrdev_region(MKDEV(MAJOR(devt_number), 2), 1);printk (KERN_EMERG "cdev i2c_eep Byebye\n");   return 0;  }   module_init(eeprom_init);  module_exit(eeprom_exit);MODULE_LICENSE("GPL");  

at24cxx_dev.c

#include <linux/kernel.h>#include <linux/module.h>#include <linux/platform_device.h>#include <linux/i2c.h>#include <linux/err.h>#include <linux/slab.h>static struct i2c_board_info at24cxx_info = {I2C_BOARD_INFO("at24c08", 0x50),};static struct i2c_client *at24cxx_client;static int at24cxx_dev_init(void){struct i2c_adapter *i2c_adap;i2c_adap = i2c_get_adapter(0);at24cxx_client = i2c_new_device(i2c_adap, &at24cxx_info);i2c_put_adapter(i2c_adap);return 0;}static void at24cxx_dev_exit(void){i2c_unregister_device(at24cxx_client);}module_init(at24cxx_dev_init);module_exit(at24cxx_dev_exit);MODULE_LICENSE("GPL");

测试程序:

#include <stdio.h>#include <stdlib.h>#include <fcntl.h>int main(int argc, char **argv){int fd;unsigned char buf[2];fd = open("/dev/i2c_eep", O_RDWR);if (fd < 0){printf("can't open /dev/i2c_eep\n");return -1;}if (strcmp(argv[1], "r") == 0){buf[0] = strtoul(argv[2], NULL, 0);read(fd, buf, 1);printf("read data: %c, %d, 0x%2x\n", buf[0], buf[0], buf[0]);}else if (strcmp(argv[1], "w") == 0){buf[0] = strtoul(argv[2], NULL, 0);buf[1] = strtoul(argv[3], NULL, 0);write(fd, buf, 2);}return 0;}


0 0