Linux学习第31天:Linux MISC 驱动实验:温故知新

这篇具有很好参考价值的文章主要介绍了Linux学习第31天:Linux MISC 驱动实验:温故知新。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Linux版本号4.1.15   芯片I.MX6ULL                                    大叔学Linux    品人间百味  思文短情长 


        学习是一个不断重复的过程。只有不断的使用、修正,才能越记越牢。将学习到的新的知识点应用到以往的项目经验中,才能不断提升自我,长此以往,温故知新,才能由量变产生质变。

        本节笔记主要学习LinuxMISC驱动试验。除了最基本的简介知识点外,主要重点在于试验程序的编写。

        本节的思维导图如下:

Linux学习第31天:Linux MISC 驱动实验:温故知新,嵌入式Linux驱动开发学习,linux,学习,嵌入式硬件,arm开发,驱动开发

一、MISC设备驱动简介

        MISC 驱动也叫做杂项驱动,也就是当我们板子上的某些外设无法进行分类的时候就可以使用 MISC 驱动。

        所有的 MISC 设备驱动的主设备号都为 10,不同的设备使用不同的从设备号。

        MISC 设备会自动创建 cdev,向 Linux 注册一个 miscdevice 设备。

57 struct miscdevice {
58 int minor; /* 子设备号 */
59 const char *name; /* 设备名字 */
60 const struct file_operations *fops; /* 设备操作集 */
61 struct list_head list;
62 struct device *parent;
63 struct device *this_device;
64 const struct attribute_group **groups;
65 const char *nodename;
66 umode_t mode;
67 };

        minor 表示子设备号, MISC 设备的主设备号为 10,这个是固定的,需要用户指定子设备号。

        name 就是此 MISC 设备名字,当此设备注册成功以后就会在/dev 目录下生成一个名为 name
的设备文件。 fops 就是字符设备的操作集合, MISC 设备驱动最终是需要使用用户提供的 fops
操作集合。

        使用 misc_register 函数向系统中注册一个 MISC 设备。

int misc_register(struct miscdevice * misc)

        卸载设备驱动模块的时候需要调用 misc_deregister 函数来注销掉 MISC 设备。

int misc_deregister(struct miscdevice *misc)

二、原理图分析

Linux学习第31天:Linux MISC 驱动实验:温故知新,嵌入式Linux驱动开发学习,linux,学习,嵌入式硬件,arm开发,驱动开发

三、试验程序编写

1、修改设备树

1 pinctrl_beep: beepgrp {
2 fsl,pins = <
3 MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x10B0 /* beep */
4 >;
5 };

2、beep驱动程序编写

29 #define MISCBEEP_NAME "miscbeep" /* 名字 */
30 #define MISCBEEP_MINOR 144 /* 子设备号 */
31 #define BEEPOFF 0 /* 关蜂鸣器 */
32 #define BEEPON 1 /* 开蜂鸣器 */
33
34 /* miscbeep 设备结构体 */
35 struct miscbeep_dev{
36 dev_t devid; /* 设备号 */
37 struct cdev cdev; /* cdev */
38 struct class *class; /* 类 */
39 struct device *device; /* 设备 */
40 struct device_node *nd; /* 设备节点 */
41 int beep_gpio; /* beep 所使用的 GPIO 编号 */
42 };
43
44 struct miscbeep_dev miscbeep; /* beep 设备 */
45
46 /*
47 * @description : 打开设备
48 * @param – inode : 传递给驱动的 inode
49 * @param - filp : 设备文件, file 结构体有个叫做 private_data 的成员变量
50 * 一般在 open 的时候将 private_data 指向设备结构体。
51 * @return : 0 成功;其他 失败
52 */
53 static int miscbeep_open(struct inode *inode, struct file *filp)
54 {
55 filp->private_data = &miscbeep; /* 设置私有数据 */
56 return 0;
57 }
58
59 /*
60 * @description : 向设备写数据
61 * @param - filp : 设备文件,表示打开的文件描述符
62 * @param - buf : 要写给设备写入的数据
63 * @param - cnt : 要写入的数据长度
64 * @param - offt : 相对于文件首地址的偏移
65 * @return : 写入的字节数,如果为负值,表示写入失败
66 */
67 static ssize_t miscbeep_write(struct file *filp,
const char __user *buf, size_t cnt, loff_t *offt)
68 {
69 int retvalue;
70 unsigned char databuf[1];
71 unsigned char beepstat;
72 struct miscbeep_dev *dev = filp->private_data;
73
74 retvalue = copy_from_user(databuf, buf, cnt);
75 if(retvalue < 0) {
76 printk("kernel write failed!\r\n");
77 return -EFAULT;
78 }
79
80 beepstat = databuf[0]; /* 获取状态值 */
81 if(beepstat == BEEPON) {
82 gpio_set_value(dev->beep_gpio, 0); /* 打开蜂鸣器 */
83 } else if(beepstat == BEEPOFF) {
84 gpio_set_value(dev->beep_gpio, 1); /* 关闭蜂鸣器 */
85 }
86 return 0;
87 }
88
89 /* 设备操作函数 */
90 static struct file_operations miscbeep_fops = {
91 .owner = THIS_MODULE,
92 .open = miscbeep_open,
93 .write = miscbeep_write,
94 };

标准的字符设备驱动。

96 /* MISC 设备结构体 */
97 static struct miscdevice beep_miscdev = {
98 .minor = MISCBEEP_MINOR,
99 .name = MISCBEEP_NAME,
100 .fops = &miscbeep_fops,
101 };

        MISC 设备 beep_miscdev,第 98 行设置子设备号为 144,第 99 行设置设备名字为“ miscbeep”,这样当系统启动以后就会在/dev/目录下存在一个名为“ miscbeep”的设备文件。第 100 行,设置 MISC 设备的操作函数集合,为 file_operations 类型。

103 /*
104 * @description : flatform 驱动的 probe 函数,当驱动与
105 * 设备匹配以后此函数就会执行
106 * @param - dev : platform 设备
107 * @return : 0,成功;其他负值,失败
108 */
109 static int miscbeep_probe(struct platform_device *dev)
110 {
111 int ret = 0;
112
113 printk("beep driver and device was matched!\r\n");
114 /* 设置 BEEP 所使用的 GPIO */
115 /* 1、获取设备节点: beep */
116 miscbeep.nd = of_find_node_by_path("/beep");
117 if(miscbeep.nd == NULL) {
118 printk("beep node not find!\r\n");
119 return -EINVAL;
120 }
121
122 /* 2、 获取设备树中的 gpio 属性,得到 BEEP 所使用的 BEEP 编号 */
123 miscbeep.beep_gpio = of_get_named_gpio(miscbeep.nd, "beep-gpio",
0);
124 if(miscbeep.beep_gpio < 0) {
125 printk("can't get beep-gpio");
126 return -EINVAL;
127 }
128
129 /* 3、设置 GPIO5_IO01 为输出,并且输出高电平,默认关闭 BEEP */
130 ret = gpio_direction_output(miscbeep.beep_gpio, 1);
131 if(ret < 0) {
132 printk("can't set gpio!\r\n");
133 }
134
135 /* 一般情况下会注册对应的字符设备,但是这里我们使用 MISC 设备
136 * 所以我们不需要自己注册字符设备驱动,只需要注册 misc 设备驱动即可
137 */
138 ret = misc_register(&beep_miscdev);
139 if(ret < 0){
140 printk("misc device register failed!\r\n");
141 return -EFAULT;
142 }
143
144 return 0;
145 }

        platform 框架的 probe 函数,当驱动与设备匹配以后此函数就会执行,首先在此函数中初始化 BEEP 所使用的 IO。最后在 138 行通过 misc_register 函数向 Linux 内核注册MISC 设备,也就是前面定义的 beep_miscdev。

147 /*
148 * @description : remove 函数,移除 platform 驱动的时候此函数会执行
149 * @param - dev : platform 设备
150 * @return : 0,成功;其他负值,失败
151 */
152 static int miscbeep_remove(struct platform_device *dev)
153 {
154 /* 注销设备的时候关闭 LED 灯 */
155 gpio_set_value(miscbeep.beep_gpio, 1);
156
157 /* 注销 misc 设备驱动 */
158 misc_deregister(&beep_miscdev);
159 return 0;
160 }

        platform 框架的 remove 函数,在此函数中调用 misc_deregister 函数来注销
