Linux驱动开发笔记

news2024/12/23 17:58:10

疑问
file_operation中每个操作函数的形参中inode的作用

设备树中compatible属性中厂商和型号如何填写

file_operation定义了Linux内核驱动的所有的操作函数,每个操作函数与一个系统调用对应,对于字符设备来说,常用的函数有:llseekreadwritepool等等,这些操作函数都要需要完成实现。

为实现“高内聚,低耦合”的软件设计理念,Linux驱动采用了内核加载的方式,将驱动编译成模块(Linux 下模块扩展名为.ko),在Linux 内核启动以后使用“insmod”命令加载驱动模块,用“rmmod”命令卸载具体驱动模块,相应地需要注册模块加载函数和模块卸载函数。

module_init(xxx_init); //注册模块加载函数
module_exit(xxx_exit); //注册模块卸载函数

对于字符设备驱动而言,当驱动模块加载成功以后需要注册字符设备,同样,卸载驱动模块的时候也需要注销掉字符设备。输入命令“cat /proc/devices”可以查看当前已经被使用掉的设备号

wangchenxiao@sdc-uvdise057:~$ cat /proc/devices
Character devices:
  1 mem
 ····
Block devices:
  2 fd
 ····

Linux 中每个设备都有一个设备号,设备号由主设备号次设备号两部分组成,主设备号表示某一个具体的驱动,次设备号表示使用这个驱动的各个设备,设备号由dev_t数据类型描述,是一个32位的数据类型,中高 12 位为主设备号,其范围为 0~4095,所低 20 位为次设备号
Linux中每个设备号是独一无二的,申请新的设备号不能与已有的设备号重复,为避免冲突,使用alloc_chrdev_regiond unregister_chrdev_region动态申请和注销设备号

1.使用insmodmodprobe加载驱动模块。可以通过lsmod查看当前系统中存在的模块,模块加载后会注册设备,然后可以通过cat /proc/devices查看当前系统中存在的设备。
2.使用mknod创建设备对应的设备节点文件。通过ls /dev查看当前系统中的设备节点文件。设备节点文件是设备在用户空间中的实现,在应用程序中可以通过设备节点文件操作该设备。
3.不再使用该设备后,通过rmmod卸载设备。

MMU(内存管理单元)完成虚拟内存到物理内存的映射和内存保护的功能。可以通过ioremap完成物理内存地址到虚拟内存地址的映射,相应在卸载内存时需要通过unremap释放虚拟内存的映射,在获得指向虚拟内存地址的指针后,可以通过readbreadwreadlwritebwritewwritel对内存进行读写操作

pinctrl和gpio子系统

疑问:

用途:在裸机驱动开发中,设备的引脚和gpio通过设置相应的寄存器进行配置,在Linux驱动开发中引入了pinctrl和gpio子系统,通过在设备树中添加节点并完成引脚复用,电气等相应属性的配置,即可在驱动程序中通过提供的API函数完成引脚和gpio驱动的开发工作。

在设备树的外设节点下创建pinctrl节点,例如

pinctrl_led: ledgrp {
 fsl,pins = <
  MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0 /* LED0 */
 >;
};

fsl,pins属性通过宏定义MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 将GPIO1_IO03复用为GPIO1_IO03,并设置电气属性为0X10B0。

再设备树的根节点下创建gpio对应的外设节点

gpioled {
#address-cells = <1>;
#size-cells = <1>;
compatible = "atkalpha-gpioled";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_led>;
led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
status = "okay";
}

pinctrl-0属性设置了该节点对应的pintrcl节点,led-gpio属性设置了该设备对应的gpio节点信息,通过该属性可以获得GPIO编号

在驱动文件中
在设备结构体中定义GPIO编号
在初始化函数中根据of_find_node_by_path获得设备节点,通过of_get_named_gpio获得设备gpio编号,设置gpio输出输入属性
在写入函数中,通过gpio_set_value设置gpio的输出值。

Linux并发与竞争

原子变量:该变量的赋值和读取为原子操作
自旋锁:加锁后其他线程无法访问临界区,会处于忙等状态,因此适用于临界区耗时不长的场景。
信号量/互斥体:其他线程无法访问临界区时会进入休眠状态,进行上下文切换,适用于临界区较为耗时的场景。
同时只允许一个进程打开设备
通过在设备结构体中设置原子变量,初始化时设置该设备的原子变量为1,打开设备时原子变量减一,并判断是否小于零,若小于零则打开失败,关闭设备时原子变量加一。
在设备结构体中定义整形变量表示该设备是否使用,并定义自旋锁保护该变量,在初始化函数中初始化自旋锁,在打开设备时变量加一,如果变量大于零打开失败,关闭设备时变量减一,注意在对变量进行读写时需要通过自旋锁进行保护。
在设备结构体中定义信号量,在初始化函数中初始化信号量为1,在打开函数中获取信号量,若此时信号量为0则打开失败,在关闭函数中释放信号量。
在设备结构体中定义互斥体,在设备初始化函数中初始化互斥体,在打开设备函数中获取互斥体,如果获取互斥体失败则打开文件失败,在关闭函数中释放互斥体。

Linux内核定时器

Linux通过硬件定时器湖区时钟源,该时钟源的频率被称为系统频率或节拍率,该频率可以在编译LInux内核的时候设置。Linux 内核使用全局变量 jiffies 来记录系统从启动以来的系统节拍数,系统启动的时候会将 jiffies 初始化为 0
在设备结构体中定义timer_list定时器结构体,在初始化函数中初始化定时器,添加超时时间和处理函数,并注册定时器,开始定时功能,在关闭函数中删除定时器。

Linux中断

裸机中断系统?
设备树中通过interrupt-parent指定相应的gpio中断控制器,通过interrupts设置引脚号和中断出发标志。gpio中断控制器节点中,通过interrupts设置该gpio中断源信息
在驱动文件的设备结构体中定义中断IO描述结构体,其中包含gpio、终端号、中断服务函数,名字等信息。通过of_get_named_gpio提取gpio号,然后根据irq_of_parse_and_map从设备树中获取中断号,完成中断处理函数后,通过request_irq完成中断的申请。在关闭函数中,释放中断号

阻塞和非阻塞IO

当应用程序对设备驱动进行操作的时候,如果不能获取到设备资源,那么阻塞式 IO 就会将应用程序对应的线程挂起,直到设备资源可以获取为止。对于非阻塞 IO,应用程序对应的线程不会挂起,它要么一直轮询等待,直到设备资源可以使用,要么就直接放弃,设备驱动文件的默认读取方式就是阻塞式的,若要通过非阻塞方式打开,则需要再open函数中传入O_NONBLOCK

通过等待队列实现阻塞IO
在设备结构体中添加等待队列头结构体

平台设备驱动

在Linux内核中包含了大量驱动代码,因此必须提高驱动的可重用性。
驱动的分离:采用驱动、总线、设备信息模型,将设备信息从设备驱动中剥离开来,驱动使用标准方法去获取到设备信息,后根据获取到的设备信息来初始化设备,即于驱动只负责驱动,设备只负责设备,想办法将两者进行匹配即可。
在这里插入图片描述
驱动的分层:分层的目的也是为了在不同的层处理不同的内容。
定义platform_driver结构体,在其中设置驱动名称name,表示/sys/bus/platform/drivers/目录下的驱动名称,设备树匹配表of_match_table,用于和设备树中的compatible属性匹配,probe函数用于设备和驱动完成匹配时的执行,remove函数。
在初始化函数中通过platform_driver_register注册platform_driver结构体,在卸载函数中通过platform_driver_unregister卸载platform_driver结构体,
在probe函数中完成初始化,在remove函数中完成卸载。

misc驱动

misc为杂项驱动,主设备号为10。misc_register会完成申请设备号、初始化cdev、添加cdev、创建类、创建设备等操作,misc_registe会完成删除cdev、注销设备号、删除设备、删除类等操作

input子系统

