今天开始,我会逐步开始介绍字符驱动的编写,从编译开始,慢慢的直至后面的LED流水灯,DS18B20的驱动开发过程.这里讲述的一些驱动的信号量,轮训等都适用与其他驱动.后面会一一讲述.
本人也是菜鸟.写的不好的,希望能指出问题.谢谢大家.本系列主要讲的是关于字符驱动的开发方法及一些流程.由于我在学习字符驱动的时候走的很大的弯.希望在这留下一些脚印给喜欢驱动的朋友们一些参考.
今天这一节很轻松,主要就是讲下怎么编译驱动代码.并以经典的hello world例子作为驱动的入门.下面我们一起来看一下吧.
在编译驱动之前,首先介绍下我使用的环境:
主机系统: Ubuntu 11.04
开发板: ARM11 + Linux-2.6.36
注:在编译驱动之前,请确保你有源代码,并编译通过.
下面是我的一个错误:
注:出现以上错误时,请重新编译您的源码.
好了.有了上面的准备,那么我们可以正式进入驱动的大门了.
下面来看一下经典的hello world的源码:
#include <linux/init.h> #include <linux/module.h> //模块加载函数 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); //指定模块卸载函数 MODULE_AUTHOR("LvApp"); //作者 MODULE_LICENSE("Dual BSD/GPL"); //许可证 MODULE_DESCRIPTION("A simple hello world module"); //描述 MODULE_ALIAS("a simplest module"); //别名
以上便是hello world的代码了.可以看出.驱动代码跟我们平时写的hello world有点不一样了吧.而已在驱动中的输出函数也不是printf了.而是变成了printk.这个函数会把输出的内容根据日志级别,输出至控制台或者终端,具体可以参看(在include/linux/kernel.h中):
#define KERN_EMERG 0 /*紧急事件消息,系统崩溃之前提示,表示系统不可用*/ #define KERN_ALERT 1 /*报告消息,表示必须立即采取措施*/ #define KERN_CRIT 2 /*临界条件,通常涉及严重的硬件或软件操作失败*/ #define KERN_ERR 3 /*错误条件,驱动程序常用KERN_ERR来报告硬件的错误*/ #define KERN_WARNING 4 /*警告条件,对可能出现问题的情况进行警告*/ #define KERN_NOTICE 5 /*正常但又重要的条件,用于提醒*/ #define KERN_INFO 6 /*提示信息,如驱动程序启动时,打印硬件信息*/ #define KERN_DEBUG 7 /*调试级别的消息*/
如果没有选择级别,那么这个函数使用默认级别DEFAULT_ MESSAGE_LOGLEVEL(这个默认级别一般为<4>,即与KERN_WARNING在一个级别上),其定义在linux26/kernel/printk.c中可以找到.
其实printk始终是能输出消息的.只不过不一定在终端上.我们可以去/var/log/kern.log文件里面去看.
或者使用dmesg | tail -3查看到输出.
现在知道了printk的用法.下面就开始编译我们的代码吧.
最简单的Makefile编译方法如下:
Makefile文件内容如下
obj-m += hello.o
编译指令如下:
make -C /LvApp/linux-2.6.36.2-v1.05/ M=$(pwd) modules
编译成功之后会产生.ko文件.就是驱动文件了
编译完之后,在我们当前目录下会生成hello.ko这样一个驱动文件.通过下面的方法,就可以加载hello.ko这个驱动了.在我们的串口终端输出我们printk的内容
3: 加载模块 insmod
卸载模块 rmmod
运行结果: