在线问答
直播中

罗崇军

9年用户 168经验值
擅长:嵌入式技术 接口/总线/驱动
私信 关注

【OK210试用体验】之eeprom驱动

本帖最后由 罗崇军 于 2015-8-21 00:05 编辑

这俩天,趁着闲出来的时间做了eeprom的实验,自己写了eeprom的驱动,在这里与大家分享。
版本说明:
               平台:OK210;
                os :Linux2.6.35.7
                驱动类型:eeprom

驱动程序如下:
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include
  10. #include
  11. #include

  12. #define CHARDEVICEDRIVER_MAJOR                0
  13. #define CHARDEVICEDRIVER_MINOR                0

  14. struct at24cxx_dev
  15. {
  16.         struct device *dev_device;
  17.         struct i2c_client *client;
  18.         struct cdev cdev;
  19. };

  20. struct at24cxx_dev *at24cxx_devp = NULL;
  21. static struct class *dev_class = NULL;
  22. static u32 chardevicedriver_major = CHARDEVICEDRIVER_MAJOR;
  23. static u32 chardevicedriver_minor = CHARDEVICEDRIVER_MINOR;



  24. static const struct i2c_device_id at24cxx_id[] = {
  25.     {"at24cxx", 0 }, //该i2c_driver所支持的i2c_client
  26.     {}
  27. };
  28. MODULE_DEVICE_TABLE(i2c,at24cxx_id);


  29. static ssize_t at24cxx_read(struct file *file, char __user *buf, size_t size, loff_t * offset)
  30. {
  31.         unsigned char address;
  32.         unsigned char data;
  33.         struct i2c_msg msg[2];
  34.         int ret;
  35.         
  36.         /* address = buf[0]
  37.          * data    = buf[1]
  38.          */
  39.         if (size != 1)
  40.                 return -EINVAL;
  41.         
  42.         copy_from_user(&address, buf, 1);

  43.         /* 数据传输三要素: 源,目的,长度 */

  44.         /* 读AT24CXX时,要先把要读的存储空间的地址发给它 */
  45.         msg[0].addr  = at24cxx_devp->client->addr;  /* 目的 */
  46.         msg[0].buf   = &address;              /* 源 */
  47.         msg[0].len   = 1;                     /* 地址=1 byte */
  48.         msg[0].flags = 0;                     /* 表示写 */

  49.         /* 然后启动读操作 */
  50.         msg[1].addr  = at24cxx_devp->client->addr;  /* 源 */
  51.         msg[1].buf   = &data;                 /* 目的 */
  52.         msg[1].len   = 1;                     /* 数据=1 byte */
  53.         msg[1].flags = I2C_M_RD;                     /* 表示读 */


  54.         ret = i2c_transfer(at24cxx_devp->client->adapter, msg, 2);
  55.         if (ret == 2)
  56.         {
  57.                 copy_to_user(buf, &data, 1);
  58.                 return 1;
  59.         }
  60.         else
  61.                 return -EIO;
  62. }

  63. static ssize_t at24cxx_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
  64. {
  65.         unsigned char val[2];
  66.         struct i2c_msg msg[1];
  67.         int ret;
  68.         
  69.         /* address = buf[0]
  70.          * data    = buf[1]
  71.          */
  72.         if (size != 2)
  73.                 return -EINVAL;
  74.         
  75.         copy_from_user(val, buf, 2);

  76.         /* 数据传输三要素: 源,目的,长度 */
  77.         msg[0].addr  = at24cxx_devp->client->addr;  /* 目的 */
  78.         msg[0].buf   = val;                   /* 源 */
  79.         msg[0].len   = 2;                     /* 地址+数据=2 byte */
  80.         msg[0].flags = 0;                     /* 表示写 */

  81.         ret = i2c_transfer(at24cxx_devp->client->adapter, msg, 1);
  82.         if (ret == 1)
  83.                 return 2;
  84.         else
  85.                 return -EIO;
  86. }



  87. static struct file_operations at24cxx_fops = {
  88.         .owner        = THIS_MODULE,
  89.         //.open        = chardevicedriver_open,
  90.         .read        = at24cxx_read,
  91.         .write        = at24cxx_write,
  92.         //.ioctl        = chardevicedriver_ioctl,
  93.         //.release= chardevicedriver_release,
  94. };

  95. // add one cdev and create one device file
  96. static int chardevicedriver_cdev_add(struct at24cxx_dev *pcdevp, int index)
  97. {
  98.         int ret = -EFAULT;
  99.         dev_t dev = 0;

  100.         // add cdev object
  101.         dev = MKDEV( chardevicedriver_major, chardevicedriver_minor + index );
  102.         cdev_init( &(pcdevp->cdev), &at24cxx_fops);
  103.         ret = cdev_add( &(pcdevp->cdev), dev, 1 );


  104.         // create device
  105.         pcdevp->dev_device = device_create( dev_class, NULL, dev, NULL, "at24cxx%d", MINOR( dev ) );
  106.         
  107.         
  108.         return 0;
  109. }


  110. static int at24cxx_probe(struct i2c_client *client, const struct i2c_device_id *id)
  111. {
  112.         int ret;
  113.         dev_t dev = 0;

  114.         // register device number
  115.         if( chardevicedriver_major ) { // static device number
  116.                 dev = MKDEV( chardevicedriver_major, chardevicedriver_minor );
  117.                 ret = register_chrdev_region( dev, 1, "at24cxx" );
  118.         }
  119.         else { // dynamic device number
  120.                 ret = alloc_chrdev_region( &dev, chardevicedriver_minor, 1, "at24cxx" );
  121.                 chardevicedriver_major = MAJOR( dev );
  122.         }
  123.         
  124.         at24cxx_devp = kmalloc( sizeof( struct at24cxx_dev ), GFP_KERNEL );

  125.         memset(at24cxx_devp, 0, sizeof(struct at24cxx_dev));
  126.         at24cxx_devp->client = client;
  127.         
  128.         dev_class = class_create( THIS_MODULE, "at24cxx" );

  129.         
  130.         chardevicedriver_cdev_add(at24cxx_devp,0);
  131.         
  132.         return 0;
  133. }

  134. static int __devexit at24cxx_remove(struct i2c_client *client)
  135. {
  136.         device_destroy( dev_class, MKDEV( chardevicedriver_major, 0 ) );

  137.         cdev_del( &( at24cxx_devp->cdev ) );
  138.         
  139.         // destroy device class
  140.         class_destroy( dev_class );
  141.         // free memory for private struct
  142.         kfree( at24cxx_devp );
  143.         at24cxx_devp = NULL;

  144.         // unregister device number
  145.         unregister_chrdev_region( MKDEV( chardevicedriver_major, chardevicedriver_minor ), 1 );
  146.         return 0;
  147. }

  148. /* 1. 分配一个i2c_driver结构体 */
  149. /* 2. 设置i2c_driver结构体 */
  150. static struct i2c_driver at24cxx_driver = {
  151.         .driver = {
  152.                 .name        = "at24cxx",
  153.                 .owner = THIS_MODULE,
  154.         },
  155.         .probe=at24cxx_probe,
  156.         .remove=__devexit_p(at24cxx_remove),
  157.         .id_table=at24cxx_id,
  158. };

  159. static int __init at24cxx_init(void)
  160. {
  161.         i2c_add_driver(&at24cxx_driver);
  162.         return 0;
  163. }

  164. static void __exit at24cxx_exit(void)
  165. {
  166.         i2c_del_driver(&at24cxx_driver);
  167. }

  168. module_init(at24cxx_init);
  169. module_exit(at24cxx_exit);

  170. MODULE_LICENSE("GPL");

