
linux驱动开发
文章平均质量分 83
从内核模块开始,讲解Linux驱动开发
基础部分主要包括内核模块框架、字符设备驱动框架、IO内存操作、总线设备驱动模型、中断、同步互斥等。
高级部分主要包括一些常用外设驱动(如OLED、DTH11、HX1838等)、各种常用驱动框架(如IIC总线框架、input框架、USB框架等)
lf282481431
这个作者很懒,什么都没留下…
展开
-
12.5在Linux中编写队列模式的SPI控制器驱动
在Linux内核中更加推荐使用队列模式的SPI控制器驱动,而且队列模式的SPI控制器驱动也更加简单,只需要在驱动中实现单个spi_transfer的传输即可,将spi_message拆解为spi_transfer、片选GPIO控制、统计信息更新等均由SPI核心去完成。原创 2024-01-20 12:52:50 · 1092 阅读 · 0 评论 -
12.4在Linux中编写阻塞模式的SPI控制器驱动
用make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- dtbs -j8编译设备树,用新的.dtb文件启动系统。这里编写一个虚拟的SPI控制器驱动,通过printk来输出SPI控制器的工作状态。原创 2024-01-14 21:04:17 · 1071 阅读 · 0 评论 -
12.3在应用层使用SPI总线
在SPI总线驱动框架中提供了一个spidev 的字符设备驱动,在应用层可以通过它来访问SPI总线。原创 2024-01-14 13:12:42 · 695 阅读 · 0 评论 -
12.2内核空间基于SPI总线的OLED驱动
显存被分为8页、128列,要写某个字节时,需要先指定地址(哪页、哪列),然后写入1字节的数据。OLED上有128*64个像素(128列,64行),每个像素只有2种状态:亮、灭。OLED驱动程序基于SPI总线驱动框架和缓冲帧驱动框架编写,有关缓冲帧的内容参考。注意:没有MISO引脚,因为主控只能向OLED写数据,不能读取OLED的数据。SCL(D0):CLK 时钟 (高电平 2.2V~5.5V)SDA(D1):MOSI 数据(高电平 2.2V~5.5V)D/C:数据/命令(高电平 2.2V~5.5V)原创 2024-01-14 12:05:49 · 1000 阅读 · 0 评论 -
12.1SPI驱动框架
DO(MOSI):Master Output, Slave Input, SPI主控用来发出数据,SPI从设备用来接收数据DI(MISO) :Master Input, Slave Output, SPI主控用来发出数据,SPI从设备用来接收数据SCK: Serial Clock,时钟CS:Chip Select,芯片选择引脚。原创 2024-01-10 22:02:53 · 1084 阅读 · 0 评论 -
11.3编写Linux串口驱动
这里以一个虚拟串口为例来介绍串口驱动的编写,它在 proc 文件系统中创建了一个文件,通过向这个文件写入数据来模拟串口硬件的接收(写入数据时先将数据写入到虚拟串口接收FIFO中,然后调度工作队列,用以模拟串口中断处理函数来处理写入到虚拟串口接收FIFO中的数据),通过串口发送的数据会写入虚拟串口发送FIFO中,然后可以通过这个文件来读取虚拟串口发送FIFO中的数据,用于模拟串口硬件发送。中编写的串口回环用于程序。原创 2024-01-07 14:37:31 · 1757 阅读 · 0 评论 -
11.2 Linux串口驱动框架
注册 uart_driver 的本质就是注册 tty_driver ,只是这个 tty_driver 属于uart_driver ,且对应的的操作函数集合具体操作对象为 uart_driver ( uart_driver 继承于 tty_driver )。在 uart_driver 下添加 uart_port 的本质就是在其对应的 tty_driver 下添加 tty_port ,只不过事先通过 uart_state 将 uart_port 和 tty_port 进行了关联。且在内核配置选项中使能。原创 2024-01-05 23:56:06 · 1828 阅读 · 0 评论 -
11.1Linux串口应用程序开发
UART的全称是Universal Asynchronous Receiver and Transmitter,即异步发送和接收。原创 2023-12-25 22:04:49 · 1443 阅读 · 0 评论 -
10.3 uinput
uinput 是一个内核驱动,应用程序通过它可以在内核中模拟一个输入设备,其设备文件名是 /dev/uinput 或 /dev/input/uinput。原创 2023-12-24 20:03:13 · 711 阅读 · 0 评论 -
10.2多点触摸屏驱动
配置信息:其中配置信息的byte1~4表示触摸屏尺寸:产品ID:触摸坐标:虽然一共有10组触摸点坐标寄存器组,但是它最多支持同时跟踪5个触摸点。原创 2023-12-24 16:31:14 · 2044 阅读 · 0 评论 -
10.1Linux输入子系统介绍
鼠标、键盘、按键、触摸屏等提供输入支持的设备都属于输入设备,在Linux也提供了一套驱动框架“input 子系统”与之对应,用于抽象输入设备,并提供管理输入设备驱动和输入事件处理程序的功能。原创 2023-12-15 21:18:36 · 197 阅读 · 0 评论 -
9.5I2C适配器驱动
此章节利用GPIO模拟I2C时序实现一个I2C适配器驱动,有关I2C时序相关内容可以参考博文。原创 2023-12-07 21:23:05 · 112 阅读 · 0 评论 -
9.4在内核空间使用I2C总线
此章节以AP3216C驱动为例子演示如何在内核空间使用I2C总线。原创 2023-12-06 20:45:21 · 110 阅读 · 0 评论 -
9.3在应用层使用I2C总线
AP3216C集成了光强(Ambilent Light Sensor,ALS)、距离(Proximity Sensor,PS)和红外传感器(Infrared Radiation LED,IR),该芯片通过IIC接口与主控芯片交互。从原理图中可以看出AP3216C接在控制器的I2C5 I2C接口上,所复用的GPIO分别是PA11和PA12。原创 2023-11-19 20:34:56 · 547 阅读 · 0 评论 -
9.2I2C-Tools的移植和使用
I2C-Tools 是一套在应用层通过命令行访问 IIC 设备的命令集合,它基于 Linux 内核提供的 I2C-dev 驱动实现,源代码可在“https://mirrors.edge.kernel.org/pub/software/utils/i2c-tools/“下载。原创 2023-11-18 19:33:16 · 221 阅读 · 0 评论 -
9.1 I2C总线数据结构
在那条 I2C 总线下挂载设备就在那条总线的设备树节点下添加对应设备的子节点,节点命名规则“ [标签:]名称[@地址]”,节点内容必须包含 reg 属性和 compatible 属性, reg 属性用于描述设备地址, compatible 属性用于设备和驱动的匹配,如下是在 i2c5 中添加一个 ap3216c 设备节点的示例。I2C 设备可以使用i2c_transfer函数传输数据包,另外内核中页提供了其他的数据传输函数,不过基本都是基于i2c_transfer进行封装的。原创 2023-11-18 17:36:53 · 259 阅读 · 0 评论 -
8.2LCD-TFT显示控制器驱动 (LCD驱动)
LCD-TFT显示控制器 (LTDC)驱动。原创 2023-09-07 21:03:23 · 1762 阅读 · 0 评论 -
8.1缓冲帧(Framebuffer)驱动框架
【代码】8.1缓冲帧(Framebuffer)驱动框架。原创 2023-09-05 20:05:24 · 184 阅读 · 0 评论 -
7.3 虚拟GPIO驱动
GPIO控制器驱动的核心就是创建struct gpio_chip对象,并初始化其中内容,然后利用devm_gpiochip_add_data或gpiochip_add_data注册GPIO控制器驱动(它会在内部创建并注册一个struct gpio_devic对象)原创 2023-09-04 21:17:45 · 390 阅读 · 0 评论 -
7.2 GPIO子系统的数据结构
如果设备树没有提供 gpio-ranges 属性还可以通过 gpiochip_add_pin_range 等函数进行关联(实际上设备树增加gpio-ranges属性后,在注册GPIO控制器过程中便会自动会调用gpiochip_add_pin_range 函数)。原创 2023-09-02 23:10:51 · 157 阅读 · 0 评论 -
7.1使用Linux的GPIO驱动
引脚复用为 GPIO 功能后(可以通过 pinctrl 子系统配置,默认情况下 pinctrl 子系统会将引脚复用为 GPIO 模式),便可使用 GPIO 子系统提供的函数来控制引脚(大多数芯片厂家已经在 GPIO 子系统中实现了相应 GPIO 控制器的驱动,对于使用者可以不关心驱动实现), GPIO 子系统可方便驱动开发者使用 GPIO ,驱动开发者在设备树中添加 GPIO 相关信息后就可以在驱动程序中使用 GPIO 子系统提供的 API 函数来操作 GPIO。原创 2023-08-29 20:59:48 · 717 阅读 · 0 评论 -
6.3 虚拟pinctrl驱动
Pinctrl子系统主要有三大作用,分别是引脚枚举与命名(获取单个引脚或引脚组、设备树解析等)、引脚复用功能配置(比如用作GPIO、I2C或其他功能)、引脚电气特性配置(比如上拉、下拉、open drain、驱动强度等)原创 2023-08-02 21:26:40 · 139 阅读 · 0 评论 -
6.2 pinctrl子系统的数据结构
pinctrl 框架分为两个部分,分别是引脚复用控制器 pinctrl_dev 和使用引脚的 pinctrl client。pinctrl_dev :提供服务,可以用它来复用引脚、配置引脚pinctrl client :使用服务,即使用 Pinctrl 系统的设备。原创 2023-08-01 21:54:15 · 164 阅读 · 0 评论 -
6.1 Pinctrl子系统的使用
pinctrl 子系统即引脚配置子系统,它从设备树获取引脚配置信息,并完成对引脚复用功能和电气特性的配置,如下是一个MPU框图的一部分,其中包括IIC、UART、GPIO等外设,这些外设共用外部的引脚,而引脚在同一时刻只能有一种功能,所以此时需要配置引脚复用控制器,决定引脚给那个外设使用,此外在不同的应用场合还对引脚的电气特性有不同的要求,此时还需要配置引脚的电气特性控制器(在STM32MP157中将GPIO控制器、引脚复用功能配置、引脚电气特性配置打包为了一个外设模块,叫做GPIO外设)原创 2023-08-01 20:52:08 · 229 阅读 · 0 评论 -
5.5 hierarchy中断控制器驱动
legacy类型的中断控制器是一个一对一的中断控制器,它注册在注册时需要指定其父中断控制器,父中断控制器的中断号与其对应的子中断控制器的中断号共用一个irq_desc。原创 2023-07-31 21:45:14 · 111 阅读 · 0 评论 -
5.4 linear中断控制器驱动
linear类型中断控制器与legacy类型的中断控制器一样,都是一个一对多的中断控制器,但是linear类型中断控制器是在第一次进行中断映射时才创建相应的irq_desc,相比于legacy类型的中断控制器再注册之前在系统中分配相应的irq_desc的方案而言更节省系统资源。原创 2023-06-28 20:27:03 · 211 阅读 · 0 评论 -
5.3 legacy中断控制器驱动
legacy类型的中断控制器是一个一对多的中断控制器,他在注册之前需要实现在系统中分配相应的irq_desc。原创 2023-06-18 16:19:33 · 412 阅读 · 0 评论 -
5.2Linux中断系统中的重要数据结构
irq_desc 对象用于描述中断源,在Linux内核中有一个 irq_desc 数组,对于每一个硬件中断源,都有一个对应的数组项(如果内核配置了CONFIG_SPARSE_IRQ,那么它就会用基数树(radix tree)来代替irq_desc数组,以减少对内存的开销。原创 2023-06-18 12:41:35 · 259 阅读 · 0 评论 -
5.1在Linux中使用中断
对于大多数总线设备内核都会解析设备树中描述的中断信息,在驱动中可以获得相应的中断号,如 iic 设备可以通过i2c_client 的 irq 成员获取中断, spi 设备可以通过 spi_device 的 irq 成员获取中断(平台设备在匹配过程中不会解析设备树中的中断信息,但是可以通过 platform_get_irq 或 platform_get_irq_byname 获取中断)43. interrupts :描述节点的中断信息,包括中断类型、中断号、触发方式等,具体含义与中断控制器相关。原创 2023-06-16 22:11:42 · 531 阅读 · 0 评论 -
4.2并发和竞争
【代码】4.2并发和竞争。原创 2023-06-05 22:07:38 · 70 阅读 · 0 评论 -
4.3原子操作
原子操作是指整个操作过程不可被拆分或者不会被打断,因此不需要考虑并发竞争问题,在 ARMV6 及以下架构中采用关中断实现,在 ARMV6 以上架构中采用 ldrex 和 strex 指令实现,如下是采用 ldrex 和 strex 指令实现的 atomic_add 函数。原创 2023-06-05 21:49:39 · 151 阅读 · 0 评论 -
4.1内联汇编
目前编译器都比较智能,能将 C 代码转换为高效率的汇编指令,但是对于某些特殊指令(如 ldrex 、 strex 实现互斥访问)或特殊算法编译器则无法正常转换,此时则需要使用汇编来实现相应的功能,如果不想创建单独的汇编文件则需要采用在C语言中嵌入汇编指令的方式来实现。原创 2023-06-05 21:21:03 · 1269 阅读 · 0 评论 -
3.4 平台总线与设备树
改进而来,主要删除了platform_device描述,增加了设备树修改内容。在顶层设备树根节点中加入如下节点。这个LED平台驱动基于。完整的驱动代码可以从。原创 2023-06-04 21:35:21 · 149 阅读 · 0 评论 -
3.3设备树
在总线设备驱动框架中实现了设备和驱动的分离,但是依然需要使用C代码来描述设备,而且还体现不出设备之间的层次关系。为了解决这个问题提,Linux引入了设备树,设备树是一种描述设备信息的数据结构(是一种树状的数据结构),它可以被bootloader传递到内核,从而让内核获得相应的硬件信息,在内核的sys/firmware/devicetree/base目录中可以查看设备树的节点信息(包括设备树中的各个节点)原创 2023-06-04 20:38:17 · 232 阅读 · 0 评论 -
3.2平台设备驱动
上一章节介绍的总线、设备、驱动框架可以很好的实现设备和驱动的分离,降低设备和驱动之间的耦合性,但是在Linux中存在许多没有实际物理总线的设备,如led、按键等,为了方便这些设备使用总线、设备、驱动框架,Linux就提供了platform(平台)总线,platform(平台)总线是一条虚拟总线,其目的是为了让没有具体物理总线的设备能够使用总线、设备、驱动框架。原创 2023-06-03 11:52:42 · 179 阅读 · 0 评论 -
3.1总线、设备、驱动框架
如下是USB总线的示意图,USB总线上可以连接各种各样的USB设备,为了让这些设备能正常工作,系统又再USB总线上注册个各种各样的设备驱动,当一个设备接入USB总线,USB总线会根据设备信息去遍历注册到USB总线上的驱动,然后找到一个与设备匹配的驱动,并将其于设备绑定,用于驱动设备。原创 2023-05-31 21:06:26 · 258 阅读 · 0 评论 -
2.9 字符设备驱动之异步通知
异步通知类似于硬件上的中断,它是在软件层面对硬件中断一种模拟,当设备可用(可执行读写等操作)时驱动向应用层发送信号,应用程序收到信号后根据信号进行相应的处理。原创 2023-05-29 21:45:07 · 112 阅读 · 0 评论 -
2.10字符设备驱动之内存映射(mmap实现)
有些驱动在使用时需要频繁的操作内核空间的某一片内存(如显示屏驱动,需要频繁的读写显存),若采用传统的read和write会存在大量的内存拷贝(因为用户空间无法直接访问内核空间的地址),这将降低程序效率,此时可以将内核空间虚拟地址所对应的物理内存映射到用户空间,以此减少内存拷贝。原创 2023-05-30 21:33:31 · 1196 阅读 · 0 评论 -
2.8字符设备驱动之poll
多路复用即同时等待多个IO,当某些IO发生相应的事件后则对其进行对应的操作。原创 2023-05-21 16:11:15 · 119 阅读 · 0 评论 -
2.7字符设备驱动之阻塞式IO和非阻塞式IO
当设备资源不可用时驱动立即返回,错误码通常是 -EAGAIN(表示资源不可用,错误码类型没有规定),当驱动文件采用非阻塞式方式打开后 structfile 的 f_flags 成员的 O_NONBLOCK 标志会置位。原创 2023-05-21 14:22:26 · 201 阅读 · 0 评论