嵌入式Linux应用开发-第十四章查询方式的按键驱动程序

嵌入式Linux应用开发-第十四章查询方式的按键驱动程序

  • 第十四章 查询方式的按键驱动程序_编写框架
    • 14.1 LED驱动回顾
    • 14.2 按键驱动编写思路
    • 14.3 编程:先写框架
      • 14.3.1 把按键的操作抽象出一个button_operations结构体
      • 14.3.2 驱动程序的上层:file_operations结构体
    • 14.4 测试
    • 14.5 课后怎业

第十四章 查询方式的按键驱动程序_编写框架

在这里插入图片描述

14.1 LED驱动回顾

对于 LED,APP调用 open函数导致驱动程序的 led_open函数被调用。在里面,把 GPIO配置为输出引脚。安装驱动程序后并不意味着会使用对应的硬件,而 APP要使用对应的硬件,必须先调用 open函数。所以建议在驱动程序的 open函数中去设置引脚。
APP继续调用 write函数传入数值,在驱动程序的 led_write函数根据该数值去设置 GPIO的数据寄存器,从而控制 GPIO的输出电平。
怎么操作寄存器?从芯片手册得到对应寄存器的物理地址,在驱动程序中使用 ioremap函数映射得到虚拟地址。驱动程序中使用虚拟地址去访问寄存器。
在这里插入图片描述

14.2 按键驱动编写思路

GPIO按键的原理图一般有如下 2种:
在这里插入图片描述

按键没被按下时,上图中左边的 GPIO电平为高,右边的 GPIO电平为低。 按键被按下后,上图中左边的 GPIO电平为低,右边的 GPIO电平为高。
编写按键驱动程序最简单的方法如下图所示:
在这里插入图片描述

回顾一下编写驱动程序的套路:
在这里插入图片描述

对于使用查询方式的按键驱动程序,我们只需要实现 button_open、button_read。

14.3 编程:先写框架

我们的目的写出一个容易扩展到各种芯片、各种板子的按键驱动程序,所以驱动程序分为上下两层: ① button_drv.c分配/设置/注册 file_operations结构体
起承上启下的作用,向上提供 button_open,button_read供 APP调用。
而这 2个函数又会调用底层硬件提供的 p_button_opr中的 init、read函数操作硬件。
② board_xxx.c分配/设置/注册 button_operations结构体
这个结构体是我们自己抽象出来的,里面定义单板 xxx的按键操作函数。
这样的结构易于扩展,对于不同的单板,只需要替换 board_xxx.c提供自己的 button_operations结构体即可。
在这里插入图片描述
使用 GIT下载所有源码后,本节源码位于如下目录:

01_all_series_quickstart\ 
05_嵌入式 Linux驱动开发基础知识\source\ 
04_button_drv\01_button_drv_template 

14.3.1 把按键的操作抽象出一个button_operations结构体

首先看看 button_drv.h,它定义了一个 button_operations结构体,把按键的操作抽象为这个结构体:

04 struct button_operations { 
05     int count; 
06     void (*init) (int which); 
07     int (*read) (int which); 
08 }; 
09 
10 void register_button_operations(struct button_operations *opr); 
11 void unregister_button_operations(void); 
12 

再看看 board_xxx.c,它实现了一个 button_operations结构体,代码如下。
第 45行调用 register_button_operations函数,把这个结构体注册到上层驱动中。 37 static struct

button_operations my_buttons_ops ={ 
38     .count = 2, 
39     .init  = board_xxx_button_init_gpio, 
40     .read  = board_xxx_button_read_gpio, 
41 }; 
42 
43 int board_xxx_button_init(void) 
44 { 
45     register_button_operations(&my_buttons_ops); 
46     return 0; 
47 } 
48 

14.3.2 驱动程序的上层:file_operations结构体

上层是 button_drv.c,它的核心是 file_operations结构体,首先看看入口函数,代码如下。
第 83行向内核注册一个 file_operations结构体。
第 85行创建一个 class,但是该 class下还没有 device,在后面获得底层硬件的信息时再在 class下创建 device:这只是用来创建设备节点,它不是驱动程序的核心。

81 int button_init(void) 
82 { 
83     major = register_chrdev(0, "xxxxxx_button", &button_fops); 
84 
85     button_class = class_create(THIS_MODULE, "xxxxxx_button"); 
86     if (IS_ERR(button_class)) 
87         return -1; 
88 
89     return 0; 
90 } 
91 

再来看看 button_drv.c中 file_operations结构体的成员函数,代码如下。
第 34、44行都用到一个 button_operations指针,它是从何而来?

