基于ARM微处理器,linux内核的STN-LCD驱动的移植
王博文
摘要:如今,嵌入式产品被广泛的应用于我们生产生活的各个领域,几十年以后,它将取代PC占有较大的市场份额,我们将会进入后PC时代。嵌入式产品的开发也成了技术人员热切关注的课题。本文从实践的角度详细讨论了如何在基于S3C6410的开发板上,对STN-LCD驱动进行移植。涉及Frambuffer技术,在了解内核代码的基础上,本人成功的对STN-LCD进行移植,实践证明该结论具有较高的科研价值和社会价格。
关键词:STN;LCD驱动;linux内核移植;
中图分类号:TP273;
Abstract:Today, embedded products are widely used in all areas of life we produce, several decades later, it will replace the PC account for a large market share, we will enter the post-PC era. Embedded product development has become a subject of great concern technical staff. From the practical point of view discussed in detail how to S3C6410 based development board, on the STN-LCD driver for transplant. Frambuffer technology involved in understanding the basis of the kernel code, I am a successful transplant of the STN-LCD, practice shows that the conclusion of high scientific value and social price.
KEY WORDS:STN LCD;LCD DRIVER; linux core
1、linux开发环境介绍。ARM11 S3C6410微处理器与Linux的结合越来越紧密,逐渐在嵌入式领域得到广范的应用。目前,在便携式消费类电子产品、无线设备、汽车、网络、存储产品等都可以看到S3C6410与Linux相结合的身影。
在众多嵌入式操作系统中,Linux目前发展最快、应用最为广泛。性能优良、源码开放的Linux具有体积小、内核可裁减、网络功能完善、可移植性强等诸多优点,非常适合作为嵌入式操作系统。由于linux本身为开源代码,其版本也在逐渐升级。每个阶段的版本对应的设备驱动程序差异很大。
与Linux2.4内核相比,2.6内核吸收了最新的技术,在性能、可测量性、器件支持和可用性方面有了大幅度提高;支持更多的体系结构、处理器、总线、接口和设备;标准化了内部接口;简化了扩展或添加新设备的步骤等。
我们主要针对linux2.6版本的STN-LCD驱动的移植进行说明。
要移植、开发小型Linux系统,首先要在安装了RedHat9或更高版本Linux操作系统的主机上配置交叉开发环境。交叉开发是指在开发主机上安装开发工具,编辑、编译目标板的引导程序、内核和文件系统,使其能在目标板上运行。
STN液晶屏显示器与显示材料,光线的干涉现象有关,因此显示的色调以淡绿色与橘红色为主。STN显示器中,使用X,Y轴交叉的单纯电极驱动方式,即X,Y轴由垂直与水平方向的驱动电极组成,水平方向驱动电压控制显示部分为亮或暗,垂直方向的电极则负责驱动液晶分子的显示。STN液晶显示屏加上彩色滤光片,并将彩色显示矩阵中的每一象素分成三个子象素,分别通过彩色滤光片显示红,绿,蓝三原色,也可以显示出彩色。单色液晶屏与灰度液晶屏都是STN液晶屏。
本人使用的源代码是linux2.6.16,由于该源代码没有对STN-LCD驱动的实现部分,缺省的是TFT-LCD驱动程序。所以,必须对相关的代码进行优化,否则无法点亮一个STN型号的LCD,也无法显示任何图像。
2、Framebuffer介绍。Framebuffer介绍图形硬件设备的抽象层。它描述视频硬件的帧缓冲区,提供一组非常方便的应用软件访问图形硬件的接口,应用软件不需要了解底层设备的任何信息。
Framebuffer设备通过指定的设备节点访问,通常位于/dev目录下,如dev/fb*,内核中/Doc unmentation/fb目录下的framebuffer.txt和interal.txt 文件介绍了一部分关于Framebuffer的信息。
在linux系统,对于使用者Framebuffer设备与/dev目录下的其它设备使用大体相同,Framebuffer是主编号29的字符设备,尾编号指定同一类设备的顺序。
0=/dev/fb0
1=/dev/fb1
……
31=/dev/fb31
3、STN-LCD移植的实现过程。由于LCD驱动程序是在编译内核的时候·编译进内核的,而LCD驱动程序是通过Framebuffer设备来显示图像的。Framebuffer是让内存的物理地址映射到用户进程空间,从而用户在往Framebuffer写信息时,同时也显示在了LCD上。对于用户而言,它和 /dev 下面的其他設设备没有区别,用户可以把 framebuffer 看成一块內存,既可以向这块內存中写入数据,也可以从这块内存中读取数据。对于s3c6410的framebuffer驱动支持的操作主要有s3c6410fb_ops变量中定义,该变量类型为struct fb_ops,该类型的定义在include/linux/fb.h文件中。
我们打开内核的相关文件,在路径linux-2.6.16\drivers\video 下面找到s3c6410fb.c文件。这个文件是关于LCD驱动程序的。在这个文件里面,有几个函数,下面就这几个函数的功能简单说明下。
static struct fb_ops s3c6410fb_ops = {
.owner = THIS_MODULE,
.fb_check_var = s3c6410fb_check_var,
.fb_set_par = s3c6410fb_set_par,
.fb_blank = s3c6410fb_blank,
.fb_setcolreg = s3c6410fb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
对framebuffer驱动程序函数的定义可以在linux/drivers/video/fbmem.c里面找到,上式主要对framebuffer驱动程序进行实现。
s3c6410fb_check_var,对于一个LCD屏来说内核提供了两组数据结构来描述它,一组是可变属性(fb_var_screeninfo描述),另一组是不变属性(fb_fix_screeninfo描述)。对于可变属性,应该防止在操作的过程中出现超出法定范围的情况,因此内核应该可以调用相关函数来检测、并将这些属性固定在法定的范围内,完成这个操作的函数就是s3c6410_check_var。
s3c6410fb_set_par,该函数的主要工作是重新设置驱动的私有数据信息,主要改变的属性有bpp和行的长度(以字节为单位)。这些属性值其实是存放在fb_fix_screeninfo结构中的。
s3c6410fb_setcolreg,这个函数主要用来设置颜色模式,比如RGB:5、6、5。
s3c6410fb_set_par函数执行完调用s3c6410fb_activate_v函数。s3c6410fb_activate_var该函数实际是设置硬件寄存器,比如设置屏幕边界有关的寄存器的值,确定显示屏的型号的寄存器的值。
switch (var->bits_per_pixel) {
case 1:
fbi->regs.lcdcon1 |= S3C6410_LCDCON1_TFT1BPP;
break;
case 2:
fbi->regs.lcdcon1 |= S3C6410_LCDCON1_TFT2BPP;
break;
case 4:
fbi->regs.lcdcon1 |= S3C6410_LCDCON1_TFT4BPP;
break;
case 8:
fbi->regs.lcdcon1 |= S3C6410_LCDCON1_TFT8BPP;
break;
case 16:
fbi->regs.lcdcon1 |= S3C6410_LCDCON1_TFT16BPP;
break;}
var->bits_per_pixel这个值是位/像素,意思是用多少位表示一个像素。由于我们使用的是STN型的LCD,所以我们将等号右边S3C6410_LCDCON1_TFT1BPP,S3C6410_LCDCON1_TFT2BPP,S3C6410_LCDCON1_TFT4BPP,S3C6410_LCDCON1_TFT8BPP,S3C6410_LCDCON1_TFT16BPP改为S3C6410_LCDCON1_STN1BPP,S3C6410_LCDCON1_STN2GREY,S3C6410_LCDCON1_STN4GREY,S3C6410_LCDCON1_STN8BPP,S3C6410_LCDCON1_STN12BPP。
同时,我们根据STN-LCD驱动程序的驱动原理,要设置红、黄、蓝三个颜色寄存器的值,所以我们添加上如下代码。
writel(0x12210, S3C6410_DITHMODE);
writel(0xfdb96420, S3C6410_GREENLUT);
writel(0xfdb96420, S3C6410_REDLUT);
writel(0xfb40, S3C6410_BLUELUT);
打开linux/arch/arm/mach-s3c6410/mach-smdk2410.c,文件需要修改针对S3C6410初始化的信息,我们增添两个头文件
#include <asm/arch/regs-lcd.h>,#include <asm/arch-s3c6410/fb.h>同时增加数据结构
static struct s3c6410fb_mach_info s3c6410_lcd_info __initdata = {
.fixed_syncs = 0,
.regs = {
.lcdcon1=S3C6410_LCDCON1_STN8BPP|(0<<7)|S3C6410_LCDCON1_STN8|S3C6410_LCDCON1_CLKVAL(6)| (1<<0),
.lcdcon2=S3C6410_LCDCON2_VBPD(0)|S3C6410_LCDCON2_LINEVAL(239)| S3C6410_LCDCON2_VFPD(0) | S3C6410_LCDCON2_VSPW(0),
.lcdcon3=S3C6410_LCDCON3_WDLY(0)|S3C6410_LCDCON3_HOZVAL(320*3/8-1)| S3C6410_LCDCON3_LINEBLANK(16),
.lcdcon4 = S3C6410_LCDCON4_MVAL(13) | S3C6410_LCDCON4_WLH(0),
.lcdcon5 = S3C6410_LCDCON5_BSWP | S3C6410_LCDCON5_PWREN ,},
.lpcsel = 0x7,
.gpccon = 0xaaaaa9aa,
.gpccon_mask = 0xffffffff,
.gpcup = 0x0000ffef,
.gpcup_mask = 0xffffffff,
.gpdcon = 0xaaaaaaaa,
.gpdcon_mask = 0x0,
.gpdup = 0x0000ffff,
.gpdup_mask = 0xffffffff,
.width = 320,};
.height = 240, };
.xres = {320,320,320},
.yres = {240,240,240},
.bpp = {12,12,12};
以上几个对变量的赋值主要完成了对LCD相关寄存器的初始化,和定义LCD屏幕的大小和象素的位数。如.bpp = {12,12,12}定义LCD象素的位数为最小12,最大12,缺省12。
同时我们添加函数,用set_s3c6410fb_info(&s3c6410_lcd_info)来调用变量s3c6410_lcd_info。
static void __init smdk2410_lcd_init(void)
{set_s3c6410fb_info(&s3c6410_lcd_info); }
最后,在文件最后MACHINE_END 之前添加 .init_machine = smdk2410_lcd_init,
确保内核能调用我们刚定义的函数。以上代码的宏定义在linux/include/asm/arch-s3c6410/regs-lcd.h文件里面。
4 烧写内核时应注意的事项
在编译内核时候,我们需要注意的是:
#make menuconfig
Device Drivers >
Graphics support--->
<*> support for frame buffer devices
<*> S3C6410 LCD framebuffer support
Logo configuration ---> // 开机画面的选择,可据个人需要更改
[*]Bootup logo
[*]Standard 224-color linux logo
选中上述选项,把内核烧写进板子,在内核启动后,可以看到有企鹅图标出现。
说明LCD驱动移植成功。如果屏幕没有出现背景(一般为蓝色)和图标,则说明相应的LCD控制器寄存器的值没有设置正确,如果出现了背景而没有出现企鹅图标,则说明是STN相关的三个颜色寄存器的值没有设置正确。如果出现了不止一个企鹅图标,可能是象素值没有设置正确。参照S3C6410手册,正确设置后,上面的问题可以排除。
5 结束语
嵌入式ARM的开发成为近年来的高新产业一个发展趋势。根据现有的开源Linux代码系统进行产品开发将会随着人们对源码的认识不断深入。随着工程师们对嵌入式Linux源码结构的了解,产品驱动的开发将会日臻完善,技术进步会使软硬件相结合的程度更加紧密了。基于ARM的Linux操作系统将会充实我们生活的各个领域,基于ARM的嵌入式产品将会占有更为广阔的市场。
参考文献
[1]陈赜.ARM9嵌入式技术及Linux高级实践教程[M].北京:北京航空航天出版社,2005
[2]吴明晖.基于ARM的嵌入式系统开发与应用[M].北京:人民邮电出版社,2004
[3]孙福春、宁滨,ARM7嵌入式系统在车辆调度中的应用[J].微计算机信息(测量自动化),2005.21(3):78-79.
[4]马忠梅,ARM嵌入式处理器结构与应用基础[M].北京:北京航空航天大学出版社,2003.6.
[5]邬宽明,CAN总线原理和应用系统设计[M].北京:航空航天大学出版社,1996.