基于ARM微处理器,linux内核的STN-LCD驱动的移植

基于ARM微处理器,linux内核的STN-LCD驱动的移植

王博文

摘要:如今,嵌入式产品被广泛的应用于我们生产生活的各个领域,几十年以后,它将取代PC占有较大的市场份额,我们将会进入后PC时代。嵌入式产品的开发也成了技术人员热切关注的课题。本文从实践的角度详细讨论了如何在基于S3C6410的开发板上,对STNLCD驱动进行移植。涉及Frambuffer技术,在了解内核代码的基础上,本人成功的对STNLCD进行移植,实践证明该结论具有较高的科研价值和社会价格。

关键词:STNLCD驱动;linux内核移植;

中图分类号:TP273;

AbstractToday, 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 LCDLCD DRIVER; linux core

1linux开发环境介绍。ARM11 S3C6410微处理器与Linux的结合越来越紧密,逐渐在嵌入式领域得到广范的应用。目前,在便携式消费类电子产品、无线设备、汽车、网络、存储产品等都可以看到S3C6410Linux相结合的身影。

在众多嵌入式操作系统中,Linux目前发展最快、应用最为广泛。性能优良、源码开放的Linux具有体积小、内核可裁减、网络功能完善、可移植性强等诸多优点,非常适合作为嵌入式操作系统。由于linux本身为开源代码,其版本也在逐渐升级。每个阶段的版本对应的设备驱动程序差异很大。

Linux2.4内核相比,2.6内核吸收了最新的技术,在性能、可测量性、器件支持和可用性方面有了大幅度提高;支持更多的体系结构、处理器、总线、接口和设备;标准化了内部接口;简化了扩展或添加新设备的步骤等。

我们主要针对linux2.6版本的STN-LCD驱动的移植进行说明。

要移植、开发小型Linux系统,首先要在安装了RedHat9或更高版本Linux操作系统的主机上配置交叉开发环境。交叉开发是指在开发主机上安装开发工具,编辑、编译目标板的引导程序、内核和文件系统,使其能在目标板上运行。

STN液晶屏显示器与显示材料,光线的干涉现象有关,因此显示的色调以淡绿色与橘红色为主。STN显示器中,使用X,Y轴交叉的单纯电极驱动方式,即XY轴由垂直与水平方向的驱动电极组成,水平方向驱动电压控制显示部分为亮或暗,垂直方向的电极则负责驱动液晶分子的显示。STN液晶显示屏加上彩色滤光片,并将彩色显示矩阵中的每一象素分成三个子象素,分别通过彩色滤光片显示红,绿,蓝三原色,也可以显示出彩色。单色液晶屏与灰度液晶屏都是STN液晶屏。

本人使用的源代码是linux2.6.16,由于该源代码没有对STNLCD驱动的实现部分,缺省的是TFTLCD驱动程序。所以,必须对相关的代码进行优化,否则无法点亮一个STN型号的LCD,也无法显示任何图像。

2Framebuffer介绍。Framebuffer介绍图形硬件设备的抽象层。它描述视频硬件的帧缓冲区,提供一组非常方便的应用软件访问图形硬件的接口,应用软件不需要了解底层设备的任何信息。

Framebuffer设备通过指定的设备节点访问,通常位于/dev目录下,如dev/fb*,内核中/Doc unmentation/fb目录下的framebuffer.txtinteral.txt 文件介绍了一部分关于Framebuffer的信息。

linux系统,对于使用者Framebuffer设备与/dev目录下的其它设备使用大体相同,Framebuffer是主编号29的字符设备,尾编号指定同一类设备的顺序。

0/dev/fb0

1=/dev/fb1

……

31=/dev/fb31

 

3STN-LCD移植的实现过程由于LCD驱动程序是在编译内核的时候·编译进内核的,而LCD驱动程序是通过Framebuffer设备来显示图像的。Framebuffer是让内存的物理地址映射到用户进程空间,从而用户在往Framebuffer写信息时,同时也显示在了LCD上。对于用户而言,它和 /dev 下面的其他設设备没有区别,用户可以把 framebuffer 看成一块內存,既可以向这块內存中写入数据,也可以从这块内存中读取数据。对于s3c6410framebuffer驱动支持的操作主要有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,这个函数主要用来设置颜色模式,比如RGB565

    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_TFT1BPPS3C6410_LCDCON1_TFT2BPPS3C6410_LCDCON1_TFT4BPPS3C6410_LCDCON1_TFT8BPPS3C6410_LCDCON1_TFT16BPP改为S3C6410_LCDCON1_STN1BPPS3C6410_LCDCON1_STN2GREYS3C6410_LCDCON1_STN4GREYS3C6410_LCDCON1_STN8BPPS3C6410_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源码结构的了解,产品驱动的开发将会日臻完善,技术进步会使软硬件相结合的程度更加紧密了。基于ARMLinux操作系统将会充实我们生活的各个领域,基于ARM的嵌入式产品将会占有更为广阔的市场。

 

参考文献

[1]陈赜.ARM9嵌入式技术及Linux高级实践教程[M].北京:北京航空航天出版社,2005

[2]吴明晖.基于ARM的嵌入式系统开发与应用[M].北京:人民邮电出版社,2004

[3]孙福春、宁滨,ARM7嵌入式系统在车辆调度中的应用[J].微计算机信息(测量自动化),2005.213):78-79.
[4]马忠梅,ARM嵌入式处理器结构与应用基础[M].北京:北京航空航天大学出版社,2003.6.
[5]邬宽明,CAN总线原理和应用系统设计[M].北京:航空航天大学出版社,1996.

 

微信二维码
扫码添加微信咨询
QQ客服:1663286777
电话:137-1883-9017
收到信息将及时回复