uboot代码解析
废话:想了很久,还是决定花点时间去把uboot这个bootloader代码重头看到尾看一遍把,
既然我写不出来,那我看不须看懂吧,不能只是照着各种手册,改一下然后编译再download就完事
了!
#CURDIR
是
make
的内嵌变量,自动设置为当前目录
make tq2400_config
:
Makefile:
tq2440_config:unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t tq2440 NULL s3c24x0
$(@:_config=)就是将_config去掉
mkconfig tq2400 arm arm920t tq2440 NULL s3c24x0
mkconfig:
[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
board_name=tq2440
ln -s asm-$2 asm #asm ->asm-arm
ln -s ${LNPREFIX}arch-$6 asm-$2/arch #asm-arm/arch ->arch-s3c24x0
ln -s ${LNPREFIX}proc-armv asm-$2/proc #proc -> proc-armv
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux- ;若$(ARCH)=arm,
BOARDDIR = $(BOARD)
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk # include board specific rules
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
编译u-boot步骤:
1.board下构建目标板xxx的目录:内容:
2.include/config 内建立一个目标板的头文件,xxx.h :该头文件包含两类宏:
1.选项options,CONFIG_ ,它用于选择CPU,SOC,开发板类型,设置系统时钟,选择设备驱动。
Eg:
#define CONFIG_ARM920T 1
#define CONFIG_S3C2440 1
#define CONFIG_TQ2440 1
2.参数setting,CFG_前缀,它用于设置malloc缓存池,加载地址等等。
i
start.s:
b reset;
1.初始化:a.设svc模式
b.关看门狗
c.屏蔽中断
d.初始化sdram
e.设置栈
f.时钟
start-armboot ->flash_int->nand_int->main_loop->run_command->u_boot_cmd
u_boot_cmd内寻找命令名称所在结构体cmd->name ,找到其结构体内的命令函数并运行。
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
struct cmd_tbl_s {
char *name;
int maxargs;
int repeatable;
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char *usage;
#ifdef CFG_LONGHELP
char *help;
#endif
#ifdef CONFIG_AUTO_COMPLETE
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};
__u_boot_cmd_##name __attribute__ ((unused,section (".u_boot_cmd")))= {#name, maxargs, rep, cmd, usage, help}
U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)//相当于定义了一个在.u_boot_cmd段里面的结构体。
start.S:
.globl _start
@定义_start段为全局的。
_start: b
reset
@b,位置无关码,跳转到reset标号的内存地址处
_TEXT_BASE:
.word TEXT_BASE
@
先来分析一下nor启动和nand启动与sdram的关系,根据/board/tq2440/config.mk 定义用于运行地址TEXT_BASE = 0x33F80000 由上图可知从nor uboot中download to sdram和nand启动TEXT_BASE是不同的,本tq2440开发板sdram64mb=0x4000000,基址为0x30000000,所以sdram的地址范围为0x30000000~0x34000000。
.globl _armboot_start
@定义_armboot_start段为全局的,
_armboot_start:
.word _start
@定义一个字其内容为_start标号的地址
.globl _bss_start
@定义全局段_bss_start的地址,在lds链接脚本中
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
reset:
mrs r0,cpsr
@复制cpsr 到r0
bic r0,r0,#0x1f
@bic dest = op_1 AND (~op_2),所以这里是将r0低6位置0
orr r0,r0,#0xd3
@或 | mm=11,进入svc模式
msr cpsr,r0
@cpsr=r0
#if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008
# define CLKDIVN 0x14800014
#elif defined(CONFIG_S3C2410)
# define pWTCON 0x53000000
# define INTMSK 0x4A000008
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014
#endif
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
ldr
r0, =pWTCON
@r0=&pWTCON
mov
r1, #0x0
str
r1, [r0]
@[[r0]]=[r1]
,存储r1的内容到r0内容表示的内存地址单元中
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
//用来判断是从nand启动的还是只是调试uboot时的,即开发板从nor flash启动,code download to sdram to start
bl cpu_init_crit
#endif
stack_setup:
ldr r0, _TEXT_BASE
sub r0, r0, #CFG_MALLOC_LEN
sub r0, r0, #CFG_GBL_DATA_SIZE
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12
bl clock_init
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:
adr r0, _start
ldr r1, _TEXT_BASE
cmp
r0, r1
beq
clear_bss
#if 1
bl
CopyCode2Ram
#else
add r2, r0, r2
copy_loop:
ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r0, r2
ble copy_loop
#endif
#endif
clear_bss:
ldr r0, _bss_start
ldr r1, _bss_end
mov r2, #0x00000000
clbss_l:
str r2, [r0]
add r0, r0, #4
cmp r0, r1
ble clbss_l
ldr pc, _start_armboot
_start_armboot: .word start_armboot