您的位置:首页 > Web前端

S3C2440 LCD驱动(FrameBuffer)实例开发<一>

2015-08-28 15:22 459 查看
1. 背景知识

在多媒体的推动下,彩色LCD越来越多地应用到嵌入式系统中,PDA和手机等大多都采用LCD作为显示器材,因此学习LCD的应用很有实际意义!
LCD工作的硬件需求要使一块LCD正常的显示文字或图像,不仅需要LCD驱动器,而且还需要相应的LCD控制器。在通常情况下,生产厂商把LCD驱动器会以COF/COG的形式与LCD玻璃基板***在一起,而LCD控制器则是由外部的电路来实现,现在很多的MCU内部都集成了LCD控制器,如S3C2410/2440等。TQ2440是采用了S3C2440,S3C2410通过LCD控制器就可以产生LCD驱动器所需要的控制信号来控制STN/TFT屏了。
S3C2440内部LCD控制器结构图





根据数据手册来描述一下这个集成在S3C2440内部的LCD控制器:

a:LCD控制器由REGBANK、LCDCDMA、TIMEGEN、VIDPRCS寄存器组成;

b:REGBANK由17个可编程的寄存器组和一块256*16的调色板内存组成,它们用来配置LCD控制器的;

c:LCDCDMA是一个专用的DMA,它能自动地把在侦内存中的视频数据传送到LCD驱动器,通过使用这个DMA通道,视频数据在不需要CPU的干预的情况下显示在LCD屏上;

d:VIDPRCS接收来自LCDCDMA的数据,将数据转换为合适的数据格式,比如说4/8位单扫,4位双扫显示模式,然后通过数据端口VD[23:0]传送视频数据到LCD驱动器;

e:TIMEGEN由可编程的逻辑组成,他生成LCD驱动器需要的控制信号,比如VSYNC、HSYNC、VCLK和LEND等等,而这些控制 信号又与REGBANK寄存器组中的LCDCON1/2/3/4/5的配置密切相关,通过不同的配置,TIMEGEN就能产生这些信号的不同形态,从而支 持不同的LCD驱动器(即不同的STN/TFT屏)

常见TFT屏工作时序分析:





LCD提供的外部接口信号:

VSYNC/VFRAME/STV:
垂直同步信号(TFT)/帧同步信号(STN)/SEC TFT信号;


HSYNC/VLINE/CPV:
水平同步信号(TFT)/行同步脉冲信号(STN)/SEC TFT信号;


VCLK/LCD_HCLK:
象素时钟信号(TFT/STN)/SEC TFT信号;


VD[23:0]:
LCD
像素数据输出端口(TFT/STN/SEC TFT);


VDEN/VM/TP:
数据使能信号(TFT)/LCD驱动交流偏置信号(STN)/SEC TFT 信号;


LEND/STH:
行结束信号(TFT)/SEC TFT信号;


LCD_LPCOE:
SEC TFT OE
信号;


LCD_LPCREV:
SEC TFT REV
信号;


LCD_LPCREVB:
SEC TFT REVB信
号。


VBPD(vertical back porch):
表示在一帧图像开始时,垂直同步信号以后的无效的行数,对应驱动中的upper_margin;


VFBD(vertical front porch):
表示在一帧图像结束后,垂直同步信号以前的无效的行数,对应驱动中的lower_margin;


VSPW(vertical sync pulse width):
表示垂直同步脉冲的宽度,用行数计算,对应驱动中的vsync_len;


HBPD(horizontal back porch):
表示从水平同步信号开始到一行的有效数据开始之间的VCLK的个数,对应驱动中的left_margin;


HFPD(horizontal front porth):
表示一行的有效数据结束到下一个水平同步信号开始之间的VCLK的个数,对应驱动中的right_margin;


HSPW(horizontal sync pulse width):
表示水平同步信号的宽度,用VCLK计算,对应驱动中的hsync_len;


作为帧同步信号的VSYNC,每发出一个脉冲,都意味着新的一屏图像数据开始发送。而作为行同步信号的HSYNC,每发出一脉冲意味着新的一行图像资料开始发送。在帧同步和行同步的头尾留有回扫时间,这样的时序安排起源于CRT显示器电子枪偏转所需要的时间,但后来成为实际上的工业标准,因此TFT屏也包含了回扫时间。


所有显示器显示图像的原理都是从上到下,从左到右的。这是什么意思呢?这么说吧,一副图像可以看做是一个矩形,由很多排列整齐的一行一行点组成,这些点称之为像素。那么这幅图在LCD上的显示原理就是:

A:
显示指针从矩形左上角的第一行第一个点开始,一个点一个点的在LCD上显示,在上面的时序图上用时间线表示就为VCLK,我们称之为像素时钟信号;


B:
当显示指针一直显示到矩形的右边就结束这一行,那么这一行的动作在上面的时序图中就称之为1 Line;


C:
接下来显示指针又回到矩形的左边从第二行开始显示,注意,显示指针在从第一行的右边回到第二行的左边是需要一定的时间的,我们称之为行切换;


D:
如此类推,显示指针就这样一行一行的显示至矩形的右下角才把一副图显示完成。因此,这一行一行的显示在时间线上看,就是时序图上的HSYNC;


