九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 7814|回复: 6

x4412&ibox项目实战12-linux驱动的加载方法

[复制链接]
发表于 2014-9-26 11:52:14 | 显示全部楼层 |阅读模式
在类unix操作系统中,驱动加载方式一般分为:静态加载和动态加载。静态加载就是把驱动程序直接编译到内核里,系统启动后直接被调用。静态加载的缺点是调试起来比较麻烦,每次修改一个地方都要重新编译下载内核,效率较低。动态加载利用了LINUX的module特性,可以在系统启动后用insmod命令把驱动程序(.ko文件)添加上去,在不需要的时候用rmmod命令来卸载。下面我们通过蜂鸣器驱动实例分别对其进行详述。
1.1.1    静态加载
第一步:在kernel/drivers/char目录下新建目录beep,在beep目录下创建Kconfig,Makefile以及x4412-beep.c三个文件。
第二步:编辑Makefile内容如下:
  1. obj-$(CONFIG_X4412_BEEP_DRIVER) += x4412-beep.o
复制代码
编辑Kconfig内容如下:
  1. config X4412_BEEP_DRIVER
  2.          bool "X4412 beep driver"
  3.          default y
  4.          help
  5.          compile for x4412 beep driver,y for kernel,m for module.
复制代码
再编辑x4412-beep.c文件,其部分源码如下:
  1. static int __devinit x4412_beep_init(void)
  2. {
  3.          int ret;

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

  5.          ret = platform_device_register(&x4412_beep_device);
  6.          if(ret)
  7.                    printk("failed to register x4412 beep device\n");

  8.          ret = platform_driver_register(&x4412_beep_driver);
  9.          if(ret)
  10.                    printk("failed to register x4412 beep driver\n");

  11.          return ret;
  12. }

  13. static void x4412_beep_exit(void)
  14. {
  15.          platform_driver_unregister(&x4412_beep_driver);
  16. }

  17. module_init(x4412_beep_init);
  18. module_exit(x4412_beep_exit);

  19. MODULE_LICENSE("GPL");
  20. MODULE_AUTHOR("www.9tripod.com");
  21. MODULE_DESCRIPTION("x4412 beep driver");
复制代码
       第三步:在kernel/drivers/char/Kconfig中添加如下语句:
  1. source "drivers/char/beep/Kconfig"
复制代码
       第四步:在kernel/drivers/char/Makefile中添加如下语句:
  1. obj-y                             += beep/
复制代码
       第五步:配置menuconfig,编译内核。menuconfig配置界面如下:
1.png
       编译完内核后,在kernel/drivers/char/beep目录下将会生成目标文件x4412-beep.o,它会被打包到内核映像zImage中。
1.1.1    动态加载
在前面的静态加载实验中,我们在menuconfig中尝试配置X4412 beep driver,发现只能选中或不选中,这是由beep目录下面的Kconfig文件决定的。我们发现,X4412 beep driver被声明的参数为bool。我们只需要将bool改为tristate,就可以配置成模块了。bool表示布尔类型,只允许选中或不选中;tristate为三态类型,允许选中,不选中以及编译成模块。修改后的配置界面如下:
2.png
    保存配置之后再编译内核,这时我们发现,在kernel/drivers/char/beep目录下将会生成模块文件x4412-beep.ko。
    将新生成的内核映像zImage烧写到开发板,进入/sys/devices/platform目录,我们发现已经没有x4412-beep目录了,有图为证:
3.png
    linux设备驱动的动态加载可以使用insmod或modprobe两种方式,insmod一次只能加载一个特定的驱动,且需要驱动的绝对路径,而modprobe则可以一次性将有依赖关系的驱动全部加载到内核,不需要驱动的具体地址。但需要将驱动拷贝到/lib/modules/$(uname -r)/目录下,下面我们以前面的蜂鸣器驱动为例,分别介绍两种加载方法。
