Linux驱动开发(十五)---如何使用内核现有驱动(显示屏)

这篇具有很好参考价值的文章主要介绍了Linux驱动开发(十五)---如何使用内核现有驱动(显示屏)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前文回顾

《Linux驱动开发(一)—环境搭建与hello world》
《Linux驱动开发(二)—驱动与设备的分离设计》
《Linux驱动开发(三)—设备树》
《Linux驱动开发(四)—树莓派内核编译》
《Linux驱动开发(五)—树莓派设备树配合驱动开发》
《Linux驱动开发(六)—树莓派配合硬件进行字符驱动开发》
《Linux驱动开发(七)—树莓派按键驱动开发》
《Linux驱动开发(八)—树莓派SR04驱动开发》
《Linux驱动开发(九)—树莓派I2C设备驱动开发(BME280)》
《Linux驱动开发(十)—树莓派输入子系统学习(红外接收)》
《Linux驱动开发(十一)—树莓派SPI驱动学习(OLED)》
《Linux驱动开发(十二)—树莓派framebuffer学习(改造OLED)》
《Linux驱动开发(十三)—USB驱动HID开发学习(鼠标)》
《Linux驱动开发(十四)—USB驱动开发学习(键盘+鼠标)》
继续宣传一下韦老师的视频

linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341

70天30节Linux驱动开发快速入门系列课程【实战教学、技术讨论、直播答疑】

linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
内核中目前存在了大量的设备驱动,如何能够快速利用起来,也是驱动工程师需要掌握的,毕竟人家都写好了,再从头去写,何苦呢?
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341

本章目的

如果我们需要在自己的linux设备上增加一个外设,例如一个屏幕,一个键盘,首先要想到的不是去写驱动,而是看一下系统有没有带驱动。例如这块SPI的TFT屏幕,驱动芯片是ili9341。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
都是学习单片机遗留下来的东西,现在学驱动又能玩一波了。

寻找驱动

那么首先要在内核中查询是否有该芯片的屏幕驱动。通过在menuconfig中搜索关键词ili9341,我们就发现了它本身已经动态编译了ili9341的fb驱动,并且是支持framebuffer的。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
进入开发板看一下,连我们之前开发的ssd1306的驱动都存在了。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
不过不要觉得写驱动就没有意义了,写驱动一方面能够将单片机的知识应用到linux上,熟悉驱动的逻辑架构,还能够让你更快速的了解一个别人写好的驱动。万一遇到bug,也知道从哪里入手。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341

设备树

既然驱动已经存在了。那么按照总线设备驱动模型,要想正常工作,就需要增加设备信息,提供给驱动使用,才能完成设备的驱动。
那么这个设备树如何编写,两个思路,

  • 参考已有的设备树中别人怎么写的
  • 查看内核的设备树文档了。
    来查找一下有没有介绍文档
root@ubuntu:/home/pgg/shumeipai/linux/Documentation# find ./ -name "*ili9341*"                                  
./devicetree/bindings/display/ilitek,ili9341.txt
./devicetree/bindings/display/panel/ilitek,ili9341.yaml

发现了描述文档《ilitek,ili9341.txt》,内容如下,告诉了你它是一个SPI模式控制器,需要三个关键参数,
compatile,dc-gpios和rest-gpios,还有一个例子。

linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
多么的贴心
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341

那么我们就按照这个来尝试一下修改设备树。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
然后更新一下设备树。结果发现屏幕亮,但是手动加载驱动没有任何反应,打印信息中也没有看到。
在/sys/bus/spi/devices/中没有发现任何spi设备。
怀疑设备树有问题。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341

于是发现了一个对于新手来说很重要的设备树配置

status = "okay";

在增加了这条语句之后,重新编译设备树,发现了错误提示,原来刚才根本就没有编译上这个设备

root@ubuntu:/home/pgg/shumeipai/linux# ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make dtbs
  DTC     arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dtb
arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts:222.13-231.4: ERROR (phandle_references): /soc/spi@7e204000/myili9341@0: Reference to non-existent node or label "gpio0"

arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts:222.13-231.4: ERROR (phandle_references): /soc/spi@7e204000/myili9341@0: Reference to non-existent node or label "gpio0"

arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts:222.13-231.4: ERROR (phandle_references): /soc/spi@7e204000/myili9341@0: Reference to non-existent node or label "backlight"

