u-boot支持LCD显示(基于TQ2440)

2023-06-26  

平台简介

Linux版本:Linux-3.14

u-boot版本:u-boot-2015.04

硬件:TQ2440(内存:64MB  NandFlash:256MB)

作者:彭东林

邮箱:pengdonglin137@163.com

摘要

这个版本的u-boot支持LCD很容易,期间,参考了tq2440官方u-boot中的LCD驱动。我们只需要在配置文件中配置相应的宏,实现LCD的初始化和使能函数即可。

代码我已经上传到CSDN上了,git@code.csdn.net:pengdonglin137/u-boot.git

其中一共有两个分支,一个是master分支,用于跟踪u-boot的最近分支,另一个是u-boot-2015-04-tq2440-spl分支,从名称上可以看到,这个分支的u-boot版本是u-boot-2015.04,用于向tq2440上移植。

使用方法:

git clone git@code.csdn.net:pengdonglin137/u-boot.git -b u-boot-2015-04-tq2440-spl

思路

我们按照下面的思路来移植:

1.先分析u-boot的启动流程;

2.分析u-boot在内存中的布局;

3.然后重点分析u-boot中LCD的初始化流程,如FreamBuffer的分配,LCD的初始化和使能;

4.完成LCD的初始化和使能函数;

u-boot的启动流程

这里的u-boot采用了spl启动的方式,关于这部分可以参考博客:

http://www.cnblogs.com/pengdonglin137/p/4541705.html

关于这个版本的u-boot的启动流程我总结了一个pdf文档,下面是下载地址:

u-boot-2015.04启动流程以及内存布局

u-boot的内存布局

关于这部分,上面的文档中已经有总结,请参考上面的文档。

LCD的初始化流程

这里我们分为LCD的FreamBuffer的分配,LCD的初始化以及使能过程。

内存分配

下面这张图是S3C2440的LCD控制器模块:

image

 

The LCDCDMA is a dedicated DMA, which can transfer the video data in frame memory to LCD driver automatically. By using this special DMA, the video data can be displayed on the screen without CPU intervention.

u-boot分配的FrameBuffer:

下图中的红色区域就是u-boot预留的LCD FreamBuffer,它的起始地址存放在gd->fb_base中。

image

LCD的初始化

下面是函数调用关系:

board_init_r 

    -> ……

    ->stdio_init_tables

    ->initr_serial

    ->stdio_add_devices    (common/stdio.c)

            ->drv_lcd_init    (common/lcd.c)

                    ->lcd_init    (common/lcd.c)


下面是lcd_init函数:


   1: static int lcd_init(void *lcdbase)

   2: {

   3:     debug("[LCD] Initializing LCD frambuffer at %pn", lcdbase);

   4:     lcd_ctrl_init(lcdbase);

   5:  

   6:     /*

   7:      * lcd_ctrl_init() of some drivers (i.e. bcm2835 on rpi) ignores

   8:      * the 'lcdbase' argument and uses custom lcd base address

   9:      * by setting up gd->fb_base. Check for this condition and fixup

  10:      * 'lcd_base' address.

  11:      */

  12:     if (map_to_sysmem(lcdbase) != gd->fb_base)

  13:         lcd_base = map_sysmem(gd->fb_base, 0);

  14:  

  15:     debug("[LCD] Using LCD frambuffer at %pn", lcd_base);

  16:  

  17:     lcd_get_size(&lcd_line_length);

  18:     lcd_is_enabled = 1;

  19:     lcd_clear();

  20:     lcd_enable();

  21:  

  22:     /* Initialize the console */

  23:     lcd_set_col(0);

  24: #ifdef CONFIG_LCD_INFO_BELOW_LOGO

  25:     lcd_set_row(7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT);

  26: #else

  27:     lcd_set_row(1);    /* leave 1 blank line below logo */

  28: #endif

  29:  

  30:     return 0;

  31: }

通过分析,最后得知,我们只需要实现函数lcd_ctrl_init、lcd_enable,然后创建一个结构体panel_info,里面填充的是LCD显示屏的分辨率以及每个像素用多少位表示。


我在分析时,参考其他平台的配置文件,将LCD的相关配置打开,然后编译,如果某个函数没有实现,编译时会报错,然后就知道需要实现那些函数。


完成LCD驱动

下面我们就开始完成LCD驱动。


在配置文件中打开相关的配置

文件:include/configs/tq2440.h


   8: /* LCD */

   9: #define CONFIG_LCD

  10: #define LCD_BPP                LCD_COLOR16

  11: #define CONFIG_LCD_LOGO        /* 显示LOGO */

  12: #undef LCD_TEST_PATTERN

  13: #define CONFIG_LCD_INFO        /* 显示用户定义的信息 */

  14: #define CONFIG_LCD_INFO_BELOW_LOGO  /* 用户自定义的信息与LOGO的位置关系 */

  15: #define CONFIG_SYS_WHITE_ON_BLACK   /* 颜色, 黑底白字 */

  16: #define CONFIG_SYS_CONSOLE_IS_IN_ENV

  17:  

  18: #define CONFIG_TQ2440_LCD           /* 这个是我自己加的,负责将我添加的文件编译进来 */

  19:  

  20: #define CONFIG_CONSOLE_MUX  /* 这个配置可以支持将u-boot的打印输出同时定向到串口和LCD屏,否则只支持一个 */

  21:  

  22: /*

  23: 下面这些参数是LCD的硬件信息,需要阅读LCD的芯片手册,我使用的LCD的分辨率是480*272,下面的值我选用的

  24: 是LCD芯片手册中的典型值,芯片手册的名字:WXCAT43-TG6#001_V1.0.pdf

  25: */

  26: #define    CONFIG_TQ2440_LCD_VBPD        1

  27: #define    CONFIG_TQ2440_LCD_VFPD        1

  28: #define    CONFIG_TQ2440_LCD_VSPW        9

  29: #define    CONFIG_TQ2440_LCD_HBPD        1

  30: #define    CONFIG_TQ2440_LCD_HFPD        1

  31: #define    CONFIG_TQ2440_LCD_HSPW        40

  32: #define    CONFIG_TQ2440_LCD_CLKVAL      4

  33:  

  34: #define LCD_XSIZE_TFT                     (480)

  35: #define LCD_YSIZE_TFT                     (272)

  36:  

  37: #define MVAL                            (13)

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

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

  40: #define BSWP                            (0)                        //Byte swap control

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

  42:  

  43: #define CONFIG_SYS_DCACHE_OFF   /* 不定义编译的时候会报错 */

  44:  

关于这部分可以参考文件:


http://www.cnblogs.com/pengdonglin137/p/4604913.html


定义用户自定义信息

文件:board/samsung/tq2440/tq2440.c


   1: root@ubuntu:~/work/latest_codes/u-boot# git diff board/samsung/tq2440/tq2440.c

   2: diff --git a/board/samsung/tq2440/tq2440.c b/board/samsung/tq2440/tq2440.c

   3: index 3a80f22..d82d410 100644

   4: --- a/board/samsung/tq2440/tq2440.c

   5: +++ b/board/samsung/tq2440/tq2440.c

   6: @@ -13,6 +13,8 @@

   7:  #include

   8:  #include

   9:  #include

  10: +#include

  11: +#include

  12:  

  13:  DECLARE_GLOBAL_DATA_PTR;

  14:  

  15: @@ -143,3 +145,12 @@ ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)

  16:         info->interface = FLASH_CFI_X16;

  17:         return 1;

  18:  }

  19: +

  20: +#ifdef CONFIG_LCD_INFO

  21: +void lcd_show_board_info(void)

  22: +{

  23: +       lcd_printf ("%s (%s - %s)n", U_BOOT_VERSION, U_BOOT_DATE, U_BOOT_TIME);

  24: +       lcd_printf ("(C) 2008 DENX Software Engineeringn");

  25: +       lcd_printf ("    pengdonglin137@163.comn");

  26: +}

  27: +#endif /* CONFIG_LCD_INFO */

 


实现LCD初始化和使能函数

我新添加了一个文件:drivers/video/tq2440_fb.c


   1: #include

   2: #include

   3:  

   4: #include

   5: #include

   6: #include

   7:  

   8: DECLARE_GLOBAL_DATA_PTR;

   9:  

  10: #define U32 unsigned int

  11: #define M5D(n)  ( ( n ) & 0x1fffff ) // To get lower 21bits

  12: #define SCR_XSIZE_TFT LCD_XSIZE_TFT

  13:  

  14: #define HOZVAL_TFT        ( LCD_XSIZE_TFT - 1 )

  15: #define LINEVAL_TFT        ( LCD_YSIZE_TFT - 1 )

  16:  

  17: vidinfo_t panel_info = {

  18:     .vl_col = LCD_XSIZE_TFT,   /* 水平分辨率 */

  19:     .vl_row = LCD_YSIZE_TFT,   /* 垂直分辨率 */

  20:     .vl_bpix = LCD_BPP,        /* 每个像素用几位表示,这个在 include/configs/tq2440.h中配置了,我使用的是16位 */

  21: };

  22:  

  23: //volatile unsigned short (*embedsky_LCD_BUFFER)[SCR_XSIZE_TFT] = (volatile unsigned short (*)[SCR_XSIZE_TFT])(gd->fb_base);

  24: /*

  25:     gd->fb_base指向的是FreamBuffer的其实地址,这里我们把它强制转换为一个二维数组来使用

  26: */

  27: #define embedsky_LCD_BUFFER ((volatile unsigned short (*)[SCR_XSIZE_TFT])(gd->fb_base))

  28: volatile char vbpd = 1, vfpd = 1, vspw = 1, hbpd = 1, hfpd = 1, hspw = 1, clkval_tft = 1 ;

  29:  

  30: void tq2440_lcd_ClearScr(U32 c)

  31: {

  32:     unsigned int x,y ;

  33:  

  34:     for( y = 0 ; y < LCD_YSIZE_TFT ; y++ )

  35:     {

  36:         for( x = 0 ; x < (SCR_XSIZE_TFT) ; x++ )

  37:         {

  38:             embedsky_LCD_BUFFER[y][x] = c;

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。