LINUX2.6设备注册和GPIO子系统,linux2.6申请设备号,linux2.6注册相关API

一、linux2.6开发

1.1 linux2.6和杂项的区别

杂项:

        驱动程序注册的一种方式,主设备号不用申请固定是10,次设备号0-255,固定填255 自动分配次设备号。杂项注册完成之后他会自动的在/dev/目录下生成一个设备文件,一台设备最多只能挂载256个杂项设备。

linux2.6:

        在linux2.6设备注册完成之后不会自动的生成设备文件,可以手工生成设备文件

        mknod /dev/myled c 5 3

        也可以借助于自动生成设备文件相关函数,主设备号和次设备号是没有限制,主设备号总共可用的有  2^12个,次设备号总共可用的有  2^20个。由于主设备和次设备号都是没有限制的,就有可能跟现有的设备号冲突,为了避免这种情况发生最好不要自己指定主次设备号,要去找系统分配。

1.2 linux2.6申请设备号

函数的功能:

        向内核申请一个可用的设备号

函数的头文件:

        linux/fs.h

函数的原型:

        int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)

函数的参数:

        dev_t *dev,        存放设备号的指针

        unsigned baseminor, 次设备号的起始值  一般填0

        unsigned count,     要申请的设备号的个数

        const char *name    名字    设备号的名字

函数的返回值:

        成功返回   0

        失败返回  非零

MINOR(dev)  获取次设备号

MAJOR(dev)  获取主设备号

        +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:

        释放设备号

函数的原型:

        void unregister_chrdev_region(dev_t from, unsigned count)

函数的参数:

        dev_t from,  设备号的起始位置

        unsigned count 要释放的设备号的个数

函数的返回值:   

        无

1.3 linux2.6注册相关API

关键字  cdev

头文件:

        linux/cdev.h

函数:

        cdev_init  初始化

        cdev_add  注册

        cdev_del  删除

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:

        初始化linux2.6的核心结构体

函数的原型:

        void cdev_init(struct cdev *cdev, const struct file_operations *fops)

函数的参数:

        struct cdev *cdev,                            linux2.6核心结构体

        const struct file_operations *fops    操作集合结构体

函数的返回值:

        无

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:

        向内核注册一个linux2.6的内核

函数的原型:

        int cdev_add(struct cdev *p, dev_t dev, unsigned count)

函数的参数:

        struct cdev *p,          linux2.6的核心结构体的指针

        dev_t dev,                设备号

        unsigned count   要注册的个数

函数的返回值:

        成功返回 0

        失败返回  负数

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:

        删除linux2.6设备的注册

函数的原型:

        void cdev_del(struct cdev *p)

函数的参数:

        struct cdev *p:linux2.6的核心结构体

函数的返回值:

        无

1.4 linux2.6自动生成设备文件相关API

linux2.6设备注册的时候优点是可以使用的设备号的范围很广,有一个最大的缺点就是不能自动的生成设备文件。

第一种:手动执行命令来生成设备文件mknod,这种方法比较繁琐  不方便

第二种:借助于内核提供的自动生成设备文件的api,要想使用自动生成设备文件的api  ,就必须要有一个类结构体。

函数的功能:

        创建类结构体

函数的头文件:

        linux/device.h

函数的原型

#define class_create(owner, name)                

({                                                  

        static struct lock_class_key __key; 

        __class_create(owner, name, &__key); 

})

可以理解成:

struct class * class_create(struct module *owner, const char *name)

函数的参数:

        struct module *owner,     固定填写 THIS_MODULE

        const char *name            类的名字  随意填写  最好有点意义

函数的返回值:

        成功返回  类结构体的指针

        失败返回  NULL

         +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:

        自动的创建一个设备文件

函数的头文件:

        linux/device.h

函数的原型:

    struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)

函数的参数:

        struct class *class,   类结构体的指针

        struct device *parent, 父节点设备  填NULL

        dev_t devt,          设备号

        void *drvdata,           传递给设备的私有数据  NULL 

        const char *fmt, ...   可变的传参  一般写设备的名字

函数的返回值:

        成功返回   设备的结构体指针

        失败返回   NULL

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:

        销毁设备

函数的头文件:

        linux/device.h

函数的原型:

        void device_destroy(struct class *class, dev_t devt)

函数的参数:

        struct class *class:类结构体指针

        dev_t devt :设备号

函数的返回值:

        无

+++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:

        销毁类结构体

函数的头文件:

        linux/device.h

函数的原型:

        void class_destroy(struct class *cls)‘

函数的参数:

        struct class *cls:类结构体指针

函数的返回值:

        无

1.5 linux2.6设备注册示例

mylinux.c文件

#include 
#include 
#include 
#include 
#include 
#include 



struct file_operations myfops;
struct cdev mycdev;
struct class *myclass;
dev_t mydev;

int myopen(struct inode *inode, struct file *file){
	gpio_set_value(EXYNOS4X12_GPM4(0),1);
	printk("LED4\n");
	return 0;
}

int myclose(){
	gpio_set_value(EXYNOS4X12_GPM4(0),1);
	gpio_direction_output(EXYNOS4_GPD0(0), 0);
	printk("close\n");
	return 0;

}

static int __init myled_init(void){
	if(alloc_chrdev_region(&mydev,0,1,"myBP")<0){
		printk("alloc_chrdev_region error\n");
	}
	printk("设备号:%d\n",mydev);
	printk("主设备号:%d\n",MAJOR(mydev));
	printk("次设备号:%d\n",MINOR(mydev));

	myfops.owner=THIS_MODULE;
	myfops.open=myopen;
	myfops.release=myclose;
	cdev_init(&mycdev,&myfops);
	cdev_add(&mycdev,mydev,1);

	
	myclass=class_create(THIS_MODULE,"myBP");
	if(myclass==NULL){
		printk("创建class失败\n");
		return -1;
	}
	device_create(myclass,NULL,mydev,NULL,"myBP");


	if(gpio_set_value(EXYNOS4_GPD0(0),"test")<0){
		printk("GPIO申请失败\n");
	}
	gpio_direction_output(EXYNOS4_GPD0(0), 0);
	return 0;
}
static void __exit myled_exit(void){
	//销毁类
	device_destroy(myclass,mydev);
	//销毁类结构体
	class_destroy(myclass);

	//释放linux2.6的注册
	cdev_del(&mycdev);
	//释放设备号
	unregister_chrdev_region(mydev,0);
}
module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");



你可能感兴趣的:(驱动,linux,驱动开发,单片机)