Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2613656
  • 博文数量: 877
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5921
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-05 12:25
个人简介

技术的乐趣在于分享,欢迎多多交流,多多沟通。

文章分类

全部博文(877)

文章存档

2021年(2)

2016年(20)

2015年(471)

2014年(358)

2013年(26)

分类: LINUX

2014-03-28 10:39:25

这两天在板子上加载模块的时候,遇到了各种问题,与我第一次加载模块时碰到的问题大同小异,故记录在博客,仅供查阅。

 

    1.PC机和目标板内核版本不一致

       问题提示:version magic '2.6.32.2 mod_unload modversions ARMv4 ' should be '2.6.32.2-FriendlyARM mod_unload ARMv4 '

 

       准确来说,PC机上的内核所指的是用于编译模块的内核的版本,并不一定就是运行在PC上linux系统上的内核版本。用指令 uname -r 所查询到的版本号,就是后者。之前按照mini2440用户手册的流程,配置好PC机上用于实验的内核,但由于一段时间以来的捣鼓,早已“面目全非”,先将其还原。

       (1)在内核linux-2.6.xxxxxx # 目录上,执行make distclean     //清除,即还原

       (2)在同一目录上执行 cp config_mini2440_t35 .config          //使用现成配置

       (3)执行 make menuconfig   之后退出即可                          //内核保存配置信息之用

       (4)执行 make zImage                                                  //编译内核

       (5)执行 make modules                                                 //编译模块

 

        一般来说经过上述几步即可与板子上的内核同一版本,前提当然是正在使用的内核版本与板载的内核版本相符。

 

     2.测试程序在板上运行的问题

        问题提示:syntaxerror : "(" unexpected

 

        刚开始以为是ftp传送方式,导致文件传送不完整所引起的问题,后来再三验证其他程序,并无异常,所以排除这个可能。瞎弄了一阵,突然发现是makefile的问题,我竟然把它用gcc而不是arm-linux-gcc编译了!顿时晕了一阵!以下附上arm-linux-gcc编译方式的简单makefile文件

 

       

[c-sharp] view plaincopy
  1. CROSS=arm-linux-  
  2.   
  3. all : jarvis_led                                  #生成执行文件的名字,可改  
  4. jarvis_led : jarvis_led.c                         #这里给出源代码文件  
  5.         $(CROSS)gcc -o jarvis_led jarvis_led.c    #此处注意缩进是一个tab  
  6.   
  7. clean :  
  8.         @rm -vf led *.o *~  


    3.编译驱动模块方法

       这里我们讨论的是字符驱动,所以先把驱动程序复制到内核目录下 /drivers/char 里。接着就是对 /drivers/char 里的Kconfig和Makefile进行改写的操作了。

 

       (1)Kconfig

        我们在make menuconfig 界面上所看到的信息就是在Kconfig文件中定义的,所以我们需要编译自己的驱动的话,总得先把自己的驱动放进界面,之后才能进行选择是编译模块(M)还是直接编译进内核(*)吧。添加代码如下

 

config LED_MODULE                           //与Makefile产生联系

        tristate "jarvis_led_module"        //在menuconfig 界面上我们就看到这个名字啦

        depends on ARCH_S3C2410

        default m if MACH_FRIENDLY_ARM_MINI2440

 

        要想看到上面的信息,我们需要进入menuconfig-->Device Drivers-->character devices,就能看到自己模块的信息啦。

 

        (2)Makefile

         返回到 /drivers/char 目录下,修改Makefile,实质只需添加一条语句即可,如下:

obj-$(CONFIG_LED_MODULE)   += jarvis_led.o     //红色字体必须与Kconfig对应

 

          至此,准备工作已做完,我们需要在内核目录下,即linux-2.6.xx.xx #上执行 make modules。之后再返回 /drivers/char 应该就会看到我们所编译的驱动模块有一个.ko文件产生,that`s it!

 

     

 

       最后,如何把模块送到板子上,加载、卸载、测试等工作,mini2440用户手册讲解得十分清晰,遂不在此赘述。本人知识浅薄,还望大家多多指点!
http://blog.csdn.net/jarvis_xian/article/details/6428358

嵌入式Linux驱动程序之编程常见错误

1、warning: function declaration isn't a prototype

这种错误也是很常见的,主要是对一些函数固定格式的错误使用。比如int function()改称int function(void)

static int xxxx_init(void)记住不要缺少static,而static void xxxx_exit(void)

2、出现 warning: assignment makes pointer from integer without a cast 的原因

第一可能是类型转换的问题。函数的返回值类型等等

第二、在源文件中没有发现函数的声明,可能是忘加头文件了。(未经声明的函数原型一律默认为返回int值)

