u-boot bootloader 代码学习之关键

在阅读uboot(u-boot)代码的时候,很多人首先被.word搞晕了,为什么使用.word,其实与调用有关

大家首先好好理解汇编代码:

ldr pc, main_loop

// 换一下代码 ldr pc, =main_loop

main_loop:

    .word test_code

    b main_loop

test_code:

    b test

在bootloader中使用的第一种,没有加=的代码。调用main_loop, 其实是让pc指向test_code的地址

 

调用ldr时,什么时候使用有=的代码

ldr pc, =main_loop

main_loop:

    // 此注释代码千万不可以打开 .word test_code

    b main_loop

此时如果取消注释,哈哈:),让程序飞吧!!

 

ldr, mov 命令之比较:

ldr地址相关,mov地址无关

我说一个关键点,可能大家不曾思考:

ldr r1, =0x50000000

ldr r1, =0x50000011

这两句编译生成的代码并不一样,通过arm-linux-objdump可以看到

第一句:

   0:   e3a00205        mov     r0, #1342177280 ; 0x50000000

第二句:

   0:   e51f0004        ldr     r0, [pc, #-4]   ; 4 <.text+0x4>
   4:   50000011        andpl   r0, r0, r1, lsl r0
第一个值能用立即数表示,mov指令就行了

第二句不能用立即数表示,不能不使用ldr指令

其实Arm还是很聪明的嘛!第一句能节省一个指令空间,代码size减少了4字节啊!

如果非要看看第一句也使用ldr指令,大概是这样的汇编,当然不会是真的:

   0:   e51f0004        ldr     r0, [pc, #-4]   ; 4 <.text+0x4>
   4:   50000000       。。。。。。

 

 

Uboot 分析(2010.09版):

拿到源代码,如果解压之后,通常执行两个步骤(假设smdk2410)

#make smdk2410_config

#make all

如果不能确定是否运行***_config,期望一个干净的环境,可以首先执行:

#make distclean

 

运行make ****_config?检查Makefile

%_config:: unconfig
 @$(MKCONFIG) -A $(@:_config=)
.......

#还有:

galaxy5200_config: unconfig

....

MVBC_P_config: unconfig
......

不能搜索到smdk2410_config in Makefile,所以选择运行:

%_config:: unconfig
 @$(MKCONFIG) -A $(@:_config=)

MKCONFIG := $(SRCTREE)/mkconfig

等同于./mkconfig -A smdk2410,其实调用当前目录下的脚本mkconfig执行。

 

如果板子是MVBC_P_config, 运行:make MVBC_P_config,则选择不一样了。

mkconfig中:

if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then
 # Automatic mode
 line=`egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg` || {
  echo "make: *** No rule to make target \`$2_config'.  Stop." >&2
  exit 1
 }

 set ${line}
 # add default board name if needed
 [ $# = 3 ] && set ${line} ${1}
fi

条件为真,set ${line}, 嘿嘿,参数改变了,变为了:

./mkconfig smdk2410 arm arm920t  -  samsung  s3c24x0

运行命令,看看结果:

echo $1 

echo $2

 

 

 lds的部分理解,在arch\arm\cpu\arm920t\u-boot.lds中

 . = .;
 __u_boot_cmd_start = .;
 .u_boot_cmd : { *(.u_boot_cmd) }
 __u_boot_cmd_end = .;

 在include/command.h中

#define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

凡是用U_BOOT_CMD进行声明的变量,作为cmd_tbl_t类型的变量,这些变量放到.u_boot_cmd中,不放到普通的.text中。

 

 进行代码移植的时候,通常会新建自己的板子,时间长了,忘了是什么名字。

make ***_config

可以查看boards.cfg,我们会定义自己新建的板子,找到就知道了。

 

如果把u-boot移动了位置,再次编译的时候会失败。

比如原来放在/root/u-boot-test,移动为/root/u-boot-new目录。

#make clean

#make all

清空*.o文件后编译会提示:

make[1]: Entering directory `/root/work/friendlyArm/code_test/bootloader/test/u-boot-2010.09redo/tools'
make[1]: *** No rule to make target `/root/u-boot-test/lib/crc32.c', needed by `crc32.o'.  Stop. 

因为/root/u-boot-test已经不存在了。所以还需要删除所有依赖关系:

#find . -name "*.depend"   //可以看见生成的依赖关系文件

#find . -name "*.depend" -exec rm -fr {} \;

 

 

我也是新手,欢迎大家拍砖:)

共同进步!

 

 

 

 

 

 

 

你可能感兴趣的:(u-boot bootloader 代码学习之关键)