重新修改设备树
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
再次更新设备树。能够看到spi设备了

root@raspberrypi:/home/pgg# ls /sys/bus/spi/devices/
spi0.0

linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341

连接硬件

然后按照引脚接好电路,和之前的oled小屏幕是一样的。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
重启设备。驱动会自动根据设备树里面的描述进行加载。直接就能显示桌面了!真是个小惊喜。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
直接就启动了。然后插上usb鼠标,加载上自己的驱动。走你!没毛病

linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341

OLED同理

之前我们的OLED是SPI的oled,还有一部分相同芯片ssd1306采用的是iic通讯,那么我们同样可以找到相关的驱动
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
以及搜索到相关的设备树范例:
Documentation\devicetree\bindings\display\ssd1307fb.txt
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
改天试一下这个驱动,感觉要比自己写的,用起来更踏实呢。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341

学习源码

在drivers\staging\fbtft路径下,我们可以看到针对大量显示屏的驱动源码,这里采用了一个框架,每一种屏幕驱动,有一个私有的文件例如fb_ili9341.c,中间围绕这一个结构体进行特殊配置

static struct fbtft_display display = {
	.regwidth = 8,
	.width = WIDTH,
	.height = HEIGHT,
	.txbuflen = TXBUFLEN,
	.gamma_num = 2,
	.gamma_len = 15,
	.gamma = DEFAULT_GAMMA,
	.fbtftops = {
		.init_display = init_display,
		.set_addr_win = set_addr_win,
		.set_var = set_var,
		.set_gamma = set_gamma,
	},
};

每个屏幕差异的操作,由fbtftops结构中的函数来定义,结构中的函数会有默认操作。

struct fbtft_ops {
	int (*write)(struct fbtft_par *par, void *buf, size_t len);
	int (*read)(struct fbtft_par *par, void *buf, size_t len);
	int (*write_vmem)(struct fbtft_par *par, size_t offset, size_t len);
	void (*write_register)(struct fbtft_par *par, int len, ...);

	void (*set_addr_win)(struct fbtft_par *par,
			     int xs, int ys, int xe, int ye);
	void (*reset)(struct fbtft_par *par);
	void (*mkdirty)(struct fb_info *info, int from, int to);
	void (*update_display)(struct fbtft_par *par,
			       unsigned int start_line, unsigned int end_line);
	int (*init_display)(struct fbtft_par *par);
	int (*blank)(struct fbtft_par *par, bool on);

	unsigned long (*request_gpios_match)(struct fbtft_par *par,
					     const struct fbtft_gpio *gpio);
	int (*request_gpios)(struct fbtft_par *par);
	int (*verify_gpios)(struct fbtft_par *par);

	void (*register_backlight)(struct fbtft_par *par);
	void (*unregister_backlight)(struct fbtft_par *par);

	int (*set_var)(struct fbtft_par *par);
	int (*set_gamma)(struct fbtft_par *par, u32 *curves);
};

函数意义

函数 意义
write 写入接口总线
read 从接口总线读取
write_vmem 将视频内存写入显示
write_reg 写入控制器寄存器
set_addr_win 设置GRAM更新窗口
reset 重置LCD控制器
mkdirty 标记要更新的显示行
update_display 更新显示
init_display 初始化显示
blank 空白显示(可选)
request_gpios_match Do pinname to gpio匹配
request_gpios 从内核请求gpios
free_gpios 释放以前请求的gpios
verify_gpios 验证是否存在必要的gpios(可选)
register_backlight 用于注册背光设备(可选)
unregister_backlight 取消注册背光设备(可选)
set_var 使用诸如@rotate和@bgr的变量值配置LCD(可选)
set_gamma 设置gamma曲线(可选)

框架有四个核心的文件
fbtft-core.c
fbtft-bus.c
fbtft-io.c
fbtft-sysfs.c
愿意了解的可以去解读一下。

总结思路

使用第三方驱动外设步骤:

  1. 查找关键驱动并启用
  2. 查找相关设备树资料
  3. 修改设备树
  4. 编译更新设备树和内核

现在的内核驱动库相当丰富,大部分常用的外设都能找到相关的驱动。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341

结束语