1.     使用insmod加载驱动
    将前面生成的x4412-beep.ko文件拷贝到SD卡或U盘,并mount到/mnt目录:
  1. [root@x4412 ~]# mount /dev/mmcblk1p1 /mnt/
  2. [root@x4412 ~]# ls /mnt/
  3. Alarms/                   Notifications/            camera.smdk4x12.so*
  4. DCIM/                     Pictures/                 camera.smdk4x12.so.rp*
  5. Download/                 Podcasts/                 sdfuse/
  6. LOST.DIR/                 Ringtones/                x4412-android/
  7. Movies/                   SimpleDoubleWebCams2.apk* x4412-beep.ko*
  8. Music/                    UvcWebCam.apk*            x4412-qt/
  9. NIKON001.DSC*             and-TPnp-vstarcam.apk*    x4412_ibox_led*
  10. [root@x4412 ~]#
复制代码
    这时我们在任意目录下即可执行如下指令加载驱动了:
  1. [root@x4412 ~]# insmod /mnt/x4412-beep.ko
  2. [  115.612694] x4412 beep driver
  3. [root@x4412 ~]#
复制代码
    我们可以看到打印信息“x4412 beep driver”,它就是蜂鸣器驱动的module_init加载的函数执行的打印信息,表明驱动已经正常运行。
    可以使用lsmod命令查看已经加载的KO文件:
  1. [root@x4412 ~]# lsmod
  2. Module                  Size  Used by    Not tainted
  3. x4412_beep              2099  0
  4. [root@x4412 ~]#
复制代码
    我们可以进一步验证驱动是否加载,可以看到/sys/devices/platform目录下是否有x4412-beep目录生成:
  1. [root@x4412 ~]# ls /sys/devices/platform/x4412-*
  2. /sys/devices/platform/x4412-Oops:
  3. Oops       driver@    modalias   power/     subsystem@ uevent

  4. /sys/devices/platform/x4412-beep:
  5. driver@    modalias   power/     state      subsystem@ uevent
  6. [root@x4412 ~]#
复制代码
    可以执行指令测试蜂鸣器是否鸣叫:
  1. [root@x4412 ~]# echo 1 > /sys/devices/platform/x4412-beep/state
复制代码
    如果还不信,使用如下指令卸载驱动后,然后再执行上面的测试指令查看结果。
  1. [root@x4412 ~]# rmmod /mnt/x4412-beep.ko
  2. [root@x4412 ~]#
  3. [root@x4412 ~]# lsmod
  4. Module                  Size  Used by    Not tainted
  5. [root@x4412 ~]#
复制代码
2.     使用modprobe加载驱动
前面我们提到,modprobe并不需要指定到具体的KO文件目录,我们不仿测试下:
  1. [root@x4412 /]# modprobe x4412-beep.ko
  2. modprobe: can't change directory to '/lib/modules': No such file or directory
  3. [root@x4412 /]#
复制代码
这里提示找不到/lib/modules目录,和前面介绍的一样,它需要在指定目录下加载KO,那我们不仿新建该目录,再执行上面的指令测试:
  1. [root@x4412 /]# mkdir /lib/modules
  2. [root@x4412 /]# modprobe x4412-beep.ko
  3. modprobe: can't change directory to '3.0.15-9tripod': No such file or directory
  4. [root@x4412 /]#
复制代码
这里提示找不到3.0.15-9tripod目录,它对应linux内核的名称,可以使用uname–r指令查询。我们继续新建目录,继续测试:
  1. [root@x4412 /]# uname -r
  2. 3.0.15-9tripod
  3. [root@x4412 /]# mkdir /lib/modules/3.0.15-9tripod
  4. [root@x4412 /]# modprobe x4412-beep.ko
  5. modprobe: can't open 'modules.dep': No such file or directory
  6. [root@x4412 /]#
复制代码
这时,提示找不到modules.dep文件。我们不需要手动创建该文件,使用depmod指令即可自动生成。很有可能默认情况下根文件系统不支持该指令,执行时会提示如下信息:
  1. [root@x4412 modules]# depmod
  2. -sh: depmod: command not found
  3. [root@x4412 modules]#
