字符驱动程序模板

设备驱动模型通过sysfs文件系统向用户层提供设备驱动视图,如下。

1.设备是具体的一个个设备,在/sys/devices/是创建了实际的文件节点。而其他目录,如设备类和总线以下的子目录中出现的设备都是用符号链接指向/sys/devices/目录下的文件。

2.设备类是对/sys/devices/下的各种设备进行归类,以体现一类设备的公共属性,如鼠标和触摸屏都是属于input设备类。

3.总线目录是总线、设备、驱动模型的核心目录。因为设备和驱动都是依附在某种总线上的,如USB、PCI和平台总线等。设备和驱动正是依靠总线的管理功能才能找到对方,如设备注册到总线时去寻找驱动,而驱动注册的时候去寻找其能够支持的设备。

一、申请设备号:

    1.动态申请设备号(alloc_chrdev_region)

    2.静态申请设备号(register_chrdev_region)

二、设备注册:

    1.为cdev分配空间(cdev_alloc)。为字符设备分配空间。

    2.初始化cdev(cdev_init)。字符设备初始化,绑定相关操作到设备

    3.将cdev添加进Kernel(cdev_add)。把设备号和设备关联起来。

三、生成设备节点

    1.创建设备类(class_create)

    2.通过设备类,创建设备节点(device_create)

字符驱动程序:
 

  • #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/delay.h> /*delay*/
    #include <linux/cdev.h>
    #include <linux/device.h>
    #include <linux/slab.h>	/*kmalloc*/
    #include <linux/vmalloc.h> /*vmalloc*/
    #include <linux/types.h>   /*ssize_t*/
    #include <linux/fs.h>	  /*file_operaiotns*/
    #include <linux/gpio_keys.h>
    #include <linux/gpio.h>
    #include <linux/irq.h>
    #include <linux/interrupt.h>
    #include <linux/sched.h>
    #include <asm/irq.h>
    #include <asm/io.h>
    #include <asm/uaccess.h>
    #include <asm-generic/ioctl.h>
    #include <asm-generic/errno-base.h>
    
    /************硬件相关*************/
    #include <mach/iomux-mx6dl.h>
    
    #define DEV_NAME "gpios"
    
    /**主设备号和次设备号**/
    int device_major = 0;
    int device_minor = 0;
    static struct class *gpio_class;	/*在/sys目录创造一个类*/
    static struct cdev *gpio_class_dev; /*在这个类下,创造一个设备节点*/
    
    /*open函数的实现*/
    static int gpio_open(struct inode *inode, struct file *file)
    {
    
    	printk(KERN_ALERT "OPEN\n");
    	return 0;
    }
    
    static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    {
    	printk(KERN_ALERT "ioctl\n");
    	return 0;
    }
    
    /*release函数的实现*/
    static int gpio_close(struct inode *inode, struct file *file)
    {
    
    	printk(KERN_ALERT "close\n");
    	return 0;
    }
    
    ssize_t gpio_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
    {
    
    	printk(KERN_ALERT "read\n");
    	return 0;
    }
    
    /*具体的文件操作集合*/
    static const struct file_operations gpio_fops =
    	{
    		/*这是拥有者*/
    		.owner = THIS_MODULE,
    		.open = gpio_open,
    		.unlocked_ioctl = gpio_ioctl,
    		.release = gpio_close,
    		.read = gpio_read,
    };
    
    /*驱动的初始化函数*/
    static int gpio_init(void)
    {
    	int ret;
    	dev_t gpio_dev_no; //设备号
    
    	if (device_major)
    	{
    		gpio_dev_no = MKDEV(device_major, device_minor);
    		register_chrdev_region(gpio_dev_no, 1, DEV_NAME);
    	}
    	else
    	{
    		ret = alloc_chrdev_region(&gpio_dev_no, 0, 1, DEV_NAME);
    		if (ret)
    		{
    			printk(KERN_ALERT "alloc_chrdev_region failed\n");
    		}
    		device_major = MAJOR(gpio_dev_no);
    		device_minor = MINOR(gpio_dev_no);
    		printk(KERN_ALERT "major=%d minor=%d\n", MAJOR(gpio_dev_no), MINOR(gpio_dev_no));
    	}
    
    	gpio_class_dev = cdev_alloc();								  //分配空间
    	cdev_init(gpio_class_dev, &gpio_fops);	/*字符设备初始化,绑定相关操作到设备*/
    	gpio_class_dev->owner = THIS_MODULE;						  /*设备的拥有者*/
    	cdev_add(gpio_class_dev, gpio_dev_no, 1);/*添加设备到内核*/
    	gpio_class = class_create(THIS_MODULE, DEV_NAME); /*创建设备类,用于自动创建设备文件*/
    	device_create(gpio_class, NULL, gpio_dev_no, NULL, DEV_NAME); /*依据以前创建的设备类,创建设备*/
    	return 0;
    }
    
    /*退出函数*/
    static void gpio_exit(void)
    {
    	/*设备卸载*/
    	cdev_del(gpio_class_dev);										//注销设备
    	unregister_chrdev_region(MKDEV(device_major, device_minor), 1); //释放设备号
    	device_destroy(gpio_class, MKDEV(device_major, device_minor));
    	class_destroy(gpio_class);
    }
    
    /*LICENSE信息*/
    MODULE_LICENSE("GPL");
    /*卸载和加载*/
    module_init(gpio_init);
    module_exit(gpio_exit);
    

测试程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <poll.h>
#include <signal.h>
#include <asm-generic/ioctl.h>

int main(int args, char *argv[])
{
    int fd, val,ret;
	unsigned char buffer[10]={0};
	
	fd = open("/dev/gpios",O_RDWR);	
	if(fd < 0)	
	{		
		printf("can't open %s\n","/dev/gpios");
	}
	sleep(2);		
	ret= read(fd,buffer,0);
	sleep(2);
	ioctl(fd,0,NULL);
	sleep(2);
    close(fd);
    return 0;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值