MISC 设备。

162 /* 匹配列表 */
163 static const struct of_device_id beep_of_match[] = {
164 { .compatible = "atkalpha-beep" },
165 { /* Sentinel */ }
166 };
167
168 /* platform 驱动结构体 */
169 static struct platform_driver beep_driver = {
170 .driver = {
171 .name = "imx6ul-beep", /* 驱动名字 */
172 .of_match_table = beep_of_match, /* 设备树匹配表 */
173 },
174 .probe = miscbeep_probe,
175 .remove = miscbeep_remove,
176 };
177
178 /*
179 * @description : 驱动入口函数
180 * @param : 无
181 * @return : 无
182 */
183 static int __init miscbeep_init(void)
184 {
185 return platform_driver_register(&beep_driver);
186 }
187
188 /*
189 * @description : 驱动出口函数
190 * @param : 无
191 * @return : 无
192 */
193 static void __exit miscbeep_exit(void)
194 {
195 platform_driver_unregister(&beep_driver);
196 }

标准的 platform 驱动。

3、编写测试APP

20 #define BEEPOFF 0
21 #define BEEPON 1
22
23 /*
24 * @description : main 主程序
25 * @param - argc : argv 数组元素个数
26 * @param - argv : 具体参数
27 * @return : 0 成功;其他 失败
28 */
29 int main(int argc, char *argv[])
30 {
31 int fd, retvalue;
32 char *filename;
33 unsigned char databuf[1];
34
35 if(argc != 3){
36 printf("Error Usage!\r\n");
37 return -1;
38 }
39
40 filename = argv[1];
41 fd = open(filename, O_RDWR); /* 打开 beep 驱动 */
42 if(fd < 0){
43 printf("file %s open failed!\r\n", argv[1]);
44 return -1;
45 }
46
47 databuf[0] = atoi(argv[2]); /* 要执行的操作:打开或关闭 */
48 retvalue = write(fd, databuf, sizeof(databuf));
49 if(retvalue < 0){
50 printf("BEEP Control Failed!\r\n");
51 close(fd);
52 return -1;
53 }
54
55 retvalue = close(fd); /* 关闭文件 */
56 if(retvalue < 0){
57 printf("file %s close failed!\r\n", argv[1]);
58 return -1;
59 }
60 return 0;
61 }

四、运行测试

1、编译驱动程序和测试APP

obj-m := miscbeep.o

make -j32
编译成功以后就会生成一个名为“ miscbeep.ko”的驱动模块文件。

arm-linux-gnueabihf-gcc miscbeepApp.c -o miscbeepApp
编译成功以后就会生成 miscbeepApp 这个应用程序。

2、运行测试

depmod //第一次加载驱动的时候需要运行此命令
modprobe miscbeep.ko //加载设备模块

        当驱动模块加载成功以后我们可以在/sys/class/misc 这个目录下看到一个名为“ miscbeep
的子目录。

        输入ls /dev/miscbeep -l命令查看主次设备号。
 

        输入如下命令打开 BEEP:
./miscbeepApp /dev/miscbeep 1 //打开 BEEP
        在输入如下命令关闭 LED 灯:
./miscbeepApp /dev/miscbeep 0 //关闭 BEEP
        观察一下 BEEP 能否打开和关闭,如果可以的话就说明驱动工作正常,如果要卸载驱动的
话输入如下命令即可:rmmod miscbeep.ko

五、总结

        本节笔记主要学习LinuxMISC驱动试验。除了最基本的简介知识点外,主要重点在于试验程序的编写。


本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。文章来源地址https://www.toymoban.com/news/detail-741095.html

