嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十六)LED驱动程序框架

上周一位客户向我询问有关 LED 驱动器的问题。
它创建了一堆代码,但是在安装驱动程序时却显示了一条消息,即 versionmagic 不匹配,这非常烦人。
我只是觉得你越清楚越好,尤其是写驱动的时候,如果分几步来做,就不容易遇到问题了。

我们先来说一下字符设备驱动框架。
如果您想成为一名司机,您需要按照以下步骤操作:
1 .确定主设备号。
这件事一定要提前计划好,不能和别人冲突。
2 . 自定义一个file_operations结构体,里面应该填充各种操作函数。
3 .实现相应的打开、读取、写入功能并完成 4 .调用register_chrdev告诉内核你的操作 5 、必须有一个输入函数(如__init led_init),在驱动安装过程中会被内核调用。
6 、卸载驱动时调用对应的退出函数(__exit led_exit) 7 .记得改进,使用class_create和device_create自动创建设备节点
对于LED驱动,你想要哪个接口?比如用文件操作来控制LED的亮灭?这需要实现写函数来接收打开和关闭 LED 的命令。

如何支持多地图?这分为几层。
将驱动分为通用框架(leddrv.c)和具体硬件操作(board_X.c)。
例如,我在 2 02 3 年在上海的一个购物中心进行的项目就采用了这种多层次的方法。
led_operations结构体是抽象的,每个板子实现自己的硬件操作,并通过该结构体调用上层驱动程序。
看一下代码中定义的led_operations,他们将LED操作抽象为两个函数,init和ctl。

编写代码时,源代码位于01 _all_series_quickstart\05 _嵌入式Linux驱动开发基础知识\source\02 _led_drv\01 _led_drv_template目录下。
驱动程序分为两层:leddrv.c和board_demo.c。
leddrv.c负责记录file_operations,打开并写入它会调用board_demo.c中提供的led_opr中的相应函数。

首先看led_opr.h,它定义了led_operations结构体并总结了该结构体中的LED操作。
看到这个头文件,就可以立即编写board_demo.c框架,具体功能稍后实现。
头文件怎么写?参考Linux内核代码中类似的驱动或者使用open命令阅读系统手册。

leddrv.c的顶层是file_operations结构。
查看 __init led_init 函数。
第 8 8 行使用 register_chrdev 来注册驱动程序,第 1 02 行从下层检索 led_operations 结构。
再看一下file_operations中的成员函数。
第 4 9 行和第 6 0 行将调用 led_operations 中的函数。

我把完整的代码贴出来了,你看得懂吗?尤其是get_board_led_opr函数,我不确定它具体是做什么的,我得查一下。

ledtest.c测试程序也很简单。
第2 6 行打开设备节点,第3 7 或4 2 行写入值来控制LED。
测试的时候记得配置交叉工具链,修改Makefile中的内核源码路径,编译驱动,测试程序。
使用NFS将编译好的程序传输到开发板。
安装驱动后,使用 ls /dev/1 00ask_led 查看设备节点,然后使用 ./ledtest /dev/1 00ask_led0 打开 LED。

尝试一下。
如果您在安装驱动时仍然收到versionmagic不匹配的消息,请参阅文档末尾的常见问题解答,或者直接询问我,我会帮助您。

Linux platform设备驱动编写

开发Linux设备驱动程序,首先了解硬件,然后查看现有代码,自己编写结构,获取关键功能,安装模块,自动加载,最后调试看看效果。
设备分析、读取协议、系统定位、研究现有代码、构建基础设施、编写函数、安装模块、自动配置和调试。

【科普】linux驱动系列学习之DRM

DRM,全称Direct Rendering Manager,是Linux系统上非常常见的图形渲染环境。
与传统的 Framebuffer 相比,DRM 可以跟上现代硬件的步伐。
支持GPU、3 D渲染和显示功能,还可以管理GPU和显示驱动,使得软件架构统一,易于开发和维护。
这里我只讲一下显示。
我对GPU了解不够,无法详细解释这一点。
稍后我弄清楚后会添加更多。

