主题 : u-boot移植加LCD驱动 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 46330
精华: 0
发帖: 7
金钱: 35 两
威望: 7 点
贡献值: 0 点
综合积分: 14 分
注册时间: 2011-05-12
最后登录: 2011-12-28
楼主  发表于: 2011-09-14 10:41

 u-boot移植加LCD驱动

我移植U-boot-2010.06时,想移植LCD驱动,就是让串口上输出的内容在LCD上显示,并加一个图形LOGO,我应该怎么根据LCD的datasheet设置参数.主要是x  y pixclk   le ri  up lo   hs vs  s  vmode这几个参数的主设置.我的是S3C2440+256M nandflash+64M mem+4.3”LCD.



移植参考如下:

移植环境



1,主机环境:VMare下CentOS 5.5 ,1G内存。



2,集成开发环境:Elipse IDE



3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。



4,开发板:mini2440,2M nor flash,128M nand flash。



5,u-boot版本:u-boot-2009.08









7.1添加 LCD 显示功能



对于这个 LCD 的支持是参考Openmoko 的代码移植的。Openmoko 的GTA2 使用的是S3C2442 的CPU,在LCD 控制器上是一样的。而GTA2 在U-boot 的可以在LCD 上显示字符,而且对于软件分层的U-boot 来说,只要将底层驱动移植过来并调整好初始化参数就可以在LCD 上显示console。下图是LCD驱动软件分层执行流程示意。可以看到LCD在执行时最终调用的是底层的board_video_init()函数,其主要作用是对LCD控制寄存器进行初始化。可由用户根据实际LCD硬件编写。







由于友善之臂使用了两种屏,他们在一个参数上有很小的差别,而屏有不可以通过程序去识别,所以只能简单的通过Nand Flash 配置来区分导入的参数(64MB Nand 的板子使用的都是NEC 的,其他的都是统宝的)。这个功能的移植修改了5 个文件(包括drivers/video/Makefile,以及前面已经修改过的board/samsung/mini2440/mini2440.c 文件)。



【1】在/drivers/video/下添加一个驱动文件名为s3c2410_fb.c,将下面内容粘贴进去:



/*

* (C) Copyright 2006 by OpenMoko, Inc.

* Author: Harald Welte <laforge@openmoko.org>

*

* This program is free software; you can redistribute it and/or

* modify it under the terms of the GNU General Public License as

* published by the Free Software Foundation; either version 2 of

* the License, or (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program; if not, write to the Free Software

* Foundation, Inc., 59 Temple Place, Suite 330, Boston,

* MA 02111-1307 USA

*/



#include <common.h>



#if defined(CONFIG_VIDEO_S3C2410)



#include <video_fb.h>

#include "videomodes.h"

#include <s3c2410.h>

/*

* Export Graphic Device

*/

GraphicDevice smi;



#define VIDEO_MEM_SIZE  0x200000        /* 240x320x16bit = 0x25800 bytes */



extern void board_video_init(GraphicDevice *pGD);



/*******************************************************************************

*

* Init video chip with common Linux graphic modes (lilo)

*/

void *video_hw_init (void)

