为OMAP L138增加uboot启动画面

 

 

 

 

 

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

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

 

第一阶段TI官方提供的开发包里找到用CCS测试LCD 的程序将此程序稍作修改生成2个文件, my_lcd.hmy_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_LCDCONFIG_LCD_LOGO.于是寻找带这2个标记的代码段在添加这2个选项后 编译会报很多错主要因为需要指定一款LCD, UBOOT里没有对138的支持在 drvier/video里找到atmel 的驱动这个对LCD支持比较强准备在此基础上改把驱动的核心代码换成上面第一阶段的代码而思想就是对LCDC进行控制.此过程持续了2,3最终因为关联东西太多而放弃.

 

 

 

 

第三阶段参考HAWK

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

作为TI138的合作伙伴, hawkboard也出了开发板下载他的UBOOT代码,编译,可以看见启动画面了只是在ubootlinux直接会有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_CTR

*((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, hawd540, 而不论哪个值都会在ubootlinux切换的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;

// NANDlinux内核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%
}
}

 

你可能感兴趣的:(为OMAP L138增加uboot启动画面)