您的位置:首页 > 其它

为OMAP L138增加uboot启动画面

2010-12-08 15:42 162 查看
由于默认的UBOOT不支持OMAPL138开机画面, 所以需要手动移植, 我的移植分为3个阶段, 前2个阶段都以失败告终, 如果不想耽误时间可以直接跳转到第3阶段处.
先说说环境 OMAPL138 软件以TI为主, 开发板是我们自己做的, 仿真器是闻亭的

第一阶段: 在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%
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: