栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux驱动开发|MISC驱动

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux驱动开发|MISC驱动

MISC驱动 一、MISC设备驱动介绍

MISC设备也叫杂项设备,即当板子上的某些外设无法分类时,就可以使用MISC设备驱动。所有的 MISC 设备驱动的主设备号都为 10,不同的设备使用不同的从设备号。MISC设备会自动创建cdev,不需要手动创建,因此采用 MISC 设备驱动可以简化字符设备驱动的编写。

向 Linux 注册一个 miscdevice 设备, miscdevice是一个结构体,定义在文件 include/linux/miscdevice.h 中,内容如下:

 struct miscdevice {
	int minor; 							
	const char *name; 					
	const struct file_operations *fops; 
	struct list_head list;
	struct device *parent;
	struct device *this_device;
	const struct attribute_group **groups;
	const char *nodename;
	umode_t mode;
};

定义了MISC设备后,需要设置minor、name和fops三个成员变量。minor表示子设备号,主设备号固定为10,Linux系统预定义了一些MISC设备的子设备号,定义在include/linux/miscdevice.h 文件中,可以从中挑选,也可以自已定义

#define PSMOUSE_MINOR 1
#define MS_BUSMOUSE_MINOR 2 
#define ATIXL_BUSMOUSE_MINOR 3 

#define ATARIMOUSE_MINOR 5 
#define SUN_MOUSE_MINOR 6 
......
#define MISC_DYNAMIC_MINOR 255

设置好miscdevice后,就需要向系统中注册MISC设备,卸载设备驱动时需要注销掉MISC设备。注册和注销MISC设备使用如下函数

  • misc_register:注册MISC设备
int misc_register(struct miscdevice * misc)
//misc:要注册的 MISC 设备
//返回值:负数,失败;0,成功



alloc_chrdev_region(); 	
cdev_init(); 			
cdev_add(); 			
class_create(); 		
device_create(); 		
  • misc_deregister:注销MISC设备
int misc_deregister(struct miscdevice * misc)
//misc:要注销的 MISC 设备
//返回值:负数,失败;0,成功



cdev_del(); 					
unregister_chrdev_region(); 	
device_destroy(); 				
class_destroy(); 				
二、MISC设备驱动实验

本实验采用 platform 加 misc 的方式编写 beep 驱动,采用 platform 来实现总线、设备和驱动, misc 主要负责完成字符设备的创建

2.1 修改设备树
  • 添加pinctrl节点:在iomuxc节点的imx6ul-evk子节点下创建“pinctrl_beep”节点,复用SNVS_TAMPER1
pinctrl_beep: beepgrp {
	fsl,pins = <
		MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01		0x10B0
	>;
};
//MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 用于设置pin的复用功能
//0x10B0 用于设置pin的电气特性
  • 添加BEEP设备节点:在根节点下创建beep设备节点,设置PIN对应的pinctrl节点,指定所使用的的GPIO
beep {
	#address-cells = <1>;
	#size-cells = <1>;
	compatible = "atkalpha-beep";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_beep>;
	led-gpio = <&gpio5 1 GPIO_ACTIVE_HIGH>;
	status = "okay";
};
  • 检查PIN是否冲突:检查pinctrl中设置以及设备节点中指定的引脚有没有被别的外设使用

保存修改后,在kernel主目录下使用“make dtbs”命令编译设备树,使用新的设备树文件启动Llinux系统

2.2 驱动程序编写

新建 miscbeep.c 驱动文件,并输入如下内容

#define MISCBEEP_NAME		"miscbeep"	
#define MISCBEEP_MINOR		144			
#define BEEPOFF 			0			
#define BEEPON 				1			

struct miscbeep_dev{
	dev_t devid;				
	struct cdev cdev;			
	struct class *class;		
	struct device *device;		
	struct device_node	*nd; 	
	int beep_gpio;				
};
struct miscbeep_dev miscbeep;		

static int miscbeep_open(struct inode *inode, struct file *filp){
	filp->private_data = &miscbeep; 
	return 0;
}

static ssize_t miscbeep_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt){
	int retvalue;
	unsigned char databuf[1];
	unsigned char beepstat;
	struct miscbeep_dev *dev = filp->private_data;

	retvalue = copy_from_user(databuf, buf, cnt);
	if(retvalue < 0) {
		printk("kernel write failed!rn");
		return -EFAULT;
	}

	beepstat = databuf[0];		
	if(beepstat == BEEPON) {	
		gpio_set_value(dev->beep_gpio, 0);	
	} else if(beepstat == BEEPOFF) {
		gpio_set_value(dev->beep_gpio, 1);	
	}
	return 0;
}

