16_LinuxLCD驱动

news2024/11/24 20:44:18

目录

Framebuffer设备

LCD驱动简析

LCD驱动程序编写

LCD屏幕参数节点信息修改

LCD 屏幕背光节点信息

使能Linux logo显示

设置LCD作为终端控制台


Framebuffer设备

先来回顾一下裸机的时候LCD驱动是怎么编写的,裸机LCD驱动编写流程如下:

1.初始化I.MX6U的eLCDIF控制器,重点是LCD屏幕宽(width)、高(height)、hspw、hbp、hfp、vspw、vbp和vfp 等信息。

2.初始化LCD像素时钟。

3.设置RGBLCD显存。

4.应用程序直接通过操作显存来操作LCD,实现在LCD上显示字符、图片等信息。

在Linux中应用程序最终也是通过操作RGB LCD的显存来实现在LCD上显示字符、图片等信息。在裸机中我们可以随意的分配显存,但是在Linux系统中内存的管理很严格,显存是需要申请的,不是你想用就能用的。而且因为虚拟内存的存在,驱动程序设置的显存和应用程序访问的显存要是同一片物理内存。

为了解决上述问题, Framebuffer诞生了, Framebuffer翻译过来就是帧缓冲,简称fb,因此大家在以后的Linux学习中见到"Framebuffer"或者“fb”的话第一反应应该想到RGBLCD或者显示设备。fb是一种机制,将系统中所有跟显示有关的硬件以及软件集合起来,虚拟出一个 fb 设备,当我们编写好LCD 驱动以后会生成一个名为/dev/fbX(X=0-n)的设备,应用程序通过访问/dev/fbX这个设备就可以访问LCDNXP官方的Linux内核默认已经开启了LCD驱动,因此我们是可以看到/dev/fb0这样一个设备,如图所示:

 图中的/dev/fb0就是LCD对应的设备文件,/dev/fb0是个字符设备,因此肯定有

file-operations操作集,fb的fileoperations操作集定义在drivers/video/fbdev/core/fbmem.c文件中,如下所示:

 

LCD驱动简析

LCD裸机例程主要分两部分:

1.获取LCD的屏幕参数。

2.根据屏幕参数信息来初始化eLCDIF接口控制器。不同分辨率的LCD屏幕其eLCDIF控制器驱动代码都是一样的,只需要修改好对应的屏幕参数即可。屏幕参数信息属于屏幕设备信息内容,这些肯定是要放到设备树中的,因此本实验的主要工作就是修改设备树,NXP官方的设备树已经添加了LCD设备节点,只是此节点的LCD屏幕信息是针对NXP官方EVK开发板所使用的4.3寸480*272编写的,需要将其改为我们所使用的屏幕参数。简单看一下NXP 官方编写的Linux下的LCD驱动,打开imx6ull.dtsi,然后找到Icdif节点内容,如下所示:

示例代码59.1.2.1中的Iedif节点信息是所有使用I.MX6ULL芯片的板子所共有的,并不是完整的ledif节点信息。像屏幕参数这些需要根据不同的硬件平台去添加,比如向imx6ullalientek-emmc.dts中的lcdif节点添加其他的属性信息。从示例代码可以看出lcdif节点的compatible属性值为"fsl,imx6ul-ledif"和"fsl,imx28-ledif",因此在Linux源码中搜索这两个字符串即可找到I.MX6ULL的LCD驱动文件,这个文件为drivers/video/fbdev/mxsfb.c, mxsfb.c就是 I.MX6ULL的LCD驱动文件,在此文件中找到如下内容:

从示例代码可以看出,这是一个标准的platform驱动,当驱动和设备匹配以后mxsfb_probe 函数就会执行。在看mxsfb_probe函数之前我们先简单了解一下Linux下Framebuffer驱动的编写流程, Linux内核将所有的Framebuffer抽象为一个叫做fb_info的结构体,fb_info结构体包含了Framebuffer设备的完整属性和操作集合,因此每一个Framebuffer设备都必须有一个fb_info。换言之就是, LCD的驱动就是构建fb_info,并且向系统注册fb_info的过程。fb_info 结构体定义在include/linux/fb.h文件里面,内容如下(省略掉条件编译):

 fb_info结构体的成员变量很多,我们重点关注var、fix、fbops、 screen_base、screen_size和pseudo_palette。

mxsfb_probe函数的主要工作内容为:

1.申请fb_info。

2.初始化 fb_info 结构体中的各个成员变量。

3.初始化eLCDIF控制器。

4.使用register_framebuffer函数向Linux内核注册初始化好的fb_info。register_framebuffer函数原型如下:

 fb_info:需要上报的

