嵌入式学习笔记--misc

嵌入式学习笔记–misc

一、内核自带MISC驱动简介
misc 的意思是混合、杂项的,因此 MISC 驱动也叫做杂项驱动,也就是当我们板子上的某些外设无法进行分类的时候就可以使用 MISC 驱动。 MISC 驱动其实就是最简单的字符设备驱动,通常嵌套在 platform 总线驱动中,实现复杂的驱动,

所有的 MISC 设备驱动的主设备号都为 10,不同的设备使用不同的从设备号。随着 Linux字符设备驱动的不断增加,设备号变得越来越紧张,尤其是主设备号, MISC 设备驱动就用于解决此问题。 MISC 设备会自动创建 cdev,不需要像我们以前那样手动创建,因此采用 MISC 设备驱动可以简化字符设备驱动的编写。

	MISC驱动编写的核心就是初始化miscdevice结构体变量。然后使用misc_register向内核注册,卸载驱动的时候使用misc_deregister来卸载miscdevice。	如果设置miscdevice里面minor为255的话,表示由内核自动分配也给次设备号。

二、驱动实例

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define MISCBEEP_NAME		"miscbeep"	/* 名字 	*/
#define MISCBEEP_MINOR		144			/* 子设备号 */
#define BEEPOFF 			0			/* 关蜂鸣器 */
#define BEEPON 				1			/* 开蜂鸣器 */

struct misc_devices {
	struct device_node *dev_node;
	int beep_gpio;
};
struct misc_devices *misc_dev;

static int miscbeep_open(struct inode *inod, struct file *filp){
	printk("-----------%s------------\n",__FUNCTION__);

	filp->private_data = misc_dev;
	return 0;
}

static ssize_t miscbeep_read(struct file *filp, char __user *buf, size_t size, loff_t *loft){
	printk("-----------%s------------\n",__FUNCTION__);
	return 0;
}
static ssize_t miscbeep_write(struct file *filp, const char __user *buf, size_t size, loff_t *loft){
	printk("-----------%s------------\n",__FUNCTION__);

	int ret;
	unsigned char databuf[1];
	struct misc_devices *dev = filp->private_data;
	ret = copy_from_user(databuf, buf, size);
	if(ret<0){
		printk("kernel write failed!!\n");
		return -EFAULT;
	}
	if(databuf[0] == BEEPON){
		gpio_set_value(dev->beep_gpio,0);
	}else if(databuf[0] == BEEPOFF){
		gpio_set_value(dev->beep_gpio,1);
	}

	return 0;
}
static int miscbeep_release(struct inode *inod, struct file *filp){
	printk("-----------%s------------\n",__FUNCTION__);
	return 0;
}

//004-2
static struct file_operations miscbeep_fops = {
	.owner = THIS_MODULE,
	.open = miscbeep_open,
	.read = miscbeep_read,
	.write = miscbeep_write,
	.release = miscbeep_release,
};

//004-1
static struct miscdevice misc_beep = {
	.minor = 144,//次设备号。主设备号系统已经提供,为10
	.name = "miscbeep",//设备的名字。   加载驱动成功后,/dev/下会出现miscbeep这个设备
	.fops = &miscbeep_fops,
};

//03-1
static int misc_probe(struct platform_device *dev){
	printk("device and driver has matched!!\n");
	misc_dev = (struct misc_devices *)kzalloc(sizeof(struct misc_devices),GFP_KERNEL);
	if(misc_dev == NULL){
		printk("misc_dev alloc failed!!\n");
		return -ENOMEM;
	}

	int ret = 0;
	//001.获取设备节点
	misc_dev->dev_node = of_find_node_by_path("/gpio_beep");
	if(misc_dev->dev_node == NULL){
		printk("beep node not find!!\n");
		return -EINVAL;
	}
	//002.获取设备树中gpio属性,gpio号
	misc_dev->beep_gpio = of_get_named_gpio(misc_dev->dev_node, "beep-gpio", 0);
	if(misc_dev->beep_gpio < 0){
		printk("beep_gpio can not get!!\n");
		return -EINVAL;
	}
	printk("beep-gpio %d !!\n",misc_dev->beep_gpio);
	///003.设置gpio为输出,1为输出高电平	
	ret = gpio_direction_output(misc_dev->beep_gpio, 1);
	if(ret<0){
		printk("can not set gpio!!\n");
	}
	
	//004.
	ret = misc_register(&misc_beep);
	if(ret < 0){
		printk("misc device register failed!!\n");

		return -EINVAL;
	}

	printk("------misc_probe done!----\n");
	return 0;
}
//03-2
static int misc_remove(struct platform_device *dev){
	gpio_set_value(misc_dev->beep_gpio,1);
	misc_deregister(&misc_beep);

	kfree(misc_dev);
	return 0;
}

const struct of_device_id	misc_of_match[] = {
	{.compatible = "peifeng-gpiobeep"},//和设备树中的compatible应该一至
	{}
};

//03.
struct platform_driver misc_drv = {
	.driver = {
		.name = "peifeng-gpiobeep",
		.of_match_table = misc_of_match,
	},
	.probe = misc_probe,
	.remove = misc_remove,
};

//01.
static int __init misc_drv_init(void){
	printk("-----------%s------------\n",__FUNCTION__);
	return platform_driver_register(&misc_drv);
}

//02.
static void __exit misc_drv_exit(void){
	printk("-----------%s------------\n",__FUNCTION__);
	return platform_driver_unregister(&misc_drv);
}

module_init(misc_drv_init);
module_exit(misc_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PEIFENG");

在这里插入图片描述

在这里插入图片描述

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"


#define MISCBEEP_NAME		"miscbeep"	/* 名字 	*/
#define MISCBEEP_MINOR		144			/* 子设备号 */
#define BEEPOFF 			0			/* 关蜂鸣器 */
#define BEEPON 				1			/* 开蜂鸣器 */

int main(int argc,char *argv[]){
	int fd,ret;
	unsigned databuf[1];

	if(argc<3){
		printf("error useage!! please ./**  /dev/miscbeep  1");

		return -1;
	}

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

	databuf[0] = atoi(argv[2]);
	ret = write(fd,databuf,sizeof(databuf));
	if(ret <0){
		printf("beep control failed!!\n");
		close(fd);
		return -1;
	}
	ret = close(fd);
	if(ret<0){
		printf("file %s close failed!!\n",argv[1]);

		return -1;
	}

	return 0;
}

加载驱动:insmod misc_drv.ko
运行:
开 ./misc_app /dev/miscbeep 1

关 ./misc_app /dev/miscbeep 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值