{

    S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();

    GraphicDevice *pGD = (GraphicDevice *)&smi;

    int videomode;

    unsigned long t1, hsynch, vsynch;

    char *penv;

    int tmp, i, bits_per_pixel;

    struct ctfb_res_modes *res_mode;

    struct ctfb_res_modes var_mode;

//    unsigned char videoout;



    /* Search for video chip */

    printf("Video: ");



    tmp = 0;



         videomode = CFG_SYS_DEFAULT_VIDEO_MODE;

         /* get video mode via environment */

         if ((penv = getenv ("videomode")) != NULL) {

                 /* deceide if it is a string */

                 if (penv[0] <= '9') {

                         videomode = (int) simple_strtoul (penv, NULL, 16);

                         tmp = 1;

                 }

         } else {

                 tmp = 1;

         }

         if (tmp) {

                 /* parameter are vesa modes */

                 /* search params */

                 for (i = 0; i < VESA_MODES_COUNT; i++) {

                         if (vesa_modes.vesanr == videomode)

                                 break;

                 }

                 if (i == VESA_MODES_COUNT) {

                         printf ("no VESA Mode found, switching to mode 0x%x ", CFG_SYS_DEFAULT_VIDEO_MODE);

                         i = 0;

                }

                 res_mode =

                         (struct ctfb_res_modes *) &res_mode_init[vesa_modes.

                                                                  resindex];

                 bits_per_pixel = vesa_modes.bits_per_pixel;

         } else {



                res_mode = (struct ctfb_res_modes *) &var_mode;

                 bits_per_pixel = video_get_params (res_mode, penv);

         }



         /* calculate hsynch and vsynch freq (info only) */

         t1 = (res_mode->left_margin + res_mode->xres +

               res_mode->right_margin + res_mode->hsync_len) / 8;

         t1 *= 8;

         t1 *= res_mode->pixclock;

         t1 /= 1000;

         hsynch = 1000000000L / t1;

         t1 *=

                 (res_mode->upper_margin + res_mode->yres +

                  res_mode->lower_margin + res_mode->vsync_len);

         t1 /= 1000;

         vsynch = 1000000000L / t1;



         /* fill in Graphic device struct */

         sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,

                  res_mode->yres, bits_per_pixel, (hsynch / 1000),

                  (vsynch / 1000));

         printf ("%s\n", pGD->modeIdent);

         pGD->winSizeX = res_mode->xres;

         pGD->winSizeY = res_mode->yres;

         pGD->plnSizeX = res_mode->xres;

         pGD->plnSizeY = res_mode->yres;

            

         switch (bits_per_pixel) {

         case 8:

                 pGD->gdfBytesPP = 1;

                 pGD->gdfIndex = GDF__8BIT_INDEX;

                 break;

         case 15:

                 pGD->gdfBytesPP = 2;

                 pGD->gdfIndex = GDF_15BIT_555RGB;

                 break;

         case 16:

                 pGD->gdfBytesPP = 2;

                 pGD->gdfIndex = GDF_16BIT_565RGB;

                 break;

         case 24:

                 pGD->gdfBytesPP = 3;

                 pGD->gdfIndex = GDF_24BIT_888RGB;

                 break;

         }



         /* statically configure settings */

        pGD->winSizeX = pGD->plnSizeX = 240;

         pGD->winSizeY = pGD->plnSizeY = 320;

         pGD->gdfBytesPP = 2;

         pGD->gdfIndex = GDF_16BIT_565RGB;



         pGD->frameAdrs = LCD_VIDEO_ADDR;

         pGD->memSize = VIDEO_MEM_SIZE;



         board_video_init(pGD);



         lcd->LCDSADDR1 = pGD->frameAdrs >> 1;



         /* This marks the end of the frame buffer. */

         lcd->LCDSADDR2 = (lcd->LCDSADDR1&0x1fffff) + (pGD->winSizeX+0) * pGD->winSizeY;

         lcd->LCDSADDR3 = (pGD->winSizeX & 0x7ff);



         /* Clear video memory */

         memset((void *)pGD->frameAdrs, 0, pGD->memSize);



         /* Enable  Display  */

         lcd->LCDCON1 |= 0x01;   /* ENVID = 1 */



         return ((void*)&smi);

}



void

video_set_lut (unsigned int index,      /* color number */

                unsigned char r, /* red */

                unsigned char g, /* green */

                unsigned char b  /* blue */

  )

{

}



#endif /* CONFIG_VIDEO_S3C2410 */



【2】打开/drivers/video/Makefile,定位到



COBJS-y += videomodes.o

COBJS-y += s3c2410_fb.o



COBJS := $(COBJS-y)





【3】打开/drivers/video/cfb_console.c,定位到284行,修改如下:



#include <linux_logo.h>

#define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH

#define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT

#define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET

#define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS

#endif /* CONFIG_VIDEO_BMP_LOGO */

//#define VIDEO_INFO_X  (VIDEO_LOGO_WIDTH)

//#define VIDEO_INFO_Y  (VIDEO_FONT_HEIGHT/2)

#define VIDEO_INFO_X  (0)

#define VIDEO_INFO_Y  (VIDEO_LOGO_HEIGHT)

#else /* CONFIG_VIDEO_LOGO */

#define VIDEO_LOGO_WIDTH 0