昨晚一夜没睡好,其实大家心里都憋着一股火气,各种抱怨的声音充斥着微信群,朋友圈。正所谓是爱之深,责之切,不过有些事,并不是头脑一热,就能够干的。处理这些危机,靠的也得是冷静的头脑。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341
无论是什么统,那都是内部矛盾,最后容易受伤的还是普通人。
所以要深刻认识到,谁才是真正的坏人。
不过坏人也干了一件好事,你能去,那我也能去咯,我离得近,还能天天去。日久天长,我就不走了。
linux 显示驱动,linux知识,驱动开发,操作系统,驱动开发,linux,树莓派,tft屏幕,ili9341文章来源地址https://www.toymoban.com/news/detail-608692.html

到了这里,关于Linux驱动开发(十五)---如何使用内核现有驱动(显示屏)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • linux驱动开发:Linux 内核的一些函数

    1 、 MKDEV ( ma, mi ) 构造设备号,将主设备号和次设备号转换为设备号类型(dev_t)。 MKDEV 宏将主设备号( ma )左移 20 位,然后与次设备号( mi )相与,得到设备号。 dev_t 结构 主设备号 12 位

    2024年02月17日
    浏览(41)
  • PyTorch入门学习(十五):现有网络模型的使用及修改

    目录 一、使用现有网络模型 二、修改现有网络模型 一、使用现有网络模型 PyTorch提供了许多流行的深度学习模型,这些模型在大规模图像数据集上进行了预训练。其中一个著名的模型是VGG16。下面是如何使用VGG16模型的示例代码: 在上述代码中,使用 torchvision.models.vgg16 来加

    2024年02月05日
    浏览(35)
  • 怎么降低Linux内核驱动开发的风险?

    降低Linux内核驱动开发的风险是一个重要的目标,因为内核驱动开发可能会对系统的稳定性和安全性产生重要影响。以下是一些降低风险的建议: 1. 深入了解Linux内核:在开始内核驱动开发之前,建议深入学习Linux内核的工作原理和架构,包括内核模块、设备模型、调度机制等

    2024年02月08日
    浏览(36)
  • <Linux开发>驱动开发 -之-内核定时器与中断

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

    2024年02月08日
    浏览(48)
  • linux驱动开发 - 08_内核定时器

    链接: C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂 1.1 内核时间管理简介 Linux 内核中有大量的函数需要时间管理,比如周期性的调度程序、延时程序、对于驱动编写者来说最常用的定时器。 硬件定时器提供时钟源,时钟源的频率可以设置, 设置好以

    2024年02月02日
    浏览(33)
  • Android驱动开发之如何编译和更换内核

    编译内核可以使用图形化的界面配置,也可以直接使用脚本。在X86_64模拟器环境下,不用交叉编译,而交叉编译工具很容易出现兼容问题,一般也只能使用芯片厂商提供的工具,而不是GNU提供的工具。 android内核开发流程以及架构变化了很多,详情请看 内核官网 内核版本选择

    2024年04月26日
    浏览(30)
  • 嵌入式Linux驱动开发 02:将驱动程序添加到内核中

    在上一篇文章 《嵌入式Linux驱动开发 01:基础开发与使用》 中我们已经实现了最基础的驱动功能。在那篇文章中我们的驱动代码是独立于内核代码存放的,并且我们的驱动编译后也是一个独立的模块。在实际使用中将驱动代码放在内核代码中,并将驱动编译到内核中也是比较

    2023年04月09日
    浏览(74)
  • [驱动开发]Linux内核定时器与中断的简单应用

    首先介绍一下定时器原理。 在linux系统中定时器有分为软定时和硬件定时器。 以海思某款芯片为例,定时器模块又称为Timer模块,主要实现定时、计数功能。 Timer 具有以下特点: 带可编程 8 位预分频器的 32bit/16bit 减法定时器/计数器。 Timer 的计数时钟为 3MHz 时钟。 支持 3 种

    2024年02月20日
    浏览(42)
  • 【linux驱动开发】在linux内核中注册一个杂项设备与字符设备以及内核传参的详细教程

    开发环境: windows + ubuntu18.04 + 迅为rk3568开发板 相较于字符设备,杂项设备有以下两个优点: 节省主设备号:杂项设备的主设备号固定为 10,在系统中注册多个 misc 设备驱动时,只需使用子设备号进行区分即可。 使用简单:相比如普通的字符设备驱动, misc驱动只需要将基本信

    2024年01月21日
    浏览(51)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包