到了这里,关于Linux学习第31天:Linux MISC 驱动实验:温故知新的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • .net 温故知新【14】:Asp.Net Core WebAPI 缓存

    缓存指在中间层中存储数据的行为,该行为可使后续数据检索更快。 从概念上讲,缓存是一种性能优化策略和设计考虑因素。 缓存可以显著提高应用性能,方法是提高不常更改(或检索成本高)的数据的就绪性。 在最新的缓存控制规范文件RFC9111中,详细描述了浏览器缓存和

    2024年02月05日
    浏览(62)
  • 温故知新之:代理模式,静态代理和动态代理(JDK动态代理)

    代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。 静态代理 是一种代理模式的实现方式,它在编译期间就已经确定了代理对象,需要为每一个被代理对象创建一个代理类。静态代理的实现比较简单,但是每个被代理对象都需要创建

    2024年02月11日
    浏览(48)
  • .net 温故知新【17】:Asp.Net Core WebAPI 中间件

    到这篇文章为止,关于.NET \\\"温故知新\\\"系列的基础知识就完结了,从这一系列的系统回顾和再学习,对于.NET core、ASP.NET CORE又有了一个新的认识。 不光是从使用,还包括这些知识点的原理,虽然深入原理谈不上,但对于日常使用也够了,我想的是知其然,知其所以然。 在实际

    2024年01月18日
    浏览(59)
  • .net 温故知新【11】:Asp.Net Core WebAPI 入门使用及介绍

    在Asp.Net Core 上面由于现在前后端分离已经是趋势,所以asp.net core MVC用的没有那么多,主要以WebApi作为学习目标。 我使用的是VS2022, .Net 7版本。 在创建界面有几项配置: 配置Https 启用Docker 使用控制器 启用OpenAPI支持 不使用顶级语句 其中配置Https 是WebApi是否使用https协议,启

    2024年02月07日
    浏览(46)
  • <Linux开发>驱动开发 -Linux MISC 驱动

    <Linux开发>驱动开发 -Linux MISC 驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: <Linux开发> -之-系统移植 uboot移植过程详细记录(第一部分) <Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分) <Linux开发> -之

    2024年02月13日
    浏览(30)
  • Linux学习第30天:Linux 自带的 LED 灯驱动实验:驱动开发思维方式的转变势在必行

    Linux版本号4.1.15   芯片I.MX6ULL                                      大叔学Linux    品人间百味  思文短情长            学习嵌入式Linux驱动开发整整30天了。今天简单做一个小结。因为之前的主要工作是做ARM的裸机开发,所以接触Linux以后感觉很多东西都变了。不仅仅

    2024年02月05日
    浏览(66)
  • Linux 音频驱动实验

    开发板通过此接口外接了一个 WM8960 音频 DAC 芯片,本章我们就来学习一下如何使能 WM8960 驱动,并且通过 WM8960 芯片来完成音乐播放与录音。 1、WM8960 简介 ①、此部分是 WM8960 提供的输入接口,作为立体声音频输入源,一共提供了三路,分别为 LINPUT1/RINPUT1、LINPUT2/RINPUT2、LIN

    2024年02月15日
    浏览(42)
  • Linux USB 驱动实验

    USB 是很常用的接口,目前大多数的设备都是USB 接口的,比如鼠标、键盘、USB 摄像头等,我们在实际开发中也常常遇到USB 接口的设备,本章我们就来学习一下如何使能Linux内核自带的USB 驱动。注意!本章并不讲解具体的USB 开发,因为USB 接口很复杂,不同的设备其协议也不同

    2024年02月07日
    浏览(40)
  • Linux I2C 驱动实验

    目录 一、Linux I2C 驱动简介 1、I2C 总线驱动 2、I2C 设备驱动 1、 i2c_client 结构体 2、 i2c_driver 结构体 二、硬件分析 三、设备树编写 1、pinctrl_i2c1 2、在 i2c1 节点追加 ap3216c 子节点 3、验证 四、 代码编写 1、makefile 2、ap3216c.h  3、ap3216c.c ①、头文件 ②、驱动出入口  ③、 i2c驱动

    2024年02月08日
    浏览(54)
  • 【Linux驱动】设备树中指定中断 | 驱动中获得中断 | 按键中断实验

    🐱作者:一只大喵咪1201 🐱专栏:《Linux驱动》 🔥格言: 你只管努力,剩下的交给时间! 继续拿这个中断流程图来说话。 在硬件上,中断控制器只有 GIC 这一个,但是我们在软件上可以把 GPIO 也归类为中断控制器。 芯片会有多个GPIO模块,所以软件上的中断控制器就会有很

    2024年01月17日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包