makefile文件如下
  1. all:
  2.         make -C $(SRC_PATH)/kernel M=`pwd` modules
  3.         cp at24cxx.ko $(SRC_PATH)/system/modules/ -av
  4. clean:
  5.         make -C $(SRC_PATH)/kernel M=`pwd` modules clean
  6.         rm -rf modules.order *.o *.ko *.mod.* Module.*

  7. obj-m        += at24cxx.o

测试程序如下

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include


  7. /* i2c_test r addr
  8. * i2c_test w addr val
  9. */

  10. void print_usage(char *file)
  11. {
  12.         printf("%s r addrn", file);
  13.         printf("%s w addr valn", file);
  14. }

  15. int main(int argc, char **argv)
  16. {
  17.         int fd;
  18.         unsigned char buf[2];
  19.         
  20.         if ((argc != 3) && (argc != 4))
  21.         {
  22.                 print_usage(argv[0]);
  23.                 return -1;
  24.         }

  25.         fd = open("/dev/at24cxx0", O_RDWR);
  26.         if (fd < 0)
  27.         {
  28.                 printf("can't open /dev/at24cxxn");
  29.                 return -1;
  30.         }

  31.         if (strcmp(argv[1], "r") == 0)
  32.         {
  33.                 buf[0] = strtoul(argv[2], NULL, 0);
  34.                 read(fd, buf, 1);
  35.                 printf("data: %c, %d, 0x%2xn", buf[0], buf[0], buf[0]);
  36.         }
  37.         else if (strcmp(argv[1], "w") == 0)
  38.         {
  39.                 buf[0] = strtoul(argv[2], NULL, 0);
  40.                 buf[1] = strtoul(argv[3], NULL, 0);
  41.                 write(fd, buf, 2);
  42.         }
  43.         else
  44.         {
  45.                 print_usage(argv[0]);
  46.                 return -1;
  47.         }
  48.         
  49.         return 0;
  50. }

连续发了好几篇驱动程序,还有大概俩个实验,就准备发项目的了,由于我也是初学者,程序中难免有错误和bug,还请各位i大神多多包涵。

回帖(1)

低调de炫耀爱

2015-8-21 10:46:20
七夕的深夜还在默默的写试用体验 也是蛮拼的啊 加油加油
举报

更多回帖

发帖
×
20
完善资料,
赚取积分