转载 uboot LCD 进度条 为OMAP L138增加uboot启动画面

先说说环境 OMAPL138 软件以TI为主, 开发板是我们自己做的, 仿真器是闻亭的

由于默认的UBOOT不支持OMAPL138开机画面, 所以需要手动移植, 我的移植分为3个阶段, 前2个阶段都以失败告终, 如果不想耽误时间可以直接跳转到第3阶段处.

 

第一阶段: 在TI官方提供的开发包里, 找到用CCS测试LCD 的程序, 将此程序稍作修改生成2个文件, my_lcd.h和my_lcd.c

MY_LCD.C ( 示意代码 )

#include "my_lcd.h"

void mlz_usleep ( int n ) { 略 }

void OMAPL138_lpscTransition(psc_regs_t *psc, unsigned int in_domain, unsigned char in_module, unsigned char in_next_state)

{

while (CHKBIT(psc->PTSTAT, in_domain)) {}

... 略

}

unsigned int enable_lcdc( void )

{

/* Enable the LCD Hardware */

OMAPL138_lpscTransition(PSC1, DOMAIN0, LPSC_LCDC, PSC_ENABLE);

... 略

return (ERR_NO_ERROR);

}

unsigned int raster_config( void )

{

unsigned int x;

unsigned short *pdata;

LCDC->RASTER_CTRL &= 0xfffffffe; // Turn raster controller off

return (ERR_NO_ERROR);

... 略

}

unsigned int disable_lcdc( void ) {略}

void RASTER_plot(unsigned short x, unsigned short y, unsigned short pixel_data)

{

*((unsigned short *)(FRAMEBUF_BASE + 32 + y * (LCD_WIDTH <<1) + (x << 1))) = pixel_data;

}

unsigned int RASTER_init(void)

{

int x,y;

unsigned int rtn = ERR_NO_ERROR;

// enable power and setup lcdc.

enable_lcdc();

raster_config();

mlz_usleep(300000);

disable_lcdc();

mlz_usleep(100000);

// power-up the display kit following the correct sequence.

// enable_lcd_power();

enable_lcdc();

mlz_usleep(300000);

// enable_lcd_backlight();

for (x = 0; x < LCD_WIDTH; x++)

for (y = 0; y < LCD_HEIGHT; y++)

RASTER_plot(x, y, 0x55aa );

return (rtn);

}

 

MY_LCD.H ( 示意代码 )

typedef struct

{

volatile unsigned int REVID; // 0x0000

} psc_regs_t;

#define SETBIT(dest,mask) (dest |= mask)

#define CLRBIT(dest,mask) (dest &= ~mask)

// define the power and sleep config modules.

#define PSC0 ((psc_regs_t *)PSC0_REG_BASE)

#define PSC1 ((psc_regs_t *)PSC1_REG_BASE)

//-----------------------------------------------------------------------------

// power and sleep config registers

typedef struct

{

volatile unsigned int REVID; // 0x0000

volatile unsigned int LCD_CTRL; // 0x0004

...

} lcdc_regs_t;

#define LCDC ((lcdc_regs_t *)LCDC_REG_BASE)

#define LCDC_REG_BASE (0x01E13000)

#define FRAMEBUF_BASE 0xc0000000

修改后把这2个文件放入common文件夹中, 并强制修改common文件夹的Makefile, 以生产my_lcd.o

然后在board/davinci/da8xxevm/da850evm.c中增加RASTER_init调用

int board_init(void)

{

Extern void RASTER_init ( void );

RASTER_init();

}

开机, 应该出现整屏的蓝色, 但颜色变成了渐变色而且分成了好几块, 且一段时间后会花屏, 跟彩色电视机的雪花一样, 然后在linux的开机画面出现前1s, 出现了一个错位/缩小的linux开机画面.

第二阶段, 利用CONFIG_LCD