#define VIDEO_LOGO_HEIGHT 0

#endif /* CONFIG_VIDEO_LOGO */



【4】打开/drivers/video/videomodes.c,定位到98行附近,修改如下:



  {0x31A, RES_MODE_1280x1024, 16},

{0x31B, RES_MODE_1280x1024, 24},

{0x211, RES_MODE_240x320, 16},

};

const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {

/* x  y pixclk   le ri  up lo   hs vs  s  vmode */

{640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED},

{800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},

{1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED},

{960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED},

{1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED},

{1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED},

{240, 320, 158025, 26,  6,  1, 11, 37,  2, 0, FB_VMODE_NONINTERLACED},

};



【5】打开/drivers/video/videomodes.h,定位到25行,修改如下:



//#ifndef CONFIG_SYS_DEFAULT_VIDEO_MODE

//#define CONFIG_SYS_DEFAULT_VIDEO_MODE 0x301

#ifndef CFG_SYS_DEFAULT_VIDEO_MODE

#define CFG_SYS_DEFAULT_VIDEO_MODE 0x211

#endif



/* Some mode definitions */



定位到83行,修改如下:



#define RES_MODE_1280x1024 5

//#define RES_MODES_COUNT  6

#define RES_MODE_240x320 6

#define RES_MODES_COUNT  7

//#define VESA_MODES_COUNT 19

#define VESA_MODES_COUNT 20



extern const struct ctfb_vesa_modes vesa_modes[];







【6】打开board/samsung/mini2440/mini2440.c,定位到30行,加入如下头文件:



#include <common.h>

#include <s3c2410.h>

#include <video_fb.h>



定位到138行附近,修改如下:



return 0;

}



#define MVAL  (0)

#define MVAL_USED  (0)  //0=each frame   1=rate by MVAL

#define INVVDEN  (1)  //0=normal       1=inverted

#define BSWP  (0)  //Byte swap control

#define HWSWP  (1)  //Half word swap control





//TFT 240320

#define LCD_XSIZE_TFT_240320  (240)

#define LCD_YSIZE_TFT_240320  (320)



//TFT240320

#define HOZVAL_TFT_240320 (LCD_XSIZE_TFT_240320-1)

#define LINEVAL_TFT_240320 (LCD_YSIZE_TFT_240320-1)



//Timing parameter for NEC3.5"

#define VBPD_240320  (3)  

#define VFPD_240320  (10)

#define VSPW_240320  (1)



#define HBPD_240320  (5)

#define HFPD_240320  (2)

#define HSPW_240320_NEC  (36)  //Adjust the horizontal displacement of the screen

#define HSPW_240320_TD  (23)  //64MB nand mini2440 is 36 ,128MB is 23

          //+ ?-->    - : <--

#define CLKVAL_TFT_240320 (3)  

//FCLK=101.25MHz,HCLK=50.625MHz,VCLK=6.33MHz





void board_video_init(GraphicDevice *pGD)

{

    S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();

   S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

    /* FIXME: select LCM type by env variable */

  

/* Configuration for GTA01 LCM on QT2410 */

lcd->LCDCON1 = 0x00000378; /* CLKVAL=4, BPPMODE=16bpp, TFT, ENVID=0 */

lcd->LCDCON2 = (VBPD_240320<<24)|(LINEVAL_TFT_240320<<14)|(VFPD_240320<<6)|(VSPW_240320);

lcd->LCDCON3 = (HBPD_240320<<19)|(HOZVAL_TFT_240320<<8)|(HFPD_240320);



if ( (nand->NFCONF) & 0x08 ) {

lcd->LCDCON4 = (MVAL<<8)|(HSPW_240320_TD);

}

else {

   lcd->LCDCON4 = (MVAL<<8)|(HSPW_240320_NEC);

}



lcd->LCDCON5 = 0x00000f09;

lcd->LPCSEL  = 0x00000000;

}





int dram_init (void)

{

gd->bd->bi_dram[0].start = PHYS_SDRAM_1;

gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;



return 0;

}



【7】打开/lib_arm/board.c,定位到482行附近,修改如下:



#if defined(CONFIG_CFB_CONSOLE)        

printf ("%s\n", version_string);

