1. U-Boot源码下载地址
http://sourceforge.net/project/u-boot
ftp://ftp.denx.de/pub/u-boot/
U-BOOT邮件列表下载:
http://lists.sourceforge.net/lists/listinfo/u-boot-users/
DENX相关的网站:
http://www.denx.de/re/DPLG.html
2. 源码文件的删除
二、U-Boot移植过程
1. 修改Makefile文件
依照1897和1880,增加1882和1883两行,如下图所示:
arm:表示现在用的CPU的架构就是ARM体系结构
arm920t:指这是CPU的内核类型,它对应于cpu/arm920t
smdk2410:这是开发板的型号,它的目录在board/smdk2410目录下,在这
里可以命名自己的开发板,如我的是lwj2440
s3c24x0:表示开发板上的CPU是啥
2. 建立自己的开发板
(1)进入源码u-boot-1.1.6目录下,将board/smdk2410目录复制为lwj2440
cp -rf board/smdk2410 board/lwj2440
(2)修改board/lwj2440目录下的smdk2410.c为lwj2440.c
mv board/lwj2440/smdk2410.c board/lwj2440/lwj2440.c
3. 建立自己的配置文件
在include/configs目录下建立一个配置文件lwj2440.h,将include/configs/smdk2410.h直接复制为lwj2440.h
cp include/configs/smdk2410.h include/configs/lwj2440.h
4. 修改Makefile
修改board/lwj2440/Makefile,把原来的28行改为第29行的内容
5. 修改交叉编译工具的路径
在顶层Makefile中原始内容如下:
当不修改时,此时用默认的交叉编译工具,我的是EABI4.4.3
当想换其它交叉编译工具时,修改第128行,比如我想用3.4.5的,修改如下:
6. 编译并测试
进入u-boot-1.1.6目录
# make distclean
# make lwj2440_config
# make all
如果没有错误,则会生成u-boot.bin文件、U-Boot文件、U-Boot.srec文件
u-boot.bin:二进制可执行文件,可以直接烧入ROM、NOR FLASH的文件
U-Boot:ELF格式的可执行文件
U-Boot.srec:Motorola S-Record格式的可执行文件
如果想编译时产生u-boot的反汇编代码,在顶层Makefile中查找u-boot.bin那一行:
修改如下所示:
即在原来代码上添加了 $(obj)u-boot.dis
三、增加对S3C2440的支持
1.修改SDRAM配置
SDRAM的初始化在U-Boot的第一阶段完成,就是在board/lwj2440/lowlevel_init.S文件中设置存储控制器
进入board/lwj2440/lowlevel_init.S,修改54和58行,如下所示:
再次进行修改第126行:
#define REFCNT 1113
/*period=15.6us,HCLK=60Mhz,(2048+1-15.6*60)*/
改为如下所示:
#define REFCNT 0x4f4
/*period=7.8125us,HCLK=100Mhz,(2048+1-7.8125*100)*/
2.修改时钟配置
对于S3C2440开发板,将FCLK设为400Mhz,分频率比为FCLK:HCLK:PCLK=1:4:8,而且将UPLL设为48Mhz,即UCLK为48Mhz
(1) 首先屏蔽掉原来S3C2410的时钟设置,修改cpu/arm920t目录下的start.S文件,大概148,其修改如下所示:
(2) 然后重新配置时钟,修改board/lwj2440/lwj2440.c文件中的board_init函数(68行),同时在第33行增加一些声明,如下所示修改:
添加的声明:
上图针对S3C2410、S3C2440分别定义了MPLL、UPLL寄存器的值,开发板输入时钟为12MHZ(在include/configs/lwj2440.h中的宏CONFIG_SYS_CLK_FREQ中定义)
对board_init函数的修改如下:
int board_init (void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
/* set up the I/O ports */
gpio->GPACON = 0x007FFFFF;
gpio->GPBCON = 0x00044555;
gpio->GPBUP = 0x000007FF;
gpio->GPCCON = 0xAAAAAAAA;
gpio->GPCUP = 0x0000FFFF;
gpio->GPDCON = 0xAAAAAAAA;
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA;
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA;
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA;
gpio->GPHUP = 0x000007FF;
/* support both of S3C2410 and S3C2440*/
if((gpio->GSTATUS1 == 0x32410000) || (gpio->GSTATUS1 == 0x32410002))
{
/* FCLK:HCLK:PCLK = 1:2:4 */
clk_power->CLKDIV = S3C2410_CLKDIV;
/* change for asynchronous bus mod*/
__asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register*/
"orr r1, r1, #0xc0000000\n" /* Asynchronous */
"mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register*/
:::"r1"
);
/* set PLL lock time*/
clk_power->LOCKTIME = 0xFFFFFFFF;
/* configure MPLL*/
clk_power->MPLLCON = S3C2410_MPLL_200MHZ;
/* some delay between MPLL and UPLL*/
delay(4000);
/*configure UPLL*/
clk_power->UPLLCON = S3C2410_UPLL_48MHZ;
/* have a delay again */
delay(8000);
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
}
else
{
/* FCLK:HCLK:PCLK = 1:4:8 */
clk_power->CLKDIV = S3C2440_CLKDIV;
/* change for asynchronous bus mod*/
__asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register*/
"orr r1, r1, #0xc0000000\n" /* Asynchronous */
"mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register*/
:::"r1"
);
/* set PLL lock time*/
clk_power->LOCKTIME = 0xFFFFFFFF;
/* configure MPLL*/
clk_power->MPLLCON = S3C2440_MPLL_400MHZ;
/* some delay between MPLL and UPLL*/
delay(4000);
/*configure UPLL*/
clk_power->UPLLCON = S3C2440_UPLL_48MHZ;
/* have a delay again */
delay(8000);
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
}
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;
icache_enable();
dcache_enable();
return 0;
}
(3)获取系统时钟的函数需要针对S3C2410、S3C2440的不同进行修改(get_PCLK)
在后面设置串口波特率时需要获得系统时钟,就是在U-Boot的第二阶段,lib_arm/board.c中start_armboot函数调用serial_init函数初始化串口时,会调用get_PCLK函数 ,在cpu/arm920t/s3c2440/speed.c中定义,与它相关的还有get_HCLK、get_PLLCLK函数
前面的程序board_init函数在识别出S3C2410或S3C2440后,设置机器ID:gd->bd->bi_arch_number,后面的函数可以通过它来分辨是S3C2410还是S3C2440。
在cpu/arm920t/s3c2440/speed.c 中修改如下所示:
1) 在第40添加一行,如下所示:
这样才可以使用gd变量
2) 修改get_PLLCLK函数(第54行)
修改原因:S3C2410和S3C2440的MPLL、UPLL计算公式不一样,如下所示:
static ulong get_PLLCLK(int pllreg)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
ulong r, m, p, s;
if (pllreg == MPLL)
r = clk_power->MPLLCON;
else if (pllreg == UPLL)
r = clk_power->UPLLCON;
else
hang();
m = ((r & 0xFF000) >> 12) + 8;
p = ((r & 0x003F0) >> 4) + 2;
s = r & 0x3;
/* support both of S3C2410 and S3C2440*/
if(gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
return ((CONFIG_SYS_CLK_FREQ * m) / (p << s));
else
return ((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); /* S3C2440*/
}
3)修改get_HCLK、get_PCLK函数(第84行开始)
/* for s3c2440*/
#define S3C2440_CLKDIVN_PDIVN (1<<0)
#define S3C2440_CLKDIVN_HDIVN_MASK (3<<1)
#define S3C2440_CLKDIVN_HDIVN_1 (0<<1)
#define S3C2440_CLKDIVN_HDIVN_2 (1<<1)
#define S3C2440_CLKDIVN_HDIVN_4_8 (2<<1)
#define S3C2440_CLKDIVN_HDIVN_3_6 (3<<1)
#define S3C2440_CLKDIVN_UCLK (1<<3)
#define S3C2440_CAMDIVN_CAMCLK_MASK (0xf<<0)
#define S3C2440_CAMDIVN_CAMCLK_SEL (1<<4)
#define S3C2440_CAMDIVN_HCLK3_HALF (1<<8)
#define S3C2440_CAMDIVN_HCLK4_HALF (1<<9)
#define S3C2440_CAMDIVN_DVSEN (1<<12)
/* return HCLK frequency */
ulong get_HCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
unsigned long clkdiv;
unsigned long camdiv;
int hdiv = 1;
/* support both of S3C2410 and S3C2440*/
if(gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 :
get_FCLK());
else
{ clkdiv = clk_power->CLKDIVN;
camdiv = clk_power->CAMDIVN;
/* caculate clock scalings */
switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK){
case S3C2440_CLKDIVN_HDIVN_1:
hdiv = 1;
break;
case S3C2440_CLKDIVN_HDIVN_2:
hdiv = 2;
break;
case S3C2440_CLKDIVN_HDIVN_4_8:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 :4;
break;
case S3C2440_CLKDIVN_HDIVN_3_6:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 :3;
break;
}
return get_FCLK() / hdiv;
}
}
/* return PCLK frequency */
ulong get_PCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
unsigned long clkdiv;
unsigned long camdiv;
int hdiv = 1;
/* support both of S3C2410 and S3C2440*/
if(gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 :
get_HCLK());
else
{ clkdiv = clk_power->CLKDIVN;
camdiv = clk_power->CAMDIVN;
/* caculate clock scalings */
switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK){
case S3C2440_CLKDIVN_HDIVN_1:
hdiv = 1;
break;
case S3C2440_CLKDIVN_HDIVN_2:
hdiv = 2;
break;
case S3C2440_CLKDIVN_HDIVN_4_8:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 :4;
break;
case S3C2440_CLKDIVN_HDIVN_3_6:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 :3;
break;
}
return get_FCLK() /hdiv/((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2:1);
}
}
(4)在“include/s3c24x0.h”中重新定义S3C24X0_CLOCK_POWER结构体
在s3c24x0.h中的S3C24X0_CLOCK_POWER结构体中增加如下两行:129和130
到这时,时钟部分基本上做好了,为了方便调试,可以利用开发板自带的UBOOT烧写到内存中运行
(5)便于调试UBOOT的修改
修改“cpu/arm920t/start.S”文件的第162行:
修改“boar/lwj2440/config.mk”文件的第25行:
#TEST_BASE = 0x33F80000
TEST_BASE = 0x33000000
待续。。。。。。。。。。。。。