登录站点

用户名

密码

PC_linux以及ARM_linux下驱动开发第一例实践

已有 155 次阅读  2013-04-16 13:17   标签开发 

今天尝试了linux下的驱动开发,花了一个上午的时间终于在PCARM上跑成功了经典驱动教材LINUX设备驱动程序》的第一个例子 hello.c。看似简单的程序折腾了我不少时间。


 


由于我用的redhat9.0,以及arm上以前烧录的是linux2.4.20内核因此只能用《LINUX设备驱动程序》第二板中的源代码,《LINUX设备驱动程序》第三版的源代码是for 2.6的内核的。2.42.6的驱动模型做了改动,因此开发的过程,有点不大一样,有兴趣的人可以自己在网上搜索看看。不过我也会简单比较一下不同点.


 


首先拿到hello.c的源代码:


Ldd2(《LINUX设备驱动程序》的简称)给的如下:


 


/*                                                    


 * $Id: hello.c,v 1.10 2001/07/17 10:30:02 rubini Exp $


 */                                                   


#define MODULE


#include <linux/module.h>


 


/*                                                       


 * These lines, although not shown in the book,          


 * are needed to make hello.c run properly even when     


 * your kernel has version support enabled                


 */                                                      


                                                         


int init_module(void)      { printk("<1>Hello, world\n"); return 0; }


void cleanup_module(void)  { printk("<1>Goodbye cruel world\n"); }


 


你会发现这个程序其实是有问题的:我做了简单修改:


 


/*                                                    


 * $Id: hello.c,v 1.10 2001/07/17 10:30:02 rubini Exp $


 */                                                   


#define MODULE


#include <linux/module.h>


 


/*                                                        


 * These lines, although not shown in the book,          


 * are needed to make hello.c run properly even when     


 * your kernel has version support enabled               


 */                                                       


MODULE_LICENSE("GPL");           //添加这句话,否则在PC上编译的时候会出现


//警告,没有注册


//2.6的注册不同:


//MODULE_LICENSE("Dual BSD/GPL");


#include <linux/kernel.h>               //添加了这个头文件printk函数在里面


int init_module(void)      { printk("<1>Hello, world\n"); return 0; }


void cleanup_module(void)  { printk("<1>Goodbye cruel world\n"); }


 


//2.6内核中这两个函数改成了


/*


static int hello_init(void)


{


  printk(KERN_INFO " Hello World enter\n");


  return 0;


}


 


static void hello_exit(void)


{


  printk(KERN_INFO " Hello World exit\n ");


}


 


module_init(hello_init);


module_exit(hello_exit);


*/


 


程序修改好后就可以编译了:


#gcc –I /usr/src/linux2.4/include/linux –c hello.c


//说明:写内核或内核模块不能用写应用程序时的系统调用或函数库


//      -I 后面是就是编译模块专用的内核库路径


//注意 这里编译驱动模块 只需编译到 *.o格式就可以了


 


编译好后我们执行:


#lsmod   //看看现在有那些驱动在内核中


#insmod hello.o   //加入我们刚刚编译的驱动


                //这里可能会报linux版本不匹配的错误


解决方法:1.无视它  改用#insmod –f hello.o


2. 有人提供这样的建议:


进入/usr/include/linux/目录


version.h第一句


#define UTS_RELEASE 2.4.20-1"


改成


#define UTS_RELEASE "2.4.20",这样就可以了。以你自己为准


这时候我们查看打印信息:printk函数相关内容与优先级这里不赘述,自己查看~


由于我们在xwindow下使用的是虚拟终端,所以终端不回打印,在这里查看:


#cat /var/log/messiges


发现已经有Hello, world输出了


接下来:


#rmmod hello       //卸载驱动,注意不是hello.o


同样在messiges里有good bye输出了


 


 


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//                           分隔线


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


接下来我们交叉编译该文件,方法与上面一样


代码稍微修改一下,需要删除:


 


MODULE_LICENSE("GPL");    //这句话,否则交叉编译不过去,不明,达人指教下!!


 


然后我们编译:


 


/opt/host/armv4l/bin/armv4l-linux-gcc –D__KERNEL__-I /usr/src/linux-2.4/include/linux/ -DMODULE –c hello.c


 


//  /opt/host/armv4l/bin/armv4l-linux-gcc我的交叉编译gcc


//  –D__KERNEL__  -DMODULE 代表编译的是内核模块


//  -I  同上


 


这时生成了hello.o,载到arm板子上,执行


#insmod –f hello.o  //无视版本警告


//会直接输出打印信息 hello world 因为这不是虚拟终端


#rmmod hello  //卸载 打印信息 goodbye

上一篇: stm32应用例程 下一篇: LCD12864 驱动 ,采用串行方式

分享 举报