系列文章目录
本系列使用的开发板为正点原子阿尔法IMX6ULL开发板,及根据正点原子所的提供教程学习同系列笔记已放置链接在上面。
文章目录
当工程中某些外设无法进行分类的时候就可以使用misc驱动,其实就是最简单的字符设备驱动。
简单来说,之前在字符设备驱动中会使用如下几个步骤完成设备创建:
alloc_chrdev_region(); /* 申请设备号 */
cdev_init(); /* 初始化 cdev */
cdev_add(); /* 添加 cdev */
class_create(); /* 创建类 */
device_create(); /* 创建设备 */
使用misc驱动后就不需要这些步骤了,使用misc_register函数既可完成,其函数原型如下:
int misc_deregister(struct miscdevice *misc)
misc:要注销的 MISC 设备。
返回值:负数,失败;0,成功。
同样的卸载也可以通过misc_deregister函数完成注销设备,其原型如下:
int misc_deregister(struct miscdevice *misc)
misc:要注销的 MISC 设备。
返回值:负数,失败;0,成功。
而不需要:
cdev_del(); /* 删除 cdev */
unregister_chrdev_region(); /* 注销设备号 */
device_destroy(); /* 删除设备 */
class_destroy(); /* 删除类 */
这些函数。
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;
};
其中需要设置minor、name和fops三个成员变量:
- minor表示子设备号,由于MISC设备的主设备号固定为10,所以只需要指定子设备号既可
- name为MISC设备名字,当设备注册成功以后会在/dev目录下生成一个名为name的设备文件
- fops是字符设备的操作集合,需要用户提供fops操作集合。
使用示例:
#define MISCBEEP_NAME "miscbeep" /* 名字 */
#define MISCBEEP_MINOR 144 /* 子设备号 */
/* 设备操作函数 */
static struct file_operations miscbeep_fops = {
.owner = THIS_MODULE,
.open = miscbeep_open,
.write = miscbeep_write,
};
/* MISC设备结构体 */
static struct miscdevice beep_miscdev = {
.minor = MISCBEEP_MINOR,
.name = MISCBEEP_NAME,
.fops = &miscbeep_fops,
};
/*
* @description : flatform驱动的probe函数,当驱动与
* 设备匹配以后此函数就会执行
* @param - dev : platform设备
* @return : 0,成功;其他负值,失败
*/
static int miscbeep_probe(struct platform_device *dev)
{
int ret = 0;
printk("beep driver and device was matched!\r\n");
/* 设置BEEP所使用的GPIO */
/* 1、获取设备节点:beep */
miscbeep.nd = of_find_node_by_path("/beep");
if(miscbeep.nd == NULL) {
printk("beep node not find!\r\n");
return -EINVAL;
}
/* 2、 获取设备树中的gpio属性,得到BEEP所使用的BEEP编号 */
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;
}
/* 3、设置GPIO5_IO01为输出,并且输出高电平,默认关闭BEEP */
ret = gpio_direction_output(miscbeep.beep_gpio, 1);
if(ret < 0) {
printk("can't set gpio!\r\n");
}
/* 一般情况下会注册对应的字符设备,但是这里我们使用MISC设备
* 所以我们不需要自己注册字符设备驱动,只需要注册misc设备驱动即可
*/
ret = misc_register(&beep_miscdev);
if(ret < 0){
printk("misc device register failed!\r\n");
return -EFAULT;
}
return 0;
}