开发环境:
SYSTEM : Ubuntu-12.04
Board : Mini2440-t35
Bootloader : u-boot-1.1.6
Kernel : Linux-2.6.22.6
CROSS_COMPILE: arm-linux-gcc v3.4.5
一、搭建程序框架
点击(此处)折叠或打开
-
#include <linux/kernel.h>
-
#include <linux/module.h>
-
#include <linux/init.h>
-
#include <linux/fs.h>
-
-
#define DEVICE_NAME "hello_drv"
-
-
static struct file_operations hello_drv_fops = {
-
.owner = THIS_MODULE,
-
};
-
static int hello_drv_init(void)
-
{
-
//int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)
-
register_chrdev(111,DEVICE_NAME,&hello_drv_fops); //使用register_chrdev注册字符设备
-
return 0;
-
}
-
-
static int hello_drv_exit(void)
-
{
-
unregister_chrdev(111, DEVICE_NAME);
-
}
-
-
module_init(hello_drv_init);
-
module_exit(hello_drv_exit);
- MODULE_LICENSE("GPL");
点击(此处)折叠或打开
-
KERN_DIR = /home/wangtisheng/work/kernel/linux-2.6.22.6-mini2440
-
all:
-
make -C $(KERN_DIR) M=`pwd` modules
-
clean:
-
make -C $(KERN_DIR) M=`pwd` modules clean
-
rm -rf modules.order
- obj-m += hello_drv.o
执行make即可得到hello_drv.ko模块
将模块拷贝至根文件系统根目录,我的开发板mini2440采用NFS方式挂载根文件系统。
在mini2440执行insmod命令加载驱动模块
# insmod hello_drv.ko
查看模块式否加载
# lsmod
执行如下命令即可看到设备号为111的驱动模块hello_drv
# cat /proc/devices
三、构造file_operations结构体hello_drv_fops中的各函数,本实例只是构造了open、write函数,在file_operations hello_drv_fops添加open、write函数。
点击(此处)折叠或打开
-
static int hello_drv_open(struct inode *inode, struct file *file)
-
{
-
printk("Hello_Drv_Open!\n");
-
return 0;
-
}
-
static ssize_t hello_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
-
{
-
printk("Hello_Drv_Write!\n");
-
return 0;
-
}
-
static struct file_operations hello_drv_fops = {
-
.owner = THIS_MODULE,
-
.open = hello_drv_open,
-
.write = hello_drv_write,
- };
执行make可得到驱动程序模块hello_drv.ko
四、测试驱动程序hello_drv_test.c
点击(此处)折叠或打开
-
#include <fcntl.h>
-
#include <stdio.h>
-
int main()
-
{
-
int fd;
-
int val = 1;
-
fd = open("dev/hello_drv",O_RDWR);
-
if(fd < 0)
-
printf("Can't Open!\n");
-
write(fd,&val,4);
-
return 0;
- }
arm-linux-gcc -o hello_drv_test hello_drv_test.c
五、驱动加载、测试
将模块hello_drv.ko和测试程序hello_drv_test拷贝至根文件系统根目录,我的开发板mini2440采用NFS方式挂载根文件系统。
挂载模块
# insmod hello_drv.ko
# cat /proc/devices
至此即可看到驱动程序已挂载如下:
111 hello_drv
创建该设备节点
# mknod /dev/hello_drv c 111 0
执行测试程序hello_drv_test
./hello_drv_test
结果如下:
Hello_Drv_Open!
Hello_Drv_Write!
六、总结
来自《嵌入式Linux应用开发完全手册》。
编写字符驱动程序的过程大概如下:
1. 编写驱动程序初始化函数。
进行必要的初始化、包括硬件初始化、向内核注册驱动程序等。
2. 构造file_operations结构中要用到的各个成员函数。
一般来说,编写一个Linux设备驱动程序的大致流程如下。
(1) 查看原理图、数据手册,了解设备的操作方法。
(2) 在内核中找到相近的驱动程序,以它为模板进行开发,有时候需要从零开始。
(3) 实现驱动程序的初始化:比如向内核注册这个驱动程序,这样应用程序传入文件名时,内核才能找到相应的驱动程序。
(4) 设计所要实现的操作,比如open、close、read、write等函数。
(5) 实现终端服务(中断并不是每个设备驱动所必须)。
(6) 编译驱动到内核中,或者用insmod命令加载。
(7) 测试驱动程序。