static struct file_operations miscbeep_fops = {
	.owner = THIS_MODULE,
	.open = miscbeep_open,
	.write = miscbeep_write,
};

static struct miscdevice beep_miscdev = {
	.minor = MISCBEEP_MINOR,
	.name = MISCBEEP_NAME,
	.fops = &miscbeep_fops,
};

static int miscbeep_probe(struct platform_device *dev){
	int ret = 0;
	printk("beep driver and device was matched!rn");
	
	
	miscbeep.nd = of_find_node_by_path("/beep");
	if(miscbeep.nd == NULL) {
		printk("beep node not find!rn");
		return -EINVAL;
	} 
	
	miscbeep.beep_gpio = of_get_named_gpio(miscbeep.nd, "beep-gpio", 0);
	if(miscbeep.beep_gpio < 0) {
		printk("can't get beep-gpio");
		return -EINVAL;
	}
	
	ret = gpio_direction_output(miscbeep.beep_gpio, 1);
	if(ret < 0) {
		printk("can't set gpio!rn");
	}	
	
	ret = misc_register(&beep_miscdev);
	if(ret < 0){
		printk("misc device register failed!rn");
		return -EFAULT;
	}

	return 0;
}

static int miscbeep_remove(struct platform_device *dev){
	
	gpio_set_value(miscbeep.beep_gpio, 1);
	
	misc_deregister(&beep_miscdev);
	return 0;
}

static const struct of_device_id beep_of_match[] = {
    { .compatible = "atkalpha-beep" },
    {  }
};

static struct platform_driver beep_driver = {
     .driver     = {
         .name   = "imx6ul-beep",         
         .of_match_table = beep_of_match, 
     },
     .probe      = miscbeep_probe,
     .remove     = miscbeep_remove,
};

static int __init miscbeep_init(void){
	return platform_driver_register(&beep_driver);
}

static void __exit miscbeep_exit(void){
	platform_driver_unregister(&beep_driver);
}

module_init(miscbeep_init);
module_exit(miscbeep_exit);
MODULE_LICENSE("GPL");
2.3 测试程序编写

新建测试文件 miscbeepApp.c,并编写程序

#define BEEPOFF	0
#define BEEPON 	1

int main(int argc, char *argv[]){
	int fd, retvalue;
	char *filename;
	unsigned char databuf[1];
	
	if(argc != 3){
		printf("Error Usage!rn");
		return -1;
	}

	filename = argv[1];
	fd = open(filename, O_RDWR);	
	if(fd < 0){
		printf("file %s open failed!rn", argv[1]);
		return -1;
	}

	databuf[0] = atoi(argv[2]);	
	retvalue = write(fd, databuf, sizeof(databuf));
	if(retvalue < 0){
		printf("BEEP Control Failed!rn");
		close(fd);
		return -1;
	}

	retvalue = close(fd); 
	if(retvalue < 0){
		printf("file %s close failed!rn", argv[1]);
		return -1;
	}
	return 0;
}
2.4 运行测试
  • 修改Makefile编译目标变量
obj-m := miscbeep.o
  • 使用“make -j32”编译出驱动模块文件
make -j32
  • 使用“arm-linux-gnueabihf-gcc”命令编译测试APP
arm-linux-gnueabihf-gcc miscbeepApp.c -o miscbeepApp
  • 将驱动文件和APP可执行文件拷贝至“rootfs/lib/modules/4.1.15”中

  • 使用“modprobe”命令加载驱动,加载成功后总线就会进行匹配

depmod  #第一次加载驱动时,需使用“depmod”命令
modprobe miscbeep.ko
  • 加载成功后可以在/sys/class/misc 目录下看到一个名为“miscbeep”的子目录

所有的 misc 设备都属于同一个类, /sys/class/misc 目录下就是 misc 这个类的所有设备,每个设备对应一个子目录

  • 驱动与设备匹配成功以后就会生成/dev/miscbeep 这个设备驱动文件
ls /dev/miscbeep -l  #查看设备的主次设备号

  • 使用以下命令打开或者关闭Beep
./miscbeepApp /dev/miscbeep 1
./miscbeepApp /dev/miscbeep 0

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/680042.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号