3、makefile:4: *** missing separator. Stop.

最近常用SourceInsight3.5编辑程序,里面直接编辑保存的是word格式。用WinHex或UltraEdit以二进制方式打开,里面的

Tab字符对应0x09而不应该是几个0x20。这是主要用vi打开文件,切入到底行模式,使用":set ff =unix"

4、模块与内核不匹配问题

安装模块时出现:[root@FriendlyARM nfs]# insmod key2.ko

key2: version magic '2.6.32.2 mod_unload modversions ARMv4 ' should be '2.6.32.2-FriendlyARM mod_unload ARMv4 '

这一行的意思就是说,当前插入的模块xxx.ko的版本信息(version magic)与正运行的kernel的版本信息不一致!应该是'2.6.32.2-      FriendlyARM mod_unload ARMv4 ',而实际上xxx.ko的版本信息却是:'2.6.32.2 mod_unload modversions ARMv4 '; 显然

它们之间差别是很小的。实际上,根据上面安装的kernel源码来看,它们应该是没有什么差别的。

我觉得解决这个问题最主要的手段是务必务必保证内核模块的Makefile文件中的

KDIR := /home/yuesichiu/Linux/FriendlyARM/linux-2.6.32.2与编译内核FriendlyARM/linux-2.6.32.2,下载到开发板的 zImage是同  一内核。

5、多文件编程结构体的存放位置

我比较喜欢的是把结构体和函数声明放置头文件中,把头文件加到各个.c文件中,以前把结构体定义放置main.c中,编译时老是出错。

linuxLinux/2012-12/76201.htm

目标平台:TQ2440  ARM9 

内核版本:Linux-2.6.25

前提:宿主机上已安装交叉编译工具,因为这个在linux内核移植的时候就使用过了,这里就不说了。

进入正题

1、首先进入一个目录,在其中创建一个文件夹

#cd /home/wanyao/module

#vim hello.c

   1. #include  2. #include  3. MODULE_LICENSE("Dual BSD/GPL"); 4. 5. static int hello_init(void) 6. { 7.    printk(KERN_ALERT "Hello, world\n"); 8. return 0; 9. } 10. 11. static void hello_exit(void) 12. { 13.    printk(KERN_ALERT "Goodbye, cruel world\n"); 14. return 0; 15. } 16. 17. module_init(hello_init); 18. module_exit(hello_exit);  
复制代码

2、创建Makefile文件

#vim Makefile

复制代码
   1. KERNELDIR=/opt/EmbedSky/linux-2.6.25 2. PWD:=$(shell pwd) 3. INSTALLDIR=$(PWD) 4. CC=arm-linux-gcc 5. obj-m := hello.o 6. modules: 7.     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 8. clean: 9.     rm -rf *.o *.ko *.mod.c *.markers *.order *.symvers 10. .PHONY:modules clean    
复制代码

注意:驱动模块不一定要放在内核树里,只要你的Makefile指定了内核树的路径就没问题,所以我这里在/home/wanyao/里建立了一个module目录专门用来开发驱动模块

3、然后进行make

#make

结果生成好多文件,其中hello.ko就是我们需要的用来加载的模块文件。

4、利用tftp将hello.ko这个模块文件上传到开发板上(这个步骤在我另一篇博客中有详细介绍)

5、加载模块,进行测试(一下操作是在开发板中的系统终端执行的)

# insmod hello.ko
Hello, world
# rmmod hello

Goodbye, cruel world

大功告成!

 

insmod时可能出现的错误:


1、hello: version magic '2.6.30.4 mod_unload ARMv4 ' should be'2.6.30.4-EmbedSky mod_unload ARMv4 '
insmod: cannot insert 'hello.ko': invalid module format

出错原因:模块版本与内核版本不匹配!
解决办法:导入预设配置信息,进入menuconfig 继续配置General config ->( )Local version -> 括号中加入如下内容:“-EmbedSky”退出保存为 .config ,重新编译内核、驱动模块,再来加载模块


2、hello: Unknown symbol__aeabi_unwind_cpp_pr0
insmod: cannot insert 'hello.ko': unknown symbol in module, or unknown
parameter

出错原因:模块和内核镜像不匹配

解决方法:尽量用和你同时用来编译驱动而生成的内核镜像zImage,zImage烧到板子上。Ldd3上有句话:尽管并不是必需的,但最好运行和模块对应的内核。

刚开始学驱动,终于成功加载了hello world 模块!
这是学习驱动的一小步,但是对我来说却是一大步!


http://www.cnblogs.com/wanyao/archive/2011/11/21/2257628.html

阅读(1154) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~