28 static struct button_operations *p_button_opr; 
29 static struct class *button_class; 
30 
31 static int button_open (struct inode *inode, struct file *file) 
32 { 
33     int minor = iminor(inode); 
34     p_button_opr->init(minor); 
35     return 0; 
36 } 
37 
38 static ssize_t button_read (struct file *file, char __user *buf, size_t size, loff_t *off) 
39 { 
40     unsigned int minor = iminor(file_inode(file)); 
41     char level; 
42     int err; 
43 
44     level = p_button_opr->read(minor); 
45     err = copy_to_user(buf, &level, 1); 
46     return 1; 
47 } 
48 
49 
50 static struct file_operations button_fops = { 51     .open = button_open, 
52     .read = button_read, 
53 }; 

上面第 34、44行都用到一个 button_operations指针,来自于底层硬件相关的代码。
底层代码调用 register_button_operations函数,向上提供这个结构体指针。
register_button_operations函数代码如下,它还根据底层提供的 button_operations调用
device_create,这是创建设备节点(第 62行)。

55 void register_button_operations(struct button_operations *opr) 
56 { 
57     int i; 
58 
59     p_button_opr = opr; 
60     for (i = 0; i < opr->count; i++) 
61     { 
62         device_create(button_class, NULL, MKDEV(major, i), NULL, "xxxxxx_button%d", i); 
63     } 
64 } 
65 

14.4 测试

这只是一个示例程序,还没有真正操作硬件。测试程序操作驱动程序时,只会导致驱动程序中打印信息。
首先设置交叉工具链,修改驱动 Makefile中内核的源码路径,编译驱动和测试程序。
启动开发板后,通过 NFS访问编译好驱动程序、测试程序,就可以在开发板上如下操作了:

# insmod button_drv.ko   // 装载驱动程序 
[  435.276713] button_drv: loading out-of-tree module taints kernel. 
# insmod board_xxx.ko 
# ls /dev/xxxxxx_button* -l     // 查看设备节点 
crw-------    1 root     root      236,   0 Jan 18 08:57 /dev/xxxxxx_button0 
crw-------    1 root     root      236,   1 Jan 18 08:57 /dev/xxxxxx_button1 
# ./button_test /dev/xxxxxx_button0    // 读按键 
[  450.886180] /home/book/source/04_button_drv/01_button_drv_template/board_xxx.c board_xxx_button_init_gpio 28, init gpio for button 0 [ 
450.910915] 
/home/book/source/04_button_drv/01_button_drv_template/board_xxx.c 
board_xxx_button_read_gpio 33, read gpio for button 0 
get button : 1    // 得到数据 

14.5 课后怎业

合并 LED、BUTTON框架驱动程序:01_led_drv_template、01_button_drv_template,合并为:
gpio_drv_template

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/145850.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Oracle的递归公共表表达式

查询节点id为2的所有子节点的数据&#xff0c;包括向下级联 WITH T1 (id, parent_id, data) AS (SELECT id, parent_id, dataFROM nodesWHERE id 2UNION ALLSELECT t.id, t.parent_id, t.dataFROM nodes tJOIN T1 n ON t.parent_id n.id ) SELECT * FROM T1; --建表语句 C…

layui 树状控件tree优化

先上效果图&#xff1a; 我选的组件是这个&#xff1a; 动态渲染完后&#xff0c;分别在窗体加载完成&#xff0c;节点点击事件分别加入js&#xff1a; //侧边栏图标替换//layui-icon-subtraction$(function () {$(".layui-icon-file").addClass("backs&quo…

【HTML】表格行和列的合并

概述 当我们需要在 HTML 表格中展示复杂的数据时&#xff0c;行和列的合并可以帮助我们实现更灵活的布局和结构。通过合并行和列&#xff0c;我们可以创建具有更多层次和结构的表格&#xff0c;使数据更易于理解和分析。 在 HTML 表格中&#xff0c;我们可以使用 rowspan 和 …

普通用户在Linux下免密执行sudo命令,真的可以吗?

主旨 在linux的日常运维中&#xff0c;我们会发现&#xff0c;使用root用户的权限太大了&#xff0c;很多时候一不小心就删错了&#xff0c;而且恢复不回来&#xff0c;我们应该怎么避免呢&#xff1f; 我们可以使用普通用户进行服务器的登录&#xff0c;如果有权限不够的情况&…

C/C++跨平台构建工具CMake-----在C++源码中读取CMakeLists.txt配置文件中的内容

文章目录 1.需求描述2.需求准备2.1 创建项目2.2 编辑CMakeLists.txt文件2.3 编写C文件2.4 编译构建项目 3.需求实现3.1 在CMakeLists.txt中输出日志信息3.2 增加配置生成C头文件3.3在C 源码中访问配置的值3.4 C文件中读取CMakeLists.txt中的字符串 总结 1.需求描述 当我们开发…