返回值: 0,成功;负值,失败。

接下来我们简单看一下mxsfb_probe函数,函数内容如下(有缩减):

 第1374行, host结构体指针变量,表示I.MX6ULL的LCD的主控接口, mxsfb_info结构体是NXP定义的针对I.MX系列SOC的Framebuffer设备结构体。也就是前面一直说的设备结构体,此结构体包含了I.MX系列SOC的Framebuffer设备详细信息,比如时钟、eLCDIF控制器寄存器基地址、fb_info等。

第1395行,从设备树中获取eLCDIF接口控制器的寄存器首地址,设备树中Icdif节点已经设置了eLCDIF寄存器首地址为0X021C8000,因此res=0X021C8000。

第1401行,给host申请内存,host为mxsfb_info类型结构体指针。

第1407行,给fb_info申请内存,也就是申请fb_info。

第1413~1414行,设置host的fbinfo成员变量为fb_info,设置fb_info的par成员变量为host。通过这一步就将前面申请的host和fb_info联系在了一起。

第1416行,申请中断,中断服务函数为mxsfb_irq_handler。

第1425行,对从设备树中获取到的寄存器首地址(res)进行内存映射,得到虚拟地址,并保存到 host的base成员变量。因此通过访问host的base成员即可访问I.MX6UULL的整个eLCDIF寄存器。其实在mxsfb.c中已经定义了eLCDIF各个寄存器相比于基地址的偏移值,如下所示:

 继续回到示例代码中的mxsfb_probe函数,第1462行,给fb_info中的pseudo_palette.申请内存。

第1473行,调用mxsfb_init_fbinfo函数初始化fb_info,重点是fb_info的var、fix、 fbops,screen_base和screen_size。其中fbops是Framebuffer设备的操作集, NXP 提供的fbops为mxsfb_ops,内容如下:

 关于mxsfb_ops里面的各个操作函数这里就不去详解的介绍了。mxsfb_init_fbinfo函数通过调用mxsfb_init_fbinfo_dt函数从设备树中获取到LCD的各个参数信息。最后, mxsfb_init_fbinfo函数会调用mxsfb_map_videomem函数申请LCD的帧缓冲内存(也就是显存)。

第1489-1490行,设置eLCDIF控制器的相应寄存器。

第1494 行,最后调用register_framebuffer函数向Linux内核注册fb_info。mxsfb.c文件很大,还有一些其他的重要函数,比如mxsfb_remove、mxsfb_shutdown等,这里就简单的介绍了一下mxsfb_probe 函数,至于其他的函数大家自行查阅。

LCD驱动程序编写

需要做的就是按照所使用的LCD来修改设备树。重点要注意三个地方:

1.LCD 所使用的 IO 配置。

2.LCD屏幕节点修改,修改相应的属性值,换成我们所使用的LCD屏幕参数。

3.LCD 背光节点信息修改,要根据实际所使用的背光IO来修改相应的设备节点信息。接下来依次来看一下上面这两个节点改如何去修改:

LCD屏幕IO配置

首先要检查一下设备树中LCD所使用的IO配置,这个其实NXP都已经给我们写好了,不需要修改,不过还是要看一下。打开imx6ull-alientek-emmc.dts文件,在iomuxc节点中找到如下内容:

 第2-27行,子节点pinctrl_ledif_dat,为RGB LCD的24根数据线配置项。

第30~36行,子节点pinctrl_ledif_ctrl,RGB LCD的4根控制线配置项,包括CLK、ENABLE、VSYNC和HSYNC。

第37~40行,子节点pinctrl_pwml,LCD背光PWM引脚配置项。这个引脚要根据实际情况设置,这里建议大家在以后的学习或工作中,LCD的背光IO尽量和半导体厂商的官方开发板一致。注意示例代码中默认将LCD的电气属性都设置为 0X79,这里将其都改为0X49,也就是将LCD相关IO的驱动能力改为R0/1,也就是降低 LCD相关IO的驱动能力。因为前面已经说了,正点原子的ALPHA开发板上的LCD接口用了三个SGM3157模拟开关,为了防止模拟开关影响到网络,因此这里需要降低LCD数据线的驱动能力,如果你所使用的板子没有用到模拟开关那么就不需要将0X79改为0X49。

LCD屏幕参数节点信息修改

继续在imx6ull-alientek-emmc.dts文件中找到ledif节点,节点内容如下所示:

 第3行,pinctrl-0属性,LCD所使用的IO信息,这里用到了pinctrl_ledif_dat、pinctrl_ledif_ctrl和pinctrl_ledif_reset这三个IO相关的节点,前两个在示例代码中已经讲解了。pinctrl_lcdif_reset是LCD复位IO信息节点,正点原子的I.MX6U-ALPHA开发板的LCD 没有用到复位IO,因此pinctrl_ledif_reset可以删除掉。

