九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 6602|回复: 4
打印 上一主题 下一主题

x4412&ibox项目实战14-linux驱动的编写步骤

[复制链接]
跳转到指定楼层
楼主
发表于 2014-9-26 14:51:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
从零开始编写linux驱动时,无论采用linux的何种架构,基本上都可以归纳为以下驱动八要素。
1.1.1    建立Linux驱动框架
Linux内核在使用驱动时首先要装载驱动,在装载过程中进行一些初始化动作,如建立设备文件、分配内存等。在驱动程序中需提供相应函数来处理驱动初始化工作,该函数须使用module_init宏指定。Linux系统在退出时需卸载Linux驱动,在卸载过程中进行一些退出动作,如删除设备文件、释放内存等。在驱动程序中需提供相应函数来处理退出工作,该函数须使用module_exit宏指定。Linux驱动程序一般都要这两个宏指定这两个函数,所以包含这两个宏以及其所指定的两个函数的C程序可看作是Linux驱动的框架。
蜂鸣器驱动对应的框架程序如下:
  1. static struct platform_driver x4412_beep_driver = {
  2.          .probe                  = x4412_beep_probe,
  3.          .remove               = x4412_beep_remove,
  4.          .suspend     = x4412_beep_suspend,
  5.          .resume                = x4412_beep_resume,
  6.          .driver                  = {
  7.                    .name         = "x4412-beep",
  8.          },
  9. };

  10. static struct platform_device x4412_beep_device = {
  11.          .name      = "x4412-beep",
  12.          .id        = -1,
  13. };

  14. static int __devinit x4412_beep_init(void)
  15. {
  16.          int ret;

  17.          printk("x4412 beep driver\r\n");

  18.          ret = platform_device_register(&x4412_beep_device);
  19.          if(ret)
  20.                   printk("failed to register x4412 beep device\n");

  21.          ret = platform_driver_register(&x4412_beep_driver);
  22.          if(ret)
  23.                    printk("failed to register x4412 beep driver\n");

  24.          return ret;
  25. }

  26. static void x4412_beep_exit(void)
  27. {
  28.          platform_driver_unregister(&x4412_beep_driver);
  29. }

  30. module_init(x4412_beep_init);
  31. module_exit(x4412_beep_exit);
复制代码
1.1.2    注册和注销设备文件
任何Linux驱动都需要有一个设备文件来与应用程序进行交互。建立设备文件的工作一般在上一步module_init宏指定的函数中完成的,可以使用misc_register函数创建设备文件。删除设备文件的工作一般在上一步module_exit宏指定的函数中完成的,可以使用misc_deregister函数删除设备文件。
蜂鸣器驱动对应注册和注销设备文件的程序如下:
  1. static int x4412_beep_probe(struct platform_device *pdev)
  2. {
  3.          __x4412_beep_probe();

  4.          return sysfs_create_group(&pdev->dev.kobj, &x4412_beep_attr_group);
  5. }

  6. static int x4412_beep_remove(struct platform_device *pdev)
  7. {
  8.          __x4412_beep_remove();

  9.          sysfs_remove_group(&pdev->dev.kobj, &x4412_beep_attr_group);
  10.          return 0;
  11. }
复制代码
1.1.3    指定驱动相关信息
驱动程序是自描述的,驱动程序的信息需要在驱动源代码中指定。通过MODULE_AUTHOR(作者姓名)、MODULE_LICENSE(使用的开源协议)、MODULE_ALIAS(别名)、MODULE_DESCRIPTION(驱动描述)等宏来指定与驱动相关的信息,这些宏一般写在驱动源码文件的结尾。可通过modinfo命令获取这些信息。
例如蜂鸣器驱动中指定的驱动信息如下:
  1. MODULE_LICENSE("GPL");
  2. MODULE_AUTHOR("www.9tripod.com");
  3. MODULE_DESCRIPTION("x4412 beep driver");
复制代码
使用modinfo命令查询该驱动的信息:
  1. [root@x4412 ~]# modinfo x4412-beep.ko
  2. filename:       x4412-beep.ko
  3. license:        GPL
  4. author:         www.9tripod.com
  5. description:    x4412 beep driver
  6. depends:      
  7. vermagic:       3.0.15-9tripod SMP preempt mod_unload ARMv7 p2v8
  8. [root@x4412 ~]#
