第一个驱动程序 ——s3c2440 linux2.6.30.4

看着韦东山的视频学arm,跟着他写了一下代码,由于跟视频中所用的视频不一样,所以会出现一下错误,在这里把它记录下来。


先贴上代码:

#include <linux/module.h>//对用模块的使用
#include <linux/kernel.h>//内核头文件,含有一些内核常用文件的原型定义
#include <linux/fs.h>//文件系统头文件,定义文件表结构
#include <linux/init.h>// _init _exit等
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include<linux/device.h>   //由于要自动创建结点,所以需要这个头文件
static struct class *firstdrv_class;   //创建一个类
static struct device   *firstdrv_class_dev; //创建一个设备


static int first_drv_open(struct inode *inode, struct file *file)
{
printk("first_drv_open\n");
return 0;
}




static ssize_t first_drv_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos)//__user前面是两横的
{
printk("first_drv_write\n");
return 0;
}
static struct file_operations first_drv_fops=   //用来告诉内核的方法
{
.owner=THIS_MODULE,
.open=first_drv_open,
.write=first_drv_write,
};
int major;
int first_drv_init(void)   //注册驱动
{

major=register_chrdev(0,"first_drv",&first_drv_fops);
firstdrv_class = class_create(THIS_MODULE,"firstdrv");
firstdrv_class_dev=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"xyz");
return 0;
}


void first_drv_exit(void)  //卸载驱动
{
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);


}


module_init(first_drv_init); //驱动入口
module_exit(first_drv_exit);//驱动出口
MODULE_LICENSE("GPL");


接下来来剖析一下整个流程:

一:首先是头文件的问题,因为版本的不同,所以头文件会不一样,在写之前我先百度了一下linux2.6.30.4内核的头文件(我用的内核),一些没有的我在通过内核的源文件去查找。例如,device_create和class_create相关的头文件,我就是通过源代码找到的。






推荐用sourcesight看源代码,查找的时候会很方便。

二:函数的不同:

还是device_create这些函数,以前的版本会是class_devece_create这些等等。出现这些问题的时候,也只能百度一下,然后看看源代码了。我一直相信我遇到的问题应该别人也有遇到过,百度也就会有。


三:程序的流程:

整个程序很简单。就只是通过open和write两个函数来输出一串字符:

首先,先编写open和write函数,也就是我们想实现的功能都在这里实现。写完之后,问题就来了,我们怎么让内核知道,我们所写的驱动就是用这两个函数呢?

这就涉及到了告诉内核,让内核知道的问题了。

怎么让内核知道:

一、通过一个注册一个file_operations结构,把我们写的程序填充进去。
static struct file_operations first_drv_fops=   //用来告诉内核的方法
{
.owner=THIS_MODULE,
.open=first_drv_open,
.write=first_drv_write,
};

二、在内核中注册这个驱动,也就是告诉内核:

int major;
int first_drv_init(void)   //注册驱动
{

major=register_chrdev(0,"first_drv",&first_drv_fops);
firstdrv_class = class_create(THIS_MODULE,"firstdrv");
firstdrv_class_dev=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"xyz");
return 0;
}

这个程序中,用到了自动创建设备结点的功能,如果不是自动创建结点的话,还需要手动创建,手动创建的方法就是:

1、加载驱动后, 通过  cat  /proc/devices 来查看这个驱动的主设备好,次设备号,还有属性

2、mknod  名字  属性 主设备号  次设备号  来创建结点


但是这个方法比较码放,所以就又有了主动创建结点的功能:

1:先创建出两个结构体,当然,这个根据版本的不同也不一样,具体看源代码

static struct class *firstdrv_class;    //创建一个类
static struct device   *firstdrv_class_dev;  //创建一个设备

2:创建出这个类,还有在这个类下面的设备

major=register_chrdev(0,"first_drv",&first_drv_fops);

firstdrv_class = class_create(THIS_MODULE,"firstdrv");
firstdrv_class_dev=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"xyz");

卸载的时候:

unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);

3、原理:mdev

所谓的mdev就是在注册和卸载驱动的时候,都会在/sys这个目录下生成相应的信息,mdev机制就可以通过这个信息来生成一个类,然后再生成设备结点。

通过上面的语句,注册成功后,系统就会根据相应的信息在创建出这个设备结点。可以在 /sys/class找到first_drv这个类,在这个类的下面就是“xyz”。

生成的这个设备结点,是在/dev/xyz中的。不用混乱了,上面的只是设备的信息而已,真正的设备结点在/dev这个目录下

三、怎么让系统知道就是这个注册函数;

系统就是通过下面的这两条语句来分辨不同驱动的注册函数的:

module_init(first_drv_init); //驱动入口
module_exit(first_drv_exit);//驱动出口

整个驱动的编写流程结束了。

接下来说一下测试程序:

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>


int main(int argc,char **argv)
{
int fd;
int val=1;
fd=open("/dev/xyz",O_RDWR);
if(fd<0)
printf("can't open!\n");;
write(fd,&val,4);
return 0;
}

/dev/xyz 就是我们之前创建的设备结点。别看到名字就以为系统是通过名字来识别他响应的驱动程序的。其实不是的,名字是可以一样的,唯一不一样的只有设备号。

所以是通过设备号还有属性来找到相应的设备的。例如如果/dev/xyz的设备号是252,属性是字符,那么他相应的设备号和属性也是一样的。这样就将系统程序与驱动给对应起来了,以为是很简单的函数,就不加以解释了。

哇咔咔,搞定,我的第一个arm驱动程序。














  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值