第6行,display属性,指定LCD属性信息所在的子节点,这里为display0,下面就是display0子节点内容。

第9-32行, display0子节点,描述LCD的参数信息,第10行的bits-per-pixel属性用于指明一个像素占用的bit数,默认为16bit。将LCD配置为RGB888模式,因此一个像素点占用24bit, bits-per-pixel属性要改为24。

第11行的 bus-width 属性用于设置数据线宽度,因为要配置为RGB888模式,因此bus-width也要设置为24

第13~30行,这几行非常重要!因为这几行设置了LCD 的时序参数信息,NXP官方的EVK开发板使用了一个4.3寸的480*272屏幕,因此这里默认是按照NXP官方的那个屏幕参数设置的。每一个属性的含义后面的注释已经写的很详细了,大家自己去看就行了,这些时序参数就是重点要修改的,需要根据自己所使用的屏幕去修改。

这里以正点原子的 ATK7016(7寸1024*600)屏幕为例,将imx6ull-alientek-emmc.dts文件中的ledif节点改为如下内容:

 第3行,设置LCD屏幕所使用的IO,删除掉原来的pinctrl_lcdif reset,因为没有用到屏幕复位 10,其他的IO不变。

第9行,使用RGB888模式,所以一个像素点是24bit。

第15-23行,ATK7016屏幕时序参数,根据自己所使用的屏幕修改即可。

LCD 屏幕背光节点信息

正点原子的LCD接口背光控制IO连接到了I.MX6U的GPIO1_IO08引脚上, GPIO1_IO08复用为PWM1_OUT,通过PWM信号来控制LCD屏幕背光的亮度,正点原子IMX6U-ALPHA开发板的LCD背光引脚和NXP官方EVK开发板的背光引脚一样,因此背光的设备树节点是不需要修改的,但是考虑到其他同学可能使用别的开发板或者屏幕,LCD背光引脚和NXP官方 EVK开发板可能不同,因此还是来看一下如何在设备树中添加背光节点信息。

首先是GPIO1_1008这个IO的配置,在imx6ull-alientek-emme.dts中找到如下内容:

 pinctrl_pwm1节点就是GPIO1_1O08的配置节点,从第3行可以看出,设置GPIO1_1008这个IO复用为PWM1_OUT,并且设置电气属性值为 0x110b0。

LCD背光要用到PWM1,因此也要设置PWM1节点,在imx6ull.dtsi文件中找到如下内容:

 imx6ull.dtsi文件中的pwml节点信息大家不要修改,如果要修改pwm1节点内容的话请在imx6ull-alientek-emmc.dts文件中修改。在整个Linux源码文件中搜索compatible属性的这两个值即可找到imx6ull的pwm 驱动文件,imx6ull的PWM驱动文件为

drivers/pwm/pwm-imx.c,这里我们就不详细的去分析这个文件了。

继续在imx6ull-alientek-emme.dts文件中找到向pwm1追加的内容,如下所示:

 第3行,设置pwml所使用的IO为pinctrl_pwm1,也就是示例代码所定义的GPIO1_IO08 这个IO

第4行,将status设置为okay。如果背光用的其他pwm通道,比如pwm2,那么就需要仿照示例代码的内容,向pwm2节点追加相应的内容。pwm和相关的IO已经准备好了,但是Linux系统怎么知道PWM1_OUT就是控制LCD 背光的呢?因此还需要一个节点来将LCD 背光和 PWM1_OUT连接起来。这个节点就是backlight , backlight节点描述可以参考Documentation/devicetree/indings/video/backlight/pwm-backlight.txt这个文档,此文档详细讲解了backlight 节点该如何去创建,这里大概总结一下:

1.节点名称要为“backlight”。

2.节点的compatible属性值要为"pwm-backlight”,因此可以通过在Linux内核中搜索“pwm-backlight”来查找PWM背光控制驱动程序,这个驱动程序文件为

drivers/video/backlight/pwm_bl.c,感兴趣的可以去看一下这个驱动程序。

3.pwms属性用于描述背光所使用的PWM以及PWM频率,比如要使用的pwm1,pwm频率设置为200Hz(NXP官方推荐设置)。

4.brightness-levels属性描述亮度级别,范围为0-255, 0表示PWM占空比为0%,也就是亮度最低,255表示100%占空比,也就是亮度最高。至于设置几级亮度,大家可以自行填写此属性。

5.default-brightness-level 属性为默认亮度级别。