复制代码
我们可以通过配置busybox来添加这个功能。但是我们制作的根文件系统,是用buildroot自动完成的,busybox也随之自动生成,我们还能随心所欲的添加其他功能吗?答案是肯定的。
进入buildroot的menuconfig菜单,进入Target packages选项,发现第一栏有关于busybox的配置选项,如下图所示:
4.png
       可见,我们只需要配置完busybox后,保存到这里就可以了。有两种方法可以实现,第一种就是在busybox的编译目录配置完成后,用busybox当前目录的配置文件.config替换掉package/busybox/busybox.config文件。第二种就是配置完busybox后,直接在buildroot的配置选项中导入这个配置文件。
       busybox的编译目录在output/build/busybox-1.22.1下,这里output是编译之后才会释放的文件,手工配置busybox后,配置文件也会保存在这个目录下,因此不推荐用第二种方法,它不便于源码维护。下面介绍第一种方法。
       进入output/build/busybox-1.22.1目录,执行make menuconfig,进入Linux Module Utilities菜单,如下图所示:
5.png
       选中insmod,rmmod,lsmod,modprobe,depmod,保存退出,然后将当前目录下的.config文件覆盖掉package\busybox\busybox.config文件,之后在buildroot根目录下执行make指令重新编译,busybox将会自动更新,并最终打包到映像文件rootfs.ext4中。
       将开发板更新最新的文件系统后,我们就可以使用depmod指令了。在没有执行该指令时,在/lib/modules/ 3.0.15-9tripod下是没有任何文件的,执行depmod命令后,该目录下将会生成三个文件:
  1. [root@x4412 /]# ls /lib/modules/3.0.15-9tripod/
  2. [root@x4412 /]# depmod
  3. [root@x4412 /]# ls /lib/modules/3.0.15-9tripod/
  4. modules.alias    modules.dep      modules.symbols
  5. [root@x4412 /]#
复制代码
    我们再尝试执行modprobe指令加载驱动:
  1. [root@x4412 /]# modprobe x4412-beep.ko
  2. modprobe: module x4412-beep.ko not found in modules.dep
  3. [root@x4412 /]#
复制代码
    这里提示在modules.dep文件中没有发现我们加载的ko文件,我们尝试查看一下modules.dep的内容:
  1. [root@x4412 /]# cd /lib/modules/3.0.15-9tripod/
  2. [root@x4412 3.0.15-9tripod]# more modules.dep
  3. [root@x4412 3.0.15-9tripod]#
复制代码
    可见,里面的内容为空。实际上,depmod指令会自动分析/lib/modules/$(uname -r)目录下的可加载模块,并按照固定的格式填入modules.dep中。因此,我们可以先将需要加载的ko文件拷贝到对应的目录,再执行depmod指令。
  1. [root@x4412 3.0.15-9tripod]# pwd                  
  2. /lib/modules/3.0.15-9tripod
  3. [root@x4412 3.0.15-9tripod]# cp /mnt/x4412-beep.ko .
  4. [root@x4412 3.0.15-9tripod]# depmod
  5. [root@x4412 3.0.15-9tripod]# more modules.dep
  6. x4412-beep.ko:
  7. [root@x4412 3.0.15-9tripod]#
复制代码
    可以看到,在modules.dep中已经存在有我们需要加载的ko文件名了。注意,不要手工的去编辑modules.dep文件!再执行modprobe指令,即可加载模块了。
  1. [root@x4412 3.0.15-9tripod]# modprobe x4412-beep.ko
  2. [ 2029.489772] x4412 beep driver
  3. [root@x4412 3.0.15-9tripod]#
复制代码
回复

使用道具 举报

发表于 2014-10-11 10:49:03 | 显示全部楼层
太有用了,非常好
回复 支持 反对

使用道具 举报

发表于 2014-10-12 16:07:26 | 显示全部楼层
又学习了一种方法。支持下
回复 支持 反对

使用道具 举报

发表于 2014-12-12 12:26:25 | 显示全部楼层
非常感谢您的分享~~~~~~~~
回复 支持 反对

使用道具 举报

发表于 2014-12-14 13:05:32 | 显示全部楼层
怎么看不到版主发的信息
回复 支持 反对

使用道具 举报

发表于 2015-9-16 15:07:55 | 显示全部楼层
echo 1 > /sys/devices/platform/x4412-beep/state 这句有点不明白。写得真好~~
回复 支持 反对

使用道具 举报

发表于 2016-4-17 17:28:49 | 显示全部楼层
资料挺不错的,但是为什么不整合到pdf教程里去呢?之前一直以为九鼎的板子是没有技术支持的。。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-3-29 19:30 , Processed in 0.025360 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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