E:
然 而,LCD的显示并不是对一副图像快速的显示一下,为了持续和稳定的在LCD上显示,就需要切换到另一幅图上(另一幅图可以和上一副图一样或者不一样,目的只是为了将图像持续的显示在LCD上)。那么这一副一副的图像就称之为帧,在时序图上就表示为1 Frame,因此从时序图上可以看出1 Line只是1 Frame中的一行;


F:
同样的,在帧与帧切换之间也是需要一定的时间的,我们称之为帧切换,那么LCD整个显示的过程在时间线上看,就可表示为时序图上的VSYNC


LCD控制器时序参数可以用下图形象的表示出来:






 

帧缓冲

帧缓冲是Linux为显示设备提供的一个接口,它把一些显示设备描述成一个缓冲区,允许应用程序通过 FrameBuffer定义好的接口访问这些图形设备,从而不用去关心具体的硬件细节。对于帧缓冲设备而言,只要在显示缓冲区与显示点对应的区域写入颜色 值,对应的颜色就会自动的在屏幕上显示。

通过帧缓冲显示汉字点阵,成为linux汉化的唯一可能性,帧缓冲设备是标准字符设备,主设备号为29,对应于/dev/graphics/fbn设备文件。

2. 帧缓冲(FrameBuffer)设备驱动结构

帧缓冲设备为标准的字符型设备,在Linux中主设备号29,定义在/include/linux/major.h,但FB_MAJOR是在include\linux\fb.h中定义,次设备号定义帧缓冲的个数,最大允许有32个FrameBuffer,定义在/include/linux/fb.h中的FB_MAX,也就是最大支持显示器的个数。对应于文件系统下/dev
/graphics/fb%d设备文件

3. 帧缓冲设备驱动在Linux子系统中的结构如下:





帧缓冲设备提供给用户空间的file_operations结构体由fbmem.c的file_operation提供,而特定帧缓冲设备结构体的注册、注销以及其中成员的维护,尤其是fb_ops中成员函数的实现则由xxxfb.c文件实现,fb_ops中成员函数最终会操作LCD控制器硬件寄存器。

4. 帧缓冲相关的重要数据结构

从帧缓冲设备驱动程序结构 看,该驱动主要跟fb_info结构体有关,该结构体记录了帧缓冲设备的全部信息,包括设备的设置参数、状态以及对底层硬件操作的函数指针。在Linux 中,帧缓冲设备最关键的一个数据结构体是fb_info(为了便于记忆,我们把它简称为“FBI”),FBI中包括了关于帧缓冲设备属性和操作的完整描述。每一个帧缓冲设备都必须对应一个fb_info,fb_info在/linux/fb.h中的定义如下:(只列出重要的一些)

4.1 fb_info结构体

其中,比较重要的成员有struct fb_var_screeninfo var、struct fb_fix_screeninfo fix和struct fb_ops *fbops,他们也都是结构体,下面我们一个一个的来看。

4.2 struct fb_var_screeninfo

fb_var_screeninfo结构体主要记录用户可以修改的控制器的参数,比如屏幕的分辨率和每个像素的比特数等。例如:fb_var_screeninfo中的xres定义屏幕一行有多少个点,yres定义一屏幕一列有多少个点,bits_per_pixel定义每个点用多少个自己表示。该结构体定义如下:

4.3 fb_fix_screeninfo结构体

fb_fix_screeninfo结构体又主要记录用户不可以修改的控制器的参数,比如屏幕缓冲区的物理地址和长度等。当帧缓冲设备进行映射操作的时候,就是从fb_fix_screeninfo中取得缓冲区物理地址。该结构体的定义如下:

4.4 fb_ops结构体

fb_ops结构体是对底层硬件操作的函数指针,该结构体中定义了对硬件的操作有:(这里只列出了常用的操作)

5. 帧缓冲设备作为平台设备

S3C2440的LCD控制器被集成在芯片的内部作为一个相对独立的单元,所以Linux把它看做是一个平台设备,故在内核代码/arch/arm/plat-s3c24xx/devs.c中定义有LCD相关的平台设备及资源,代码如下:

除此之外,Linux还在/arch/arm/mach-s3c2410/include/mach/fb.h中为LCD平台设备定义了一个 s3c2410fb_mach_info结构体,该结构体主要是记录LCD的硬件参数信息(比如该结构体的s3c2410fb_display成员结构中 就用于记录LCD的屏幕尺寸、屏幕信息、可变的屏幕参数、LCD配置寄存器等),这样在写驱动的时候就直接使用这个结构体。下面,我们来看一下内核是如果使用这个结构体的。在/arch/arm/mach-s3c2440/mach-smdk2440.c中定义有:

下面,我们再看一下在驱动中是如果引用 到s3c2410fb_mach_info结构体的(注意上面讲的是在内核中如何使用的)。在mach-smdk2440.c中有:

s3c24xx_fb_set_platdata定义在plat-s3c24xx/devs.c中:

一个小知识:不知大家有没有留意,在平台设备驱动中,platform_data可以保存各自平台设备实例的数据,但这些数据的类型都是不同的,为什么都可以保存?这就要看看platform_data的定义,定义在/linux/device.h中,void *platform_data是一个void类型的指针,在Linux中void可保存任何数据类型。

上面平台驱动如何应用平台设备的数据以达到板与驱动分离的目地可有下图表示:









未完!待续。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: