开发环境:主机:Window XP SP2;linux:VMware7.01+ubuntu9.10;目标板:扬创utu2440-F开发板
交叉编译器:arm-linux-gcc4.3.2(一开始用的是编译内核的版本arm-linux-gcc3.4.1,但出现了软浮点问题,于是换成了现在用的版本,当然本人编译内核的时候还是用3.4.1版本)。
摘要:在上篇文章移植u-boot-2011.03到S3C2440(utu2440)方法与步骤###1. 配置和初步编译中介绍了如何配置和裁减u-boot-2.011.03,并通过了初步编译。在此基础上,本文通过修改reille2440.h文件、分析u-boot入口、修改start.S初始化代码段,利用tftp把编译出来的u-boot-2011.03镜像下载到SDRAM中,使其跑起来,可看到熟悉的u-boot启动信息。
1. 编辑include/configs/reille2440.h文件
把reille2440.h文件中的line38、39两行屏蔽掉,同时添加如下信息:
//#define CONFIG_S3C2410 1 /* specifically a SAMSUNG S3C2410 SoC 需要屏蔽该宏定义 */
//#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board 需要屏蔽该宏定义 */
#define CONFIG_S3C2440 1 /* specifically a SAMSUNG S3C2440 SoC */
#define CONFIG_REILLE2440 /* on a SAMSUNG reille2440 Board */
#define CONFIG_SKIP_LOWLEVEL_INIT
注意:
1) 打红色为添加信息(或者修改信息,以下同)
2) CONFIG_SKIP_LOWLEVEL_INIT是跳过底层一些初始化代码的宏开关,定义则跳过。如果编译的u-boot.bin用tftp下到SDRAM中运行,则需要定义该宏,特别注意!
3) 如果S3C2440的晶振用的不是12MHz的,则还需要修改CONFIG_SYS_CLK_FREQ的值!
2. uboot入口分析:
一般在嵌入式系统软件开发中,在所有源码文件编译完成之后,链接器要读取一个链接分配文件,在该文件中定义了程序的入口点、代码段、数据段等分配情况。对于2440开发板,u-boot的这个链接文件就是cpu/arm920t/u-boot.lds,打开该文件部分代码如下:
OUTPUT_FORMAT(“elf32-littlearm”, “elf32-littlearm”, “elf32-littlearm”)
OUTPUT_ARCH(arm) //定义生成文件的目标平台是arm
ENTRY(_start) //定义程序的入口点是_start
SECTIONS
{
//其他一些代码段、数据段等分配
. = 0x00000000;
. = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text)
*(.text)
}
………………
………………
}
知道了程序的入口点是_start,那么我们就打开2440开发板u-boot第一个要运行的程序cpu/arm920t/start.S,查找到_start的位置如下:
.globl _start
_start: b start_code //将程序的执行跳转到start_code处
从这个汇编代码可以看到程序又跳转到start_code处开始执行,那么再查找到start_code处的代码如下:
/*
* the actual start code
*/
start_code:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
bl coloured_LED_init //此处两行是对AT91RM9200DK开发板上的LED进行初始化的
bl red_LED_on
由此可以看到,start_code处才是u-boot启动代码的真正开始处。
3. 在arch/arm/cpu/arm920t/start.S文件中修改相关初始化代码:对S3C2440一些寄存器的支持、添加中断禁止部分和时钟设置部分
在start.S文件的164行至175行,用下面代码替换:
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
# if defined(CONFIG_S3C2440)
# define LOCKTIME 0x4C000000
# define MPLLCON 0x4C000004
# define UPLLCON 0x4C000008
# define CLKDIV_VAL 5
# define M_MDIV 0x7f /* XTal=12.0MHz MPLL=405MHz */
# define M_PDIV 2
# define M_SDIV 1
# define U_MDIV 0x38 /* XTal=12.0MHz UPLL=48MHz */
# define U_PDIV 2
# define U_SDIV 2
// 添加s3c2440的中断禁止部分
ldr r1, =0x7fff
ldr r0, =INTSUBMSK
str r1, [r0]
ldr r0,=LOCKTIME /* 设置U_LTIME和M_LTIME */
ldr r1,=0x0fff0fff
str r1,[r0]
ldr r0, =CLKDIVN /* Fclk:Hclk:Pclk = 1:4:8 */
ldr r1, =CLKDIV_VAL
str r1, [r0]
mrc p15, 0, r0, c1, c0, 0 /* 总线模式设为异步模式 */
orr r0, r0, #0xc0000000
mcr p15, 0, r0, c1, c0, 0
ldr r0,=UPLLCON /* 配置UPLL */
ldr r1,=((U_MDIV<<12) + (U_PDIV<<4) + U_SDIV)
str r1,[r0]
nop /* 为确保硬件完成操作,至少需7个时钟周期 */
nop
nop
nop
nop
nop
nop
ldr r0,=MPLLCON /* 配置MPLL */
ldr r1,=((M_MDIV<<12) + (M_PDIV<<4) + M_SDIV)
str r1,[r0]
#else
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C2440 */
#endif /* CONFIG_S3C24X0 */
S3C2440的时钟部分除了在start.S中添加外,还要在board/samsung/reille2440/reille2440.c修改或添加部分代码,如下:
#define FCLK_SPEED 2 //设置默认等于2
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
#elif FCLK_SPEED==2 /* 设置默认等于2 Fout = 405MHz */
#define M_MDIV 0x7F
#define M_PDIV 0x2
#define M_SDIV 0x1
#endif
#define USB_CLOCK 2
#if USB_CLOCK==0
#define U_M_MDIV 0xA1
#define U_M_PDIV 0x3
#define U_M_SDIV 0x1
#elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#elif USB_CLOCK==2 /* Fout = 48MHz */
#define U_M_MDIV 0x38
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2
#endif
int board_init (void)
{
……
gd->bd->bi_arch_number = MACH_TYPE_REILLE2440;
……
}
int dram_init (void)
{
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
// 此处非常重要,否则uboot启动不起来
gd->ram_size = PHYS_SDRAM_1_SIZE;
return 0;
}
MACH_TYPE_REILLE2440为linux内核机器码值,在include/asm/mach-types中添加定义如下:
#define MACH_TYPE_REILLE2440 5244
4. 编译并用tftp下载到SDRAM中运行
按上述修改完后,如果想编译后的u-boot.bin能下载到SDRAM中运行,则还需要修改一个地方!
修改board/samsung/reille2440/config.mk
CONFIG_SYS_TEXT_BASE = 0x33000000/*0x3f800000改为0x33000000 以便内存中调试*/
这是因为,在板运行的uboot已经占用了0x3f800000及其以上的地址,如果用tftp仍下载到SDRAM的这个地址,则在板运行的uboot则会死掉,你移植的uboot则下载不进SDRAM了!
修改完毕后,重新编译出u-boot.bin,然后用tftp下载到SDRAM中运行:
tftp 0x33000000 u-boot.bin
go 0x33000000
本人在移植的时候,由于在dram_init ()函数中忘记添加gd->ram_size = PHYS_SDRAM_1_SIZE; 导致uboot启动不起来,运行到下面的提示就不动了!
U-Boot 2011.03 (Jun 12 2011 – 18:58:57)
DRAM: 254.5 MiB
在dram_init()函数中添加gd->ram_size初始化后,就能正常启动了,如下所示:
utu-bootloader=>>>go 33000000
## Starting application at 0x33000000 …
U-Boot 2011.03 (Jun 12 2011 – 22:30:16)
DRAM: 64 MiB
Flash: 512 KiB
*** Warning – bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: raise: Signal # 8 caught
CS8900-0
[reille2440]#
至此,uboot移植工作至少完成了一部分工作了!如果有其他问题可以在include/configs/reille2440.h头文件中添加DEBUG宏用于调试。
5. 参考资料:
http://www.linuxidc.com/Linux/2011-02/32772p2.htm
推荐阅读相关文章:
- u-boot-2011.03移植系列专题汇总
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###8. u-boot引导启动nand flash中内核和cramfs格式根文件系统及用户文件系统yaffs2支持
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###7.NAND FLASH部分移植和支持NAND FLASH启动和读写
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###6.使用AXD和JLINK调试u-boot方法与步骤
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###5.使用JLINK间接烧写u-boot至FLASH的方法与步骤
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###4.支持内核启动
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###3.移植和配置CS8900网卡
- 移植u-boot-2011.03到S3C2440(utu2440)方法与步骤###1. 配置和初步编译
虽然没有看懂,但是觉得好厉害的样子啊。