根据上述5点设置backlight节点,这个NXP已经给设置好了,大家在imx6ull-alientekemmc.dts 文件中找到如下内容:

 第3行,设置背光使用pwml, PWM频率为200Hz。

第4行,设置背8级背光(0-7),分别为0、4、8、16、32、64、128、255,对应占空比为0%、1.57%、3.13%、6.27%、12.55%、25.1%、50.19%、100%,如果嫌少的话可以自行添加一些其他的背光等级值。

第5行,设置默认背光等级为6,也就是50.19%的亮度。

使能Linux logo显示

Linux内核启动的时候可以选择显示小企鹅 logo,只要这个小企鹅logo显示没问题那么我们的LCD驱动基本就工作正常了。这个logo显示是要配置的,不过Linux内核一般都会默认开启logo显示,但是奔着学习的目的,我们还是来看一下如何使能Linuxlogo显示。打开Linux内核图形化配置界面,按下路径找到对应的配置项:

图中这三个选项分别对应黑白、16位、24位色彩格式的logo,把这三个都选中,都编译进Linux内核里面。设置好以后保存退出,重新编译Linux内核,编译完成以后使用新编译出来的imx6ull-alientek-emmc.dtb和zImage镜像启动系统,如果LCD驱动工作正常的话就会在LCD屏幕左上角出现一个彩色的小企鹅logo,屏幕背景色为黑色,如图所示:

 

设置LCD作为终端控制台

一直使用SecureCRT作为Linux开发板终端,开发板通过串口和SecureCRT进行通信。现在已经驱动起来LCD了,所以可以设置LCD作为终端,也就是开发板使用自己的显示设备作为自己的终端,然后接上键盘就可以直接在开发板上敲命令了,将LCD设置为终端控制台的方法如下:

设置uboot中的bootargs

重启开发板,进入Linux命令行,重新设bootargs参数的console内容,命令如下所示:

注意红色字体部分设置console,这里我们设置了两遍console,第一次设置console-tty1,也就是设置LCD屏幕为控制台,第二遍又设置console=ttymxc0,115200,也就是设置串口也作为控制台。相当于我们打开了两个console,一个是 LCD,一个是串口,重启开发板就会发现LCD 和串口都会显示Linux启动log信息。但是此时我们还不能使用LCD作为终端进行交互,因为的设置还未完成。

修改/etc/inittab文件

打开开发板根文件系统中的/etc/inittab文件,在里面加入下面这一行:

 添加完成以后的/etc/inittab 文件内容如图所示:

 修改完成以后保存/etc/inittab并退出,然后重启开发板,重启以后开发板LCD屏幕最后一行会显示下面一行语句:

至此,拥有了两套终端,一个是基于串口的SecureCRT,一个就是我们开发板的LCD屏幕,但是为了方便调试

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

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

相关文章

【代码随想录day19】找树左下角的值

题目 思路 这题最直观的方法就是用层序遍历,记录一下每一层的左边第一个节点,这样整个层序遍历一遍就能找到最后一行最左边的节点。这里要注意最左边的节点不一定是父节点的左子节点!!!如果最后一行没有左子节点&…

M5ATOMS3基础01按键

