Linux Framebuffer驱动剖析之中的一个—软件需求
嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇《Linux字符设备驱动剖析》。嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT双方面的原创技术分享,稍后会公布嵌入式企鹅圈的2015年的年终总结和2016年的分享计划。
本系列文章将分析Linux Framebuffer驱动的作用(需求)、框架、接口实现和使用。
按笔者一直倡导的Linux学习理念—从软件需求的角度去理解Linux。对于Linux各个子系统,我们首先要理解其软件需求,从中自然会清楚其存在的价值和作用;接下来是理解子系统在Linux整个驱动框架中的层次、角色和怎样交互。最后是理解驱动的接口怎样实现软件需求,明白接口怎样在各种场景中使用。
一、Linux设备驱动和裸设备驱动的关系
理解framebuffer的软件需求之前。我们先理解Linux设备驱动和裸设备驱动的关系:
比如,对于LCD液晶屏,其能够由三星研发的SOC S5PV210(Cortex A8 arm核)的多媒体硬件模块所支持。而对于详细某种LCD液晶屏,涉及到分辨率、时延參数等不同。须要通过软件来设置相应的SOC多媒体硬件寄存器。以达到控制显示的目的。这个软件设置就是SOC编程。其无论是SOC上执行的是Linux。还是Windows。或者是IOS。软件设置的终于结果体现到寄存器上都是一样的。
一般地。嵌入式都是C语言开发,而高级处理器的寄存器是统一编址的,因此裸设备驱动外围设备的C语言代码基本是一样的。
在带操作系统执行时。为了安全考虑。系统一般分为用户态和内核态。那么,SOC编程是硬件编程,仅仅能在内核态完毕,而且须要向用户态程序提供一个接口以进行调用。
对于不同的操作系统而言。从用户态的接口開始到进行终于的SOC编程接口调用的过程中,会经过不同的软件层次。对于Linux操作系统,设备驱动的接口调用过程就是Linux设备驱动框架所决定的。详见《Linux字符设备驱动剖析》、《Linux 设备文件的创建和mdev》、《总线、设备和驱动》和《字符设备驱动、设备驱动模型、sysfs、平台设备驱动的关系》。
从上面分析能够看出。不论什么Linux设备驱动都有两个层次。一个是偏底层硬件的SOC寄存器编程,一个是偏上层应用的Linux子系统软件接口。前者负责和硬件的交互。后者负责跟上层应用交互。Linux为了给用户提供统一的编程接口,在全部的设备驱动之上再架设一层公共接口层,如全部驱动都能够通过open、read、write来进行操作,其是Linux设备驱动框架的组成部分。因此,一般地,Linux设备驱动都有三个层次。
当然。各个子系统内部还会通过分层来解耦内部的需求和实现。
二、LinuxFramebuffer的软件需求
Linux Framebuffer的需求就是驱动LCD屏显示。所以其自然也有两个层次。偏底层硬件的SOC寄存器编程和偏上层应用的写屏接口。本文的重点是为了分析Linux framebuffer驱动的偏上层应用的接口实现,而不是阐述怎样进行SOC编程,由于SOC编程是针对某个详细的SOC寄存器来进行的。
1. LCD屏的驱动需求
SOC和LCD屏的连接示意图例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
1) SOC编程是为了支持多种不同的LCD屏,以使该SOC的应用场景最大化。因此SOC的多媒体Display模块须要考虑不同的屏幕分辨率、位图深度、行切换和帧切换的时延等等。
这些參数的设置终于使得LCD控制器(硬件引擎)产生匹配的时钟和数据输出到LCD引脚上。这些设置的编程方式和其它字符设备(如鼠标、串口等)都是几乎相同的。
所以。LCD的驱动需求是通过寄存器设置支持各种不同的LCD屏。
2)唯一有一点不同的就是,LCD屏驱动器内部有个大的fifo(跟分辨率有关。可能是几百K字节,甚至M字节级)。Fifo中存放LCD屏的显示数据,LCD驱动器内部显示电路会自己主动将FIFO的数据刷新到LCD屏上。由于FIFIO非常大。通过CPU写总线的方式来将内存数据写到fifo的方式是不可行的,这样会加重CPU负担。现代高级SOC处理器都使用DMA的方式,由DMA直接将内存数据搬到FIFO。DMA能够理解为一个专职搬运工,与CPU、GPU一样是独立工作的。仅仅须要告诉它源地址、目的地址和长度就能够了。
源地址就是物理内存地址,目的地址就是FIFO映射地址。DMA工作不经过MMU,所以它仅仅认物理内存地址。
那么。LCD的还有一个驱动需求是CPU将用户数据写到DMA所认的物理内存地址上。CPU写好用户数据到物理内存地址上,显示专用DMA就自己主动搬运到显示FIFO上。
2. LCD屏驱动的实现思路
从上面分析能够看出,LCD屏的设备驱动能够是一个字符设备驱动。第一个需求通过寄存器设置支持各种不同的LCD屏是非常easy实现的。而第二个需求通过write接口也是非常easy实现的。
写接口就是将用户图像数据(0-3G进程虚拟空间buffer, 相应实际的物理内存地址1)复制到内核虚拟地址空间(相应实际的物理内存地址2)。
一般地,我们在用户进程中是申请一块物理连续的内存块(返回地址是0-3G的进程虚拟地址空间),并将多个图像资源数据(如文字。图像等)放到这个内存中。我们把这次资源数据复制到内存块称为一次拷贝。
然后通过写接口复制到实际的显示物理内存,称为二次拷贝。
虚拟地址空间和物理地址空间的映射是通过MMU(内存管理单元)来进行映射和管理的。MMU机制请看《SoC嵌入式软件架构设计之二:内存管理单元的软、硬件协同设计》。简单的理解就是程序执行的空间是4G虚拟地址空间。而实际的物理内存可能是1G内存,代码和数据是真正存储在实际的物理内存上的。怎样通过虚拟地址找到相应的实际物理内存地址就是MMU的作用。
3. Framebuffer的软件需求
从上面分析,图像数据显示要经历两次拷贝。那么,有没有方法做到一次拷贝就能够显示了呢?非常好。Framebuffer就是利用MMU机制来实现一次拷贝就可以显示。
它的显示示意图是:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
可见,当用户图像数据buffer和内核虚拟地址空间buffer相应的都是同一块物理内存。当资源数据复制到用户图像数据buffer时。即是直接复制到显示物理内存了。
所以,framebuffer驱动最重要的功能就是给用户提供一个进程空间映射到实际的显示物理内存的接口(mmap)。
它跟进程间通信的共享变量的原理是一致的。
另外,考虑到一台设备可能要支持多个输出,比如HDMI接口、VGA,或者相似视频监控需求,一个屏幕上有好多个监控窗体。怎样更好地管理多个显示缓存。Framebuffer在内部进行了抽象,即其向上层应用统一抽象为一个字符主设备,而不同的窗体显示缓存即视为不同的字符从设备。Framebuffer支持多达32个从设备。
接下来会从代码级详细分析Linux Framebuffer驱动的框架组成、mmap和其它接口实现、接口使用场景。
透彻理解以上framebuffer驱动的软件需求,再来跟踪分析Linux Framebuffer驱动是不难的。
敬请关注兴许的分析文章!
很多其它嵌入式Linux和物联网原创技术分享请关注微信公众号:嵌入式企鹅圈
Linux Framebuffer驱动剖析之中的一个—软件需求的更多相关文章
- Linux Framebuffer驱动剖析之一—软件需求
		
嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇<Linux字符设备驱动剖析>.嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT两方面的原创技术分享,稍后会发布嵌入式企鹅圈的2 ...
 - Linux Framebuffer驱动剖析之二—驱动框架、接口实现和使用
		
深入分析LinuxFramebuffer子系统的驱动框架.接口实现和使用. 一.LinuxFramebuffer的软件需求 上一篇文章详细阐述了LinuxFramebuffer的软件需求(请先理解第一 ...
 - Linux Framebuffer驱动框架之二软件架构(未完待续)【转】
		
本文转载自:http://blog.csdn.net/gqb_driver/article/details/12918547 /************************************ ...
 - Linux Framebuffer 驱动框架之一概念介绍及LCD硬件原理【转】
		
本文转载自:http://blog.csdn.net/liuxd3000/article/details/17464779 一.基本概念 帧缓冲(Framebuffer)是Linux系统为显示设备提供 ...
 - Linux设备驱动剖析之IIC(二)
		
953行,适配器的编号大于MAX_ID_MASK是不行的,MAX_ID_MASK是一个宏,展开后的值为61. 957至968行,关于管理小整形ID数的,没怎么了解,略过. 974行,调用i2c_reg ...
 - Linux设备驱动剖析之SPI(二)
		
957至962行,一个SPI控制器用一个master来描述.这里使用SPI核心的spi_alloc_master函数请求分配master.它在drivers/spi/spi.c文件中定义: struc ...
 - 【iOS与EV3混合机器人编程系列之四】iOS_WiFi_EV3_Library 剖析之中的一个:WiFi UDP和TCP
		
在上一篇文章中.我们通过编写EV3 Port Viewer项目实现了iOS监測EV3的实时端口数据. 程序最核心的部分就是我们的开源码库iOS_WiFi_EV3_Library. 那么,在本文中,我们 ...
 - 嵌入式Linux驱动案例之中的一个
		
前几天解决一个嵌入式Linux驱动问题,做为一个案例进行记录. 本案例是一个CPU通过LocalBus总线訪问外围一个设备,详细设备是一个DSP器件.在实际应用中,性能要求非常高,对数据訪问速度提出比 ...
 - Linux设备驱动剖析之Input(二)
		
分别是总线类型.厂商号.产品号和版本号. 1156行,evbit,设备支持的事件类型的位图,每一位代表一种事件,比如EV_KEY.EV_REL事件等等.BITS_TO_LONGS(nr)是一个宏,假设 ...
 
随机推荐
- 好用的sublime插件以及快捷键
			
管理插件:使用Ctrl+`(Esc键下方)快捷键或者通过View->Show Console菜单打开命令行 import urllib.request,os,hashlib; h = '2915 ...
 - Redis系列(五)--主从复制
			
单机环境存在的问题: 1.机器故障,直接凉凉 2.容量瓶颈 3.QPS瓶颈 主从复制 对于可拓展平台来说,复制(replication)是必不可少的.replication可以让其他服务器slave拥 ...
 - ThinkPHP---插件highcharts
			
[一]概论 (1)介绍 基于jquery开发的国外图标插件,统计图,折线图,饼状图等常常用到. 国内也有一款类似插件echarts,由百度开发. (2)官网:www.highcharts.com ...
 - 【原】thinkphp修改Redis操作类,支持选择数据库功能及添加其他方法
			
版本3.2.2(ThinkPHP\Library\Think\Cache\Driver\Redis.class.php), 一:官方默认不支持选择数据库功能及,现就可选择数据库功能进行说明. 1 co ...
 - python多进程和多线程编程
			
17 多线程和多进程并发 The modules described in this chapter provide support for concurrent execution of code. ...
 - UVA - 12661 Funny Car Racing (Dijkstra算法)
			
题目: 思路: 把时间当做距离利用Dijkstra算法来做这个题. 前提:该结点e.c<=e.a,k = d[v]%(e.a+e.b); 当车在这个点的1处时,如果在第一个a这段时间内能够通过且 ...
 - UVA - 1601 The Morning after Halloween (双向BFS&单向BFS)
			
题目: w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...
 - Pycharm Anaconda 安装dlib
			
由于采用python3.7安装会出现各种问题,两种解决方法. 1)安装Cmake boost等(不推荐,麻烦且不容易成功). 2)安装Anaconda,创建一个python3.6的环境. 这里使用第二 ...
 - 51nod1429 巧克力
			
[题解] 找一下两个面积s1,s2的2和3的因子数,把他们除掉,如果s1,s2不相等,就是-1,否则可以用s1,s2的2和3的因子数计算答案. #include<cstdio> #incl ...
 - Android BottomSheet:便捷易用的底部滑出面板(1)
			
Android BottomSheet:便捷易用的底部滑出面板(1) Android BottomSheet是github上的一个第三方开源项目,其主页:https://github.com/Flip ...