Linux为输入设备创建的框架,统分为 input 驱动层、input 核心层、input 事件处理层。
在这里插入图片描述
首先在设备结构体定义一个input_dev指针,然后通过 input_allocate_device函数申请一个input_dev结构体,然后设置该结构体的名称,事件类型和事件值,然后通过input_register_device向Linux内核注册结构体,卸载驱动模块时需要通过input_unregister_deviceinput_free_device注销和删除设备。然后向input_eventLinux上报事件

LCD
驱动文件基本无需更改,可以在设备树中修改相应的参数

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

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

相关文章

【Vue.js】使用Element中的Mock.js搭建首页导航左侧菜单---【超高级教学】

一&#xff0c;Mock.js 1.1 认识Mock.js Mock.js是一个用于前端开发中生成随机数据、模拟接口响应的 JavaScript 库。模拟数据的生成器&#xff0c;用来帮助前端调试开发、进行前后端的原型分离以及用来提高自动化测试效率 总结来说&#xff0c;Element中的Mock.js是一个用于…

数据安全态势管理:什么是事实,什么是虚构?

考虑到组织存储大量数据的日益复杂的云环境&#xff0c;数据安全态势管理 ( DSPM )的兴起并不令人意外。使组织能够全面了解云数据资产和敏感数据的安全状况的流程对于当今的安全团队来说非常有价值。 尽管 DSPM 的重要性日益凸显&#xff0c;但人们对于它能为企业做什么和不能…

Qt中额外复制新类到工程中出现无法解析的外部符号

无法解析的外部符号 “public: virtual struct QMetaObject const * __cdecl FormCloudFilter::metaObject(v 错误原因&#xff1a;在C项目中&#xff0c;新添加了类之后&#xff0c;编译出现错误&#xff0c;原因是我们新添加的类未被Qt编译成moc文件。 解决方法&#xff1a; …

SpringCloud 学习(三)Ribbon 和 Feign

4. Netflix.Ribbon 4.1 简介 (1) 概念 Spring Cloud Ribbon 是基于 Netflix Ribbon 实现的一套客户端负载均衡工具。 (2) 负载均衡&#xff08;LB&#xff1a;LoadBalance&#xff09;和集群架构 应用集群&#xff1a;将同一应用部署到多台机器上&#xff0c;组成处理集群&…

文档升级 | iTOP-RK3568开发板ADB工具的安装和使用

iTOP -RK3568开发板使用手册更新&#xff0c;后续资料会不断更新&#xff0c;不断完善&#xff0c;帮助用户快速入门&#xff0c;大大提升研发速度。 《iTOP-3568开发板ADB使用手册》进行了文档升级&#xff0c;对ADB工具的安装和使用进行了更全面的步骤介绍。 第1章 安装adb工…

git revert 撤销之前的提交

git revert 用来撤销之前的提交&#xff0c;它会生成一个新的 commit id 。 输入 git revert --help 可以看到帮忙信息。 git revert commitID 不编辑新的 commit 说明 git log 找到需要撤销的 commitID &#xff0c; 然后执行 git revert commitID &#xff0c;会提示如下…

DataGrip初始化设置

DataGrip初始化设置 自定义设置 具体配置项 Customize —> Allsettins… 外观 退出IDE之前无需确认 启动IDE自动打开之前的项目 Appearance & Behavior —> System Settings —> Confirm before exiting the IDE Appearance & Behavior —> System Settin…

写一个Chrome浏览器插件(manifest v3)

目录 1、创建manifest.json 文件 2、开始写popup页面以及对应的逻辑。 2.1 popup 页面 2.2 后台运行 background.js 2.3 content.js 2.4 popup页面的js文件 3、chrome 浏览器加载本项目 4、参考文档 1、创建manifest.json 文件 首先需要在项目的根目录下创建manifes…

深入剖析Redis系列- Redis数据结构之哈希

1.11.5哈希类型(hash) Redis的hash 是一个string类型的key和value的映射表&#xff0c;这里的value是一系列的键值对&#xff0c;hash特别适合用于存储对象。 哈希类型的数据操作总的思想是通过key和field操作value&#xff0c;key是数据标识&#xff0c;field是域&#xff0c;…

基于SSM+Vue的舞蹈网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

大二上Redis学习笔记

redis非关系型数据库NOSQL&#xff0c;用c语言编写的,基于内存的数据库&#xff0c;每秒支持十几万的读写操作&#xff0c;性能远超数据库&#xff0c;还支持集群、分布式、主从同步等配置。 Redis基本功能 1 发布订阅系统 2 地图信息分析 3 计时器和计数器 redis运行的图形界…

【腾讯云TDSQL-C Serverless 产品体验】使用 Python向TDSQL-C添加读取数据实现词云图

关于TDSQL-C Serverless介绍 TDSQL-C 是腾讯云自主研发的新一代云原生关系型数据库。 它融合了传统数据库、云计算和新硬件技术的优势,100%兼容 MySQL,为用户提供具有极致弹性、高性能、高可用性、高可靠性和安全性的数据库服务。 TDSQL-C 实现了超过百万每秒的高吞吐量,支持…

SpringCloud 学习(四)Hystrix

6. Netflix.Hystrix 6.1 简介 ● 扇出 多服务之间调用&#xff0c;若微服务 A 调用微服务 B 和微服务 C&#xff0c;微服务 B 和 微服务 C 又调用其他微服务&#xff0c;这就是扇出 ● 服务雪崩 若扇出的链路上某个微服务的调用响应时间过长或者不可用&#xff0c;么此扇出…

ESP32在CAN(TWAI)波特率不同时收发数据,导致总线错误无法恢复

问题描述&#xff1a; 总线上有两个设备&#xff0c;主机&#xff1a;100ms周期发送数据。从机&#xff1a;以不同波特率发送数据&#xff0c;再把从机波特率调节至主机波特率一致无法通信。 环境&#xff1a;VSCODE IDF-v5.0 问题分析&#xff1a; 我们先看下ESP32技术参…

Spring 学习(四)注解实现自动装配及注解开发

1. 注解实现自动装配 JDK 1.5 开始支持注解&#xff0c;Spring 2.5 开始支持注解。 使用须知 导入约束 配置注解的支持&#xff08; <context:annotation-config/> &#xff09; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns&qu…

2023微信头像生成小程序,国庆头像生成,基于skyline+vue3+t

微信头像生成小程序&#xff0c;基于skylinevue3t该项目已适配微信小程序隐私政策&#xff0c;截图、获取头像等诸多新的接口 如何使用&#xff1a; 将代码导入到HBuilderX开发工具&#xff0c; 可无需修改任何代码&#xff0c;运行并编译到微信开发者工具 skyline需要使用微…

layui中使用JavaScript监听下拉框(select)的变化,根据选中的值来决定是否显示或隐藏input元素

HTML代码 <div class"layui-form-item" id"rubric"><label class"layui-form-label">前端说明</label><div class"layui-input-inline"><input type"text" id"user_rubric" name"…

页面添加遮罩层

1.css代码 // 子绝父相.self-check-tag {display: inline-block;min-width: 132px;height: 32px;position: relative;.overlay {position: absolute;top: 0;left: 0;width: 100%;height: 100%;background-color: gray;opacity: 0.1;}2.效果

QT windows dpi变化导致的界面异常处理

问题&#xff1a;已经在UI界面中利用布局设计好界面&#xff0c;但是运行程序后显示的界面出现错乱&#xff0c;而且在做出一些修改后重新构建&#xff0c;运行时界面无变化。 目录 一、解决UI设计界面与运行时显示界面不一致的问题 1、导致该现象的原因有&#xff1a;显示屏…

[Linux] 3.Linux下编码和执行文件

Ctrl Alt T快捷键调出命令终端 输入xrandr指令把现有的电脑分辨率列出来 &#xff0c;xrandr -s 分辨率可以调节至想要的分辨率 调节字体大小&#xff1a;Ctrl Shift “”或Ctrl Shift “-” 使字体变大变小 拖动窗口右下角可调节窗口大小 Ctrl “L”清屏 编写C代码文件:…