Linux设备驱动学习-Davinci开发板上 运行的hello-driver模块

来源:互联网 发布:div中调用js函数 编辑:程序博客网 时间:2024/06/06 10:41

基本所有程序的例子都是经典的HELLO WORLD程序。

对于Linux设备驱动也不例外

http://blog.csdn.net/lintax/article/details/4590922

这个博主写的已经相当详细,

/*================hello-driver.c==============*/

#include <linux/module.h>  /*所有模块都需要的头文件*/
#include <linux/kernel.h>
#include <linux/init.h>         /* init和exit相关宏*/


MODULE_LICENSE("Dual BSD/GPL");    #《1》
MODULE_AUTHOR("CCC");

static int hello_init(void)
{
  printk(KERN_ALERT " Hello Davinci!/n");
  return 0;
}

static void hello_exit(void)
{
  printk( KERN_ALERT " Goodbye, Davinci./n ");
}

module_init(hello_init);
module_exit(hello_exit);

/*================hello_davinci.c end===========*/


给其配个Makefile文件:

/*================Makefile==================*/

obj-m := hello_davinci.o
KERNELDIR := /opt/ti-davinci/
modules:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
 rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

/*================Makefile end===============*/

 

好了,编译吧。

我的好心情立马被扑灭了,error,又见error:

我刚开始遇到一个问题就是编译不了

: *** 没有规则可以创建“/home/dvevm_1_20/myexample/hello-driver/hello-davinci.o”需要的目标“/home/dvevm_1_20/myexample/hello-driver/hello-davinci.c”。 停止。

原因是我把文件名命名成hello-driver.c 但是Makefile里面写的是  obj-m := hello_davinci.o

因为Make命令只会查找跟目标文件名相同的.c源文件,如果obj-m后面是hello_davinci.o 当然源文件名就应该是hello_davinci.o

当然如果把Makefile里面的hello_davinci.o 改成hello-driver.o 是一样的道理


楼主说的  找不到/opt/ti-davinci/include/asm/ 下的某个头文件这个错误我没有遇到,因为在编译前我就先把内核编译过一次,

故如果做内核驱动,必须先编译内核一次,以避免此类错误,个人理解。


转移到davinci开发板上,执行插入模块命令:
 insmod hello-driver.ko
输出信息:
 insmod: error inserting 'hello.ko': -1 Invalid module format 

百度谷歌了一圈,发现基本原因就是编译时选择的内核跟实际运行的内核版本不匹配,我用的是TI官方的源码

/opt/mv_pro_5.0/montavista/pro/devkit/lsp/ti-davinci

但是这个代码应该跟开发板提供的源码有所区别,虽然我用uname -r查看是一样的,具体有什么区别就不得而知了。

把Makefile里面源码路径改成开发板提供的源码路径就可以用insmod hello_world.ko命令挂载

通过lsmod查看,也有了hello_world 模块。

然后执行移除模块命令:
 rmmod hello-driver.ko
输出信息:
 Goodbye Davinci.
再用lsmod来查看,就找不到hello_davinci了。

 有时候会出现insmod: error inserting 'hello-driver.ko': -1 File exists

就是你原来加载过,但是没有卸载,又尝试去重新加载,肯定会提示已经存在。

有以下几点要注意:

1,所使用的内核环境必须是编译过的,否刚会出现链接之类的问题

2,对于编译过程中类似于:不能创建hello_davinci.o.tmp文件的错误。说明权限不够,可更改hello_davinci.c Makefile文件所在目录的属性,或者是sudo到根用户。我用的直接是root用户,所以不存在权限问题

3,hello_davinci.c文件中调用的头文件的作用:
 init.h中的module_init(),module_exit()
 kernel.h中的printk(),KERN_ALERT
 module.h中的MODULE_LICENSE()

如果不使用MODULE_LICENSE()这个宏,会出现内核污染如

Warning: loading #.o will taint the kernel: no license

之类的错误,这只是个警告,应该要要告知版权之类的意思。

4,Makefile文件分析 
obj-m := hello_world.o  代表了我们要构造的模块名为hello_world.o,make
会在该目录下自动找到hello_world.c文件进行编译。如果 hello_world.o是由其
他的源文件生成(比如file1.c和file2.c)的,则在下面加上:
 hello_world-objs := file1.o file2.o ......

 

 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
其中 -C $(KERNELDIR) 指定了内核源代码的位置,其中保存有内核的顶层

makefile文件。
 M=$(PWD) 指定了模块源代码的位置。
 modules目标指向obj-m变量中设定的模块。

5,驱动模块运行在内核空间,运行时不能依赖于任何函数库和模块连接,所以在写驱动时所调用的函数只能是作为内核一部分的函数。

编译内核时,MAKEFILE会自动把生成的uImage 转移到 /arch/arm/boot目录

我开发板用的民NFS,所以想在Makefile中自己加上代码,直接把生成的HELLO_WORLD.KO自动复制到开发板的文件系统中,用SHELL判断,如果没有直接复制过去,如果原来有的话先删除再复制,然后就是一系列悲催的错误

make[1]: Leaving directory `/home/dvevm_1_20/myexample/EL6446_kernel'
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [install] 错误 2

一直是语法错误,因为我写MAKEFILE内容基本都是差不多,估计是因为MAKE命令对格式太敏感,有少许不对就会出现格式错误,SHELL命令执行不了,因为内容很简单,参考书上语法分析也不是内容错误,只有不断调整格式,注意个人书写习惯,别的我也没找到很好的办法


上图是没有错误的,可以正确运行。

后面加上 \ 是相当于只启动一个SHELL执行所有命令,注意then else 这些关键词后面没有 ; 

上面就是判断如果有hello-driver.ko 就提示 已经存在,如果没有,就从当关目录复制过去

几个用到的命令 modinfo

root@172.18.219.128:/home/dvevm# modinfo hello-driver.ko
filename:       hello-driver.ko
author:         davinci
license:        Dual BSD/GPL
depends:        
vermagic:       2.6.10_mvl401-davinci_evm preempt ARMv5 gcc-3.4

这个命令会出现模块相应信息,author在模块中MODULE_AUTHOR()宏定义davinci这个信息

很多 insmod: error inserting 'hello.ko': -1 Invalid module format
据说就是vermagic对不上,也就是内核版本不对,根据这个可以看一下