自己写驱动失败, 于是想利用UBOOT里的CONFIG_LCD和CONFIG_LCD_LOGO.于是寻找带这2个标记的代码段, 在添加这2个选项后 , 编译会报很多错, 主要因为需要指定一款LCD, 而UBOOT里没有对138的支持, 在 drvier/video里找到atmel 的驱动, 这个对LCD支持比较强, 准备在此基础上改, 把驱动的核心代码换成上面第一阶段的代码. 而思想就是对LCDC进行控制.此过程持续了2,3天, 最终因为关联东西太多而放弃.

第三阶段, 参考HAWK

在QQ群里有人提到了,http://code.google.com/p/hawkboard/downloads/list

作为TI的138的合作伙伴, hawkboard也出了开发板, 下载他的UBOOT代码,编译,可以看见启动画面了, 只是在uboot和linux直接会有1s的时间图像错位, 这点至今我也不会改.

Hawk的源代码在TI的基础上做了不大不小的改动, 在LCD方面, 他没有修改现有的驱动(如atmel), 也没有建立单独的c文件, 也就是说它没有用到 CONFIG_LCD选项. 他的思想和我的第一阶段比较相似, 直接写寄存器, 只不过他做的更简单,下面给出了我修改的文件:

文件名: board/davinci/da8xxevm/da850evm.c

修改说明: 写了一个LCDC初始化函数, 并在系统启动时调用,

写了一个画进度条函数, 以便在别的初始化时显示

LCDC初始化函数里, 对LCDC寄存器的初始化没有采用hawd的方式, 而是采用之前my_lcdc.c里面的参数,

增加 #include "uboot_logo.h" , 此文件存储开机画面图片, 后面介绍

增加 static int X1 = 117; //进度条外框

static int Y1 = 342;

static int X2 = 497;

static int Y2 = 362;

增加 #define LCDDMA_FB0_BASE 0xC3601000 - 32

//定义FB基地址, 范围 0xc0000000~0xc8000000

在这个地址中, -32 是为了将来画图直接从1000开始, 因为前32个字节是调色板, 而1000也是为了变成整数, 最重要的在0xc360xxxx, 以前在my_lcd里写成了0xc0000000, 因为在启动参数里将uImage调入0xc0700000, 而内核的入口地址是c0008000, 这就导致画面被冲, 结果也是如此, 在第一阶段load内核后,只有屏幕最上方的画面还在, 下面花屏了, 最上方正好对应 8000个字节

在HAWD的地址写成了c7200000, 我把它改成了36, 反正DDR的寻址是128M, 即c80000000, 而我的36M也没用, 所以没问题.

之前失败的时候还曾经试过0XA000000, 因为以前写DOS程序的时候FB就是a000000, 现在发现,在UBOOT里, 这个基地址任意给, 只要在DDR的寻址范围内即可.

 

增加进度条显示函数

void DispLogoProgress ( int data )

{

int i, j;

int n = ( X2 - X1 - 6 ) / 100.0 * data*2 + X1 * 2;

for ( i = ( Y1 + 3 ) * 640 * 2 ; i < ( Y2 - 3 ) * 640 * 2; i += 2*640 )

for ( j = ( X1 + 3 ) * 2 ; j < n; j+= 2 )

*((volatile unsigned short *)(LCDDMA_FB0_BASE+32+i+j ) ) = 0xfc00;

}

增加初始化LCDC函数

static void logo_init(void)