printf ("modified by singleboy(singleboy@163.com)\n"); //display on LCD

printf ("Love Linux forever!!\n");

#endif





  /* main_loop() can return to retry autoboot, if so just run it again. */

for (;;) {

  main_loop ();

}



【8】自定义开机logo



(1)如果先改成自己喜欢的图片,可以tools/logos/denx.bmp图片,也可将自己喜欢的图片放在tools/logos/目录下,记住一定图片大小不要起过你的屏的大小,色彩深度不能大于256色,即8位色深的图片8bpp的bmp图。不同的logo图片的大小标准对应不同的,这里S3C2440所对应的是160*96分辨率的BMP图片。



制作方法一:



可以用任何工具把需要处理的logo图片转换成bmp格式图片,大小160*96像素,色彩深度256色,即8bpp(8位色深),然后保存为你需要的文件名字,我的是logott.bmp。



制作方法二(未测试):



在制作图片前,请您现确认您的Linux主机上安装了Netpbm 工具包,如果没有,可以在 Netpbm主页下载源代码编译安装。



将你想要的图片裁减成160*96的JPG图片,然后用以下的脚本处理一下就好了:



#!/bin/sh

#install Netpbm first

    jpegtopnm $1 | ppmquant 31 | ppmtobmp -bpp 8 > $2

使用方法: (脚本名) ( 待处理的JPG图片名)(输出文件名)



(2)打开/tools/Makefile,定位到124行附近,修改如下:



# Generated LCD/video logo

LOGO_H = $(OBJTREE)/include/bmp_logo.h

LOGO-$(CONFIG_LCD_LOGO) += $(LOGO_H)

LOGO-$(CONFIG_VIDEO_LOGO) += $(LOGO_H)



ifeq ($(LOGO_BMP),)

#LOGO_BMP= logos/denx.bmp

LOGO_BMP= logos/logott.bmp

endif

ifeq ($(VENDOR),atmel)

LOGO_BMP= logos/atmel.bmp

endif

ifeq ($(VENDOR),ronetix)

LOGO_BMP= logos/ronetix.bmp

endif



如果你将自己制作的logo命名成logos目录下denx.bmp而将之前的替换掉,这里的代码就不用修改了。



然后保存。



【9】打开include/configs/mini2440.h头文件,定位到138行附近,加入下面代码,即可将串口的打印信息显示在lcd上:



#define CONFIG_EXTRA_ENV_SETTINGS     \

"stdin=serial\0"      \

"stdout=vga\0"       \

"stderr=serial\0"     \

""



CONFIG_EXTRA_ENV_SETTINGS:系统默认的环境变量在/common/env_common.c的uchar default_environment[]中,这个数组将所有的环境变量组织起来 。而对于这个数组没有定义的环境变量可以在CONFIG_EXTRA_ENV_SETTINGS中由用户自定义。



只要让stdout等于vga就可以了。在lib_arm/board.c文件中可以看到console_init初始化两次,我们修改的影响第二次的初始化,对第一次的初始化不产生影响。



定位到定位到文件末尾处,加入下面代码:



/*

LCD video settings

*/



#define CONFIG_CFB_CONSOLE //Enables console device for a color framebuffer

#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE         (240*320+1024+100) /* 100 = slack */

#define LCD_VIDEO_ADDR         0x33d00000

#define VIDEO_FB_16BPP_PIXEL_SWAP  //the color palette,bpp is bits per pixel



#define CONFIG_VIDEO //Video support

#define CONFIG_VIDEO_S3C2410

#define CONFIG_VIDEO_LOGO //display Linux Logo in upper left corner

#define CONFIG_VIDEO_BMP_LOGO //use bmp_logo instead of linux_logo

#define CONFIG_CMD_BMP //BMP support

#define CONFIG_VIDEO_BMP_GZIP //Gzip compressed BMP image support

#define CONFIG_CMD_UNZIP

#define CFG_CONSOLE_INFO_QUIET //Suppress display of console information at boot.

#define CONFIG_SPLASH_SCREEN //enable splash screen support,implicitly enable U-Boot Bitmap Support.



//#define CONFIG_VIDEO_SW_CURSOR //Draws a cursor after the last character.No blinking is provided.

//Uses the macros CURSOR_SET and CURSOR_OFF.

//#define CONFIG_CONSOLE_EXTRA_INFO //Display additional board information to serial port beside the logo.

//This define requires a board specific function: video_drawstring() that fills a info buffer.

//#define CONFIG_CONSOLE_CURSOR //on/off drawing cursor is done with delay loop in VIDEO_TSTC_FCT

//#define CONFIG_CONSOLE_TIME //display time/date in upper right corner, needs CFG_CMD_DATE.

//#define VIDEO_FB_LITTLE_ENDIAN // framebuffer organisation default: big endian





/*for PC-keyboard*/

#define VIDEO_KBD_INIT_FCT     0  //init function for keyboard

#define VIDEO_TSTC_FCT         serial_tstc //keyboard_tstc function

#define VIDEO_GETC_FCT         serial_getc //keyboard_getc function









#endif /* __CONFIG_H */





相关配置选项说明:



CONFIG_CFB_CONSOLE:使能终端设备的彩色帧缓冲. 在/divers/video/cfb_console.c)有相关定义。

            VIDEO_FB_LITTLE_ENDIAN    图像存储组织 (默认为大端序)

            VIDEO_HW_RECTFILL    图像芯片支持矩形填充(rectangle fill)(cf. smiLynxEM)

            VIDEO_HW_BITBLT        图像芯片支持位块传输(bit-blit) (cf. smiLynxEM)

            VIDEO_VISIBLE_COLS    可视像素列 (cols=pitch)

            VIDEO_VISIBLE_ROWS    可视像素行

            VIDEO_PIXEL_SIZE    每像素字节数

            VIDEO_DATA_FORMAT    图像数据格式 (0-5, cf. cfb_console.c)

            VIDEO_FB_ADRS        帧缓冲地址

            VIDEO_KBD_INIT_FCT    keyboard int fct(i.e. i8042_kbd_init())

            VIDEO_TSTC_FCT        test char fct (i.e. i8042_tstc)

            VIDEO_GETC_FCT        get char fct (i.e. i8042_getc)

            CONFIG_CONSOLE_CURSOR    打开/关闭 光标绘制 (需要 blink timer cf. i8042.c)

            CFG_CONSOLE_BLINK_COUNT    blink 间隔 (cf. i8042.c)

            CONFIG_CONSOLE_TIME    在右上角显示时间/日期信息 (需要 CONFIG_CMD_DATE)

            CONFIG_VIDEO_LOGO    在左上角显示Linux logo

            CONFIG_VIDEO_BMP_LOGO    使用bmp_logo.h作为logo(默认是linux_logo.h)。 需要 CONFIG_VIDEO_LOGO。

            CONFIG_CONSOLE_EXTRA_INFO  除了logo外的其它单板信息



如果定义了CONFIG_CFB_CONSOLE, 视频终端是默认的i/o. 使用'console=serial'环境可以强制使用串口终端

如果定义了 CONFIG_SILENT_CONSOLE, 可以用'silent'环境变量屏蔽所有终端消息(包括U-Boot和Linux的输出!)。更多信息见doc/README.silent



CONFIG_SYS_CONSOLE_IS_IN_ENV:如果你想将标准输入、标准输出、标准错误设为usbttyusbtty(USB串口终端),定义该宏。





CONFIG_VIDEO_BMP_GZIP:如果设置该选项, 除了支持标准BMP图像外, splashscreen或者bmp命令可以使用gzip压缩的BMP图像



CONFIG_SPLASH_SCREEN:如果设置该选项, 将检查环境变量"splashimage"。 如果变量存在则显示一张BMP图像,普通的logo, 版权及系统信息不再显示。 "splashimage"指定了位图的存放地址。终端也被重定向到"nulldev"。由于启动的早期就会加载Splash screen,使用它可以实现安静的启动。



7.2 重新编译后nor档a命令下载,nand启动:



可以看到左上角的logo图标换成了自己的制作的图标,下面启动信息与串口终端完全一样。LCD显示功能添加成功。



接下来为u-boot-2009.08添加USB驱动。





本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2011-05/35982p7.htm

描述:4.3"LCD datasheet
附件: AT043TN13.rar (987 K) 下载次数:43