DRM系统分为哪几部分?主要有三个:libdrm、KMS 和 GEM。
图 1 显示了 DRM 框架的框图。
libdrm 驻留在用户空间中,用于管理 DRM。
应用程序通过调用内核中的KMS和GEM来访问显示相关的资源。
KMS,Kernel ModeSetting,是DRM框架的重要组成部分。
其主要功能是设置和管理显示参数。
GEM,图形执行管理器,负责内存管理和DRM管理的释放。
这里我主要关注KMS和GEM。
测试硬件为stm3 2 mp1 5 7 (正点原子),系统为ubuntu1 8 .04
KMS模块,如图1 所示,主要负责展示相关功能。
在DRM中,KMS分为几个模块: Framebuffer是该层的渲染内容。
它与硬件无关,是一个基本元素。
CRTC从帧缓冲区中读取显示图像,然后以指定的格式输出到编码器。
主要功能是:设置适合显示器的分辨率、输出响应时间、扫描帧缓冲区然后在显示器上显示、更新帧缓冲区。
平面是一层。
实际的输出图像是几个图层的叠加,包括主图层和光标图层。
基础层、覆盖层和光标层分别由硬件加速模块生成,并且每一层都具有至少一个平面。
编码器将图像信号编码为特定的格式(如RGB、YUV等)转换为连接器所需的输出信号。
以HDMI为例,数据通过TMDS总线输出,编码任务由编码器执行。
连接器是连接到显示器的物理接口。
它负责访问设备并检索屏幕参数,包括 DP 和 HDMI。
Vblank,软硬件同步机制,RGB同步中的垂直消隐区域,软件通常通过硬件VSYNC实现。
属性:任何可以设置的参数都可以变成属性,这是DRM驱动程序中最灵活的部分。
以HDMI为例,SoC内部通常有一个显示模块,通过总线连接到HDMI接口。
显示模块对应CRTC,HDMI接口对应连接器,帧缓冲区对应显存的一部分,平面用于描述帧缓冲区,编码器将像素转换成HDMI接口所需的信号。
通常,编码器和连接器在初始化期间一起处理。

GEM主要负责显示缓冲区的分配和释放,包括钝性的、简单的和受限的。
Dumb 仅支持连续的物理内存,并且基于内核中的通用 CMAAPI 实现。
适用于分辨率较小、场景简单的情况。
主要用于简单的缓冲区显示,不需要GPU处理。
Prime 支持连续和非连续物理内存。
基于DMA-BUF机制,实现缓冲区共享,适用于复杂、内存密集型场景。
Fence是一种缓冲区同步机制,是基于内核的dma_fence机制实现的,用于防止显示内容时出现异步问题。

要实现KMS DRM驱动程序,通常需要实现以下代码和函数:fops、drm_driverdumb_create、fb_create、atomic_commitdrm_xxx_funcs、drm_xxx_helper_funcsdrm_xxx_init()、drm_xxx_helper_add()、drm_dev_init()、drm_dev_register()。
核心围绕七个对象,这些对象的创建和操作是关键。

Linux内核中的DRM结构比较复杂。
在这里我将介绍一些功能,但不是全部内容。
DMA-Buf之类的部分不在涵盖范围内,后续会根据情况进行更新。

linux驱动程序结构框架及工作原理分别是什么?

Linux设备驱动程序构成了内核和硬件之间的接口,负责硬件操作和数据传输。

字符设备、块设备和网络设备是Linux的三种主要设备文件类型。

字符设备和块设备的区别在于是否直接进行I/O操作。

设备文件有两个设备号。
主设备号标识驱动程序,次设备号区分同一驱动程序下的不同硬件。

当你编写驱动程序时,你需要填写file_operations结构并映射系统调用。

在该示例中,read_test函数处理read系统调用并将1 写入用户缓冲区。

write_test函数处理write系统调用并返回写入的字节数。

open_test和release_test函数处理open和release系统调用以实现模块计数。

建议将驱动程序编译成模块形式,以便于调试和卸载。

自己掂量一下。