{

unsigned int i,k;

unsigned char pixel[3];

int offset = 0;

int ptr = 0;

*((volatile uint *) 0x01E13028) = 0x010000C0; //TURN_OFF RASTER_CTRL

*((volatile uint *) LCDDMA_FB0_BASE) = 0x00004000;

*((volatile uint *) 0x01E13004) = 0x00000801; //LCD_CTRL

*((volatile uint *) 0x01E1302C) = (0x19 << 24)

| (0x89 << 16)

| (0x31 << 10)

| (0x27 << 4);; //RASTER_TIMING_0

*((volatile uint *) 0x01E13030) = (0x1F << 24)

| (0x20 <<16)

| (0x02 <<10)

| (0x1DF);; //RASTER_TIMING_1

*((volatile uint *) 0x01E13034) = 0x02700000 ; //RASTER_TIMING_2

*((volatile uint *) 0x01E13038) = 0x00000000; //RASTER_SUBPANEL

*((volatile uint *) 0x01E13040) = 0x00000640; //LCDDMA_CTRL

*((volatile uint *) 0x01E13044) = LCDDMA_FB0_BASE; //LCDDMA_FB0_BASE

*((volatile uint *) 0x01E13048) = LCDDMA_FB0_BASE + 640*480*2 + 30; //LCDDMA_FB0_CEILING

//画黑色背景

for (i = 0; i < (640*480*2); i+= 2)

*((volatile unsigned short *)(LCDDMA_FB0_BASE+32 + i)) = 0x0;

//显示白色字体, log_buf里存的不是颜色, 而是白色的偏移量

for ( i = 0 ; i < 4608 ; i++ )

*((volatile unsigned short *)(LCDDMA_FB0_BASE+32 + logo_buf[i] ) ) = 0xffff;

//

//显示进度条框

for ( i = Y1*640*2+X1*2 ; i < Y1*640*2+X2*2; i+= 2 ) //横线

*((volatile unsigned short *)(LCDDMA_FB0_BASE+32 + i)) = 0xfc00;

for ( i = Y2*640*2+X1*2 ; i < Y2*640*2+X2*2; i+= 2 )

*((volatile unsigned short *)(LCDDMA_FB0_BASE+32 + i)) = 0xfc00;

这里有2点值得注意, 一是一开始TURN_OFF RASTER_CTRL然后对LCDC寄存器初始化, 在my_lcd.c里, 初始化结束后要再打开这个CTRL, 然后就可以写屏了, 但HAWD把它放到了后面(下文提到), 我把它放到这里屏幕不正常.

二是LCDDMA_CTRL的默认值, MY_lcd.C里是0x20, 而通过调试发现, uboot实际启动时, 此参数是640, 而hawd是540, 而不论哪个值, 都会在uboot和linux切换的1s左右会有闪屏, 但640 闪的小些, 这个问题暂时无法解决.

 

增加logo_init调用logo_init

int board_init(void)

{

logo_init();

Return 0;

}

增加代码, 关闭LCDC

int misc_init_r(void)

{

dspwake();

*((volatile uint *) 0x01E13028) = 0x010000C1; //关闭控制器

return (0);

}

 

文件名

/lib_arm/board.c

修改摘要

增加阶段显示进度条

修改内容

增加函数声明:extern void DispLogoProgress ( int ) ;

增加进度显示

void start_armboot (void)

{

for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)

{ if ((*init_fnc_ptr)() != 0) {hang ();}}

DispLogoProgress(10);

}

增加进度显示

DispLogoProgress(20);

for (;;) {

main_loop ();

}

 

文件名

/lib_arm/common/cmd_nand.c

修改摘要

增加阶段显示进度条

修改内容

Void nand_load_image ( void )

{

/* Loading ok, update default load address */

load_addr = addr;

// 从NAND将linux内核load到内存后, 显示进度条

extern void DispLogoProgress(int);

DispLogoProgress(40);

}

 

文件名

/lib_arm/common/cmd_bootm.c

修改摘要

增加阶段显示进度条

修改内容

Int bootm_start( void )

{

// bootm 执行成功后更新进度条

extern void DispLogoProgress(int);

DispLogoProgress ( 50 );

return 0;

}

 

增加文件:board/davinci/da8xxevm/uboot_logo.h

说明: 存放初始背景图片, 由于初始背景图片简单, 且单色, 所以实际存储的只是白色的文字所在的位置,一共4K多个点,

最后附上UBOOT 启动流程(从LCD角度)




start_armboot ()
{
board_init ()
{
logo_init()
{

初始化LCDC
设置进度条 0%

}
}

.... 其他初始化

设置进度条10%

misc_init_r
{
关闭LCDC控制器
}

设置进度条20%

main_loop
{

加载内核从NAND到内存后, 40%
BOOTM执行后50%
}
}

 

猜你喜欢

转载自blog.csdn.net/yu704645129/article/details/85855658