initinputoutput Linux环境Arduino IDE中配置ATOM S3 示例 官方示例代码: /* ******************************************************************************* * Copyright (c) 2022 by M5Stack * Equipped with M5AtomS3 sample source c…

Redis过期策略和内存淘汰策略

过期策略 过期策略是指Redis设置过期时间且key已经到达过期时间时删除该key,一般有定期删除和惰性删除; 定期删除是指每隔固定时间扫描key,对已经过期的key做清除操作; 定期删除时并不会实际对key做全量扫描,而是随机…

数字时代下CIO们如何做到业务增长和安全“双手抓”

7月22日,由福建信息主管(CIO)网主办的品牌企业业务增长与CIO进化之道暨福建CIO网20周年(厦门)产业数字化供需见面会在厦门顺利举办。 作为国内云原生安全领导厂商,安全狗也收到邀请出席此次活动。 厦门服云信息科技有限公司&…

Python实战案例:轻松采集微博评论,揭示网络舆论热点!

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 开发环境: python 3.8: 解释器 pycharm: 代码编辑器 模块使用: requests: 发送请求 parsel: 解析数据 jieba pandas stylecloud 第三方模块安装: win R 输入cmd 输入安装命令 pip install 模块名 (如果你…

Android平台如何实现第三方模块编码后(H.264/H.265/AAC/PCMA/PCMU)数据实时预览播放

技术诉求 我们在做GB28181设备对接模块和RTMP直播推送模块的时候,遇到这样的技术需求,设备(如执法记录仪)侧除了采集传统的摄像头外,还需要对接比如大疆等第三方数据源,确保按照GB28181规范和RTMP协议规范…

使用百度地图SDK计算距离

说明:通过百度地图提供的SDK,可以计算出两个地点之间的距离,另外还有行驶路线等等。本文介绍如果使用百度地图SDK,并用java代码实现。 申请 首先需要登录百度地图的官网,申请开发者认证,个人认证一般都很…

装饰模式-扩展系统功能

买了新车后,不少人会对车进行装饰,比如给车贴膜,喷上骚粉的漆等。某天,小李和小张都买了辆车,小李想给车贴膜,小张想给车先喷漆然后再贴膜。现在中的做法是,把车开到改装店,如果要喷…

统一观测丨使用 Prometheus 监控 Cassandra 数据库最佳实践

作者:元格 本篇内容主要包括四部分:Cassandra 概览介绍、常见关键指标解读、常见告警规则解读、如何通过 Prometheus 建立相应监控体系。 Cassandra 简介 Cassandra 是什么? Apache Cassandra 是一个开源、分布式、去中心化、弹性可伸缩、…

day44-Spring_AOP

0目录 1.2.3 1.Spring_AOP 实体类: Mapper接口: Service和实现类: 测试1: 运行后: 测试2:无此型号时 测试3:库存不足时 解决方案1:事务声明管理器 测试&#xff1a…

【从零开始学习JAVA | 第三十篇】方法引用

前言: 方法引用作为一个重要的知识点,虽然他使用起来很复杂,而且会降低代码的可读性,但是如果用好了方法引用,我们也会获得不错的效率,因此我们在今天将为大家讲解什么是方法引用。 方法引用:…

J-Flash合并多个bin文件

文章目录 1. 前言2. 下载 J-Flash 工具3. 合并3个bin文件3.1 Booloader.bin3.2 APP1.bin3.3 APP2.bin3.4 保存 → 导出合并bin文件3.5 未用到的区域会被填充为 FF 4. 欢迎纠正~ 1. 前言 下面介绍用J-Flash工具合并多个bin文件的方法 2. 下载 J-Flash 工具 在下载Jink驱动的…

excel 生成sql技巧

"update 表名 set 字段名"&A2&" where 字段名"&B2&";"

最小栈,设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

题记: 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶…

交换机和终端设备的基本配置

1 IOS访问 1.1 操作系统 所有终端设备和网络设备都需要有操作系统 (OS)。如图所示,操作系统中直接与计算机硬件交互的部分称为内核。与应用程序和用户连接的部分则称为外壳。用户可以使用命令行界面 (CLI) 或图形用户界面 (GUI) 与外壳交互。 使用 CLI 时&#xf…

欧姆龙以太网模块连接MCGS步骤

你是否曾经遇到过这样的问题:在监控PLC数据时,触摸屏无法与PLC通讯,或者PLC的通讯口被占用了?今天,我要向大家介绍一款神奇的设备——捷米特JM-ETH-CP转以太网模块,它能够即插即用,不占用PLC通讯…

被吹爆的Wi-Fi 6,究竟强在哪?

被吹爆的Wi-Fi 6,究竟强在哪? 伴随IoT技术的成熟及发展,Wi-Fi标准也在不断迭代升级,然而就实际情况来说,依旧有不少人仍在使用旧标准,比如Wi-Fi 4、Wi-Fi 5。其实WiFi的每一次升级除了速率更高,…

SpringCloud+Nacos集成Seata-1.7.0分布式事务

Seata是一个比较成熟的分布式事务工具,非常好用,主流的的一套,网上大多都是1.4版本,以及不完整了,鄙人也是找了好久才找到有个1.7版本的详细教程(放在最后面了,毕竟是别人的技术,这里…

打造高效便捷的采购管理平台,提升企业采购效率

随着企业规模的扩大和供应链的日益复杂,传统的手工采购管理方式已经不能满足企业的需求。采购管理平台的出现为企业提供了一个集中、高效、便捷的采购管理工具。本文将重点探讨采购管理平台的意义与作用,并介绍如何打造一个高效便捷的采购管理平台。 一、…

【干货分享】如何恢复SOLIDWORKS 零件、装配体和工程图模板?

当我们卸载了SOLIDWORKS或者是购买了一台新笔记本电脑或是丢失了一直在使用的模板时,我们可以通过打开过去的零件、装配体和工程图文件来恢复 SOLIDWORKS 模板。 ▷ 零件模板 打开包含所需自定义属性的上一个部件。 保存零件的副本以避免对原始文件进行意外更改。…