HTML之如何下载网页中的音频(二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Kafka(一)使用Docker Compose安装单机Kafka以及Kafka UI

文章目录 Kafka中涉及到的术语Kafka镜像选择Kafka UI镜像选择Docker Compose文件Kafka配置项说明KRaft vs Zookeeper和KRaft有关的配置关于Controller和Broker的概念解释Listener的各种配置 Kafka UI配置项说明 测试Kafka集群Docker Compose示例配置 Kafka中涉及到的术语 对于…

Linux—进程间通信之System V共享内存

目录 简介System V共享内存特点及用法 共享内存的创建共享内存的关联与去关联共享内存的删除共享内存通信代码实现总结 简介 System V共享内存是一种在Unix-like系统中广泛使用的共享内存机制。它是基于System V IPC&#xff08;Inter-Process Communication&#xff0c;进程间…

SpringBoot整合阿里云OSS文件存储解决方案

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 &#x1f4d6;所属专栏&#xff1a;Sp…

毛玻璃态登录表单

效果展示 页面结构组成 通过上述的效果展示可以看出如下几个效果 底部背景有三个色块并且效果是毛玻璃效果登录表单是毛玻璃效果登录表单的周围的小方块也是有毛玻璃效果并且与登录表单有层次效果 CSS3 知识点 filter 属性backdrop-filter 属性绝对定位属性动画属性 底部背…

(高阶) Redis 7 第16讲 预热/雪崩/击穿/穿透 缓存篇

面试题 什么是缓存预热/雪崩/击穿/穿透如何做缓存预热如何避免或减少缓存雪崩穿透和击穿的区别?穿透和击穿的解决方案出现缓存不一致时,有哪些修补方案缓存预热 理论 将需要的数据提前加载到缓存中,不需要用户使用的过程中进行数据回写。(比如秒杀活动数据等) 方案 1.…

idea Springboot 校园助学贷款系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 校园助学贷款系统是一套完善的信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统 具有完整的源代码和数据库&…

Ubuntu服务器安全性提升:修改SSH默认端口号

在Ubuntu服务器上&#xff0c;SSH&#xff08;Secure Shell&#xff09;是一种至关重要的远程连接工具。它提供了一种安全的方式来远程连接和管理计算机系统&#xff0c;通过加密通信来确保数据的保密性和完整性。SSH协议广泛用于计算机网络中&#xff0c;用于远程管理、文件传…

网络-Ajax

文章目录 前言一、Ajax优点&#xff1a;缺点&#xff1a; 二、使用步骤XNLHttpRequest对象完整代码 总结 前言 本文主要记录Ajax技术的简介&#xff0c;以及用法。 一、Ajax Ajax是一组用于在Web浏览器和Web服务器之间进行异步通信的Web开发技术。 它代表着Asynchronous Java…

解决大模型行业落地三大挑战,华为云GaussDB向量数据库正式发布

随着AI大模型产品及应用呈现爆发式增长,新的AI时代已经到来。向量数据库可与大语言模型配合使用,解决大模型落地过程中的痛点,已成为企业数据处理和应用大模型的必选项。在近日举行的华为全联接大会2023期间,华为云正式发布GaussDB向量数据库。GaussDB向量数据库基于GaussD…

Android 使用Kotlin封装RecyclerView

文章目录 1.概述2.运行效果图3.代码实现3.1 扩展RecyclerView 3.2 扩展Adapter3.3 RecyclerView装饰绘制3.3.1 以图片实现分割线3.3.2 画网格线3.3.3空白的分割线3.3.4 不同方向上的分割线 3.4 使用方法 1.概述 在一个开源项目上看到了一个Android Kotlin版的RecyclerView封装…

Docker和Docker compose的安装使用指南

一&#xff0c;环境准备 Docker运行需要依赖jdk&#xff0c;所以需要先安装一下jdk yum install -y java-1.8.0-openjdk.x86_64 二&#xff0c;Docker安装和验证 1&#xff0c;安装依赖工具 yum install -y yum-utils 2&#xff0c;设置远程仓库 yum-config-manager --add-r…

26962-2011 高频电磁场综合水处理器技术条件

声明 本文是学习GB-T 26962-2011 高频电磁场综合水处理器技术条件. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了高频电磁场综合水处理器(以下简称处理器)的术语和定义、分类和型号、结构型式、 要求及检验、标志、包装和贮运…

Java | Maven(知识点查询)

文章目录 Maven知识速查1. Maven概述2. Maven的作用3. Maven的下载4. Maven的环境配置5. Maven 的基础组成5.1 Maven仓库5.1.1 本地仓库配置&#xff1a;5.1.2 中央仓库配置&#xff1a;5.1.3 镜像仓库配置 5.2 Maven坐标 6. Maven项目6.1 手工创建Maven项目6.2 自动构建项目 7…