Linux嵌入式驱动开发03——杂项设备驱动(附源码)

全系列传送门

Linux嵌入式驱动开发01——第一个驱动Hello World(附源码)

Linux嵌入式驱动开发02——驱动编译到内核

Linux嵌入式驱动开发03——杂项设备驱动(附源码)

Linux嵌入式驱动开发04——应用层和内核层数据传输

Linux嵌入式驱动开发05——物理地址到虚拟地址映射

Linux嵌入式驱动开发06——第一个相对完整的驱动实践编写

Linux嵌入式驱动开发07——GPIO驱动过程记录(飞凌开发板)

Linux嵌入式驱动开发08——字符设备(步步为营)

Linux嵌入式驱动开发09——平台总线详解及实战

Linux嵌入式驱动开发10——设备树开发详解

Linux嵌入式驱动开发11——平台总线模型修改为设备树实例

Linux嵌入式驱动开发12——pinctl和gpio子系统实践操作

Linux嵌入式驱动开发13——ioctl接口(gpio控制使用)

Linux嵌入式驱动开发14——中断的原理以及按键中断的实现(tasklet中断下文)

Linux嵌入式驱动开发15——等待队列和工作队列

Linux嵌入式驱动开发16——按键消抖实验(内核定时器)

Linux嵌入式驱动开发17——输入子系统

Linux嵌入式驱动开发18——I2C通信

Linux三大设备驱动

字符设备

IO的传输过程是以字符为单位的,没有缓冲,比如I2C,SPI都是字符设备

块设备

IO的传输过程以块为单位,跟存储相关的,都属于块设备,比如TF卡

网络设备

与前两个不一样,是以socket套接字来访问的

杂项设备驱动

杂项设备是字符设备的一种,可以自动生成设备节点

系统中也有很多的杂项设备,输入下面的命令可以查看

 cat /proc/misc

可以看到misc的所有的子设备驱动
在这里插入图片描述

杂项设备和字符设备区别

杂项设备要比字符设备代码简单

杂项设备的主设备号相同,均为10,次设备号不同,主设备号相同就可以节省内核的资源

主设备号和次设备号

设备号包含主设备号和次设备号,主设备号在Linux系统里是唯一的,但是次设备号不一定唯一。

设备号是计算机识别设备的一种方式,主设备号相同的也就被视为同一类设备。

主设备号可以比作电话号码的区号,比如北京的区号是010

次设备号可以比作电话号码

主设备号可以通过命令

cat /proc/devices

在这里插入图片描述

杂项设备的描述

通过命令打开Linux源码目录下的

include/linux/

可以看到很多的头文件
在这里插入图片描述
我们找到我们所要查看的杂项设备mis的头文件miscdevice.h,然后打开

就可以找到对于mis砸向驱动的描述了
在这里插入图片描述

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;
};
  • int minor;次设备号
  • const char *name;设备节点的名字
  • const struct file_operations *fops;文件操作集

文件操作集的使用

include/linux/fs.h

通过搜索查找file_operations 可以找到这个结构体
在这里插入图片描述

次设备号分配

次设备号要保证唯一,这里的MISC_DYNAMIC_MINOR可以自动分配
在这里插入图片描述
下面的这个是对杂项设备的注册和注销

extern int misc_register(struct miscdevice *misc);
extern int misc_deregister(struct miscdevice *misc);

编写一个杂项设备驱动

注册杂项设备的流程

  • 第一步 填充miscdevice结构体成员
  • 第二步 填充file_operations结构体
  • 第三步 注册杂项设备并生成设备节点

第一步 填充miscdevice结构体成员

struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "hello_misc",
    .fops = misc_fops
};

第二步 填充file_operations结构体

struct file_operations misc_fops = {
    .owner = THIS_MODULE
};

第三步 注册杂项设备并生成设备节点

static int misc_init(void)
{
    int ret;

    ret = misc_register(&misc_dev);

    if(ret < 0){
        printk("misc_register failed!!!\n");
        return -1;
    }

    printk("misc_register succeed!!!\n");          // 在内核中无法使用c语言库,所以不用printf
    
    return 0;
}

static void misc_exit(void)
{
    misc_deregister(&misc_dev);

    printk("misc exit!!!\n");
}

完整代码

Linux嵌入式杂项设备驱动模块modules_misc

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>


struct file_operations misc_fops = {
    .owner = THIS_MODULE
};

struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "hello_misc",
    .fops = misc_fops
};


static int misc_init(void)
{
    int ret;

    ret = misc_register(&misc_dev);

    if(ret < 0){
        printk("misc_register failed!!!\n");
        return -1;
    }

    printk("misc_register succeed!!!\n");          // 在内核中无法使用c语言库,所以不用printf
    
    return 0;
}

static void misc_exit(void)
{
    misc_deregister(&misc_dev);

    printk("misc exit!!!\n");
}

module_init(misc_init);
module_exit(misc_exit);


MODULE_LICENSE("GPL");              //声明模块拥有开源许可

编译成模块

Make file

# 开发板Linux内核的实际路径 
# KDIR变量
KDIR:=/work/linux-4.1.15

#  获取当前目录
PWD:=$(shell pwd)

# obj-m表示将 chrdevbase.c这个文件 编译为 chrdevbase.ko模块。
obj-m += misc.o

# 编译成模块
all:
	make -C $(KDIR) M=$(PWD) modules

clean:
	make -C $(KDIR) M=$(PWD) clean

执行make,但是出现错误
在这里插入图片描述
所以来定位到程序中检查,原来是结构体的错误引用,这里应该加上地址符
在这里插入图片描述
排查完错误,保存,make,编译成功
在这里插入图片描述
在这里插入图片描述

注册验证

发送到开发板ko文件,然后

insmod misc.ko

再到我们的/dev文件夹查看

ls /dev/

在这里插入图片描述
这样,最简单的杂项设备我们就完成了

然后再验证一下注销功能

rmmod misc.ko

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值