复制代码
1.1.4    指定回调函数
Linux驱动包含了很多动作,也称为事件,如读写事件等。触发相应事件时Linux系统会自动调用对于驱动程序的相应回调函数。一个驱动程序不一定要指定所有的回调函数。回调函数通过相关机制进行注册。如与设备文件相关的回调函数使用misc_register函数注册。
1.1.5    编写业务逻辑
业务逻辑,即是我们驱动需要实现的具体功能了。例如蜂鸣器驱动中对应的业务逻辑函数如下:
  1. static ssize_t x4412_beep_read(struct device *dev, struct device_attribute *attr, char *buf)
  2. {
  3.          if(!strcmp(attr->attr.name, "state"))
  4.          {
  5.                    if(__x4412_beep_status != 0)
  6.                             return strlcpy(buf, "1\n", 3);
  7.                    else
  8.                             return strlcpy(buf, "0\n", 3);
  9.          }
  10.          return strlcpy(buf, "\n", 3);
  11. }

  12. static ssize_t x4412_beep_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  13. {
  14.          unsigned long on = simple_strtoul(buf, NULL, 10);

  15.          if(!strcmp(attr->attr.name, "state"))
  16.          {
  17.                    if(on)
  18.                    {
  19.                             gpio_set_value(EXYNOS4_GPD0(1), 1);
  20.                             __x4412_beep_status = 1;
  21.                    }
  22.                    else
  23.                    {
  24.                             gpio_set_value(EXYNOS4_GPD0(1), 0);
  25.                             __x4412_beep_status = 0;
  26.                    }
  27.          }

  28.          return count;
  29. }
复制代码
       这里对应一个读写函数,当我们执行如下指令时,会调用x4412_beep_read函数读取当前蜂鸣器的状态:
  1. cat  /sys/devices/platform/x4412-beep/state
复制代码
       执行如下指令时,会调用x4412_beep_write函数打开蜂鸣器:
  1. echo 1 > /sys/devices/platform/x4412-beep/state
复制代码
执行如下指令时,会调用x4412_beep_write函数关闭蜂鸣器:
  1. echo 0 > /sys/devices/platform/x4412-beep/state
复制代码
1.1.6    编写MakefileKconfig文件
Linux内核源码的编译规则是通过Makefile文件定义的,每个Linux驱动程序必须要有一个Makefile文件。蜂鸣器驱动对应的Makefile文件如下:
  1. obj-$(CONFIG_X4412_BEEP_DRIVER) += x4412-beep.o
复制代码
       对应的Kconfig文件如下:
  1. config X4412_BEEP_DRIVER
  2.          tristate "X4412 beep driver"
  3.          default y
  4.          help
  5.          compile for x4412 beep driver,y for kernel,m for module.
复制代码
1.1.7    编译Linux驱动程序
如前文所说,Linux驱动程序可直接编译进内核,也可以作为模块单独编译。编译完成后,将会在驱动目录生成目标文件,对应蜂鸣器驱动的目标文件为:
编译进内核:x4412-beep.o
编译成模块:x4412-beep.ko
1.1.8    安装和卸载Linux驱动
如果将驱动编译进内核,驱动程序就会自动装载。如果Linux驱动程序以模块形式单独存在,需要使用insmod或modprobe命令装载Linux驱动模块,使用rmmod命令卸载该模块。

回复

使用道具 举报

沙发
发表于 2014-12-12 11:30:19 | 只看该作者
非常感谢您的分享~~~~~~~~
回复 支持 反对

使用道具 举报

板凳
发表于 2015-8-19 21:24:46 | 只看该作者
这些Linux驱动能搞的像裸机驱动一样打个包么?
回复 支持 反对

使用道具 举报

地板
发表于 2015-9-12 21:40:03 | 只看该作者
要是在资料中也有着写内容就更好了
回复 支持 反对

使用道具 举报

5#
发表于 2015-9-16 15:18:42 | 只看该作者
非常棒,我喜欢~~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2024-5-3 06:19 , Processed in 0.019102 second(s), 16 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表