1、程序入口
我们从什么地方去找入口呢,首先是打开顶层目录的makefile文件,在这个文件里面,每一个uboot支持的开发板都有一个配置选项,比如说,搜索smdk2440,结果如下
我们主要关注上图的右方那个红线处,它决定了开发板的名称smdk2440,拿到这个名称后,我们到目录boardsamsungsmdk2440下存放的文件就是开发板支持相关的一些文件;找到里面的u-boot.lds文件,那么我们uboot的整个链接就是用这个脚本文件来控制的,打开之
可知,在我们代码段最前端的是目录cpu/s3c24xx/下的start.c或者start.s文件,那么这个文件会得到最先运行,那么这个文件里面的那一段代码最先运行呢?
由链接器脚本可知
在start.s代码里面的标号_start处最先执行,也就是
2、分析第一阶段的代码--BL1
上面是设置中断向量表;
上面是设置处理器到SVC32模式,
上面是刷新I/D cache,然后是关闭MMU和cache;没有定义CONFIG_ONENAND这个宏,所以跳过
接下来执行
bl lowlevel_init
该函数位于对应开发板的lowlevel_init.S下
进入到该文件:
上面是初始化系统时钟,对串口进行汇编级的初始化,对nandflash进行简单的初始化,对内存的初始化,
然后,返回到上一级代码处:
判断是norflash还是nandflash,我们这里是nandflash,所以下面要拷贝nandflash剩下的内容
上面是拷贝nand_copy的内容,
上面是设置堆栈,为c语言编程做准备,清除bss段,
3、分析第二阶段的代码--BL2
在这个阶段通过ldr pc,_start_armboot,使程序进入内存中运行,那么下面来证明_start_armboot是不是在内存中
下面来证明_start_armboot在内存当中,
首先,对uboot进行配置
make smdk2440_config(这个来自于makefile里面)
然后,再执行一个make进行编译;
可以看到elf格式的uboot以及二进制格式的uboot.bin文件,
我们要查看_start_armboot的地址是多少,我们对u-boot.elf进行反汇编
打开dump文件且搜索底行命令格式下/_start_armboot
其入口地址为30001100,实际上它是内存里面的地址
往最前看,入口地方,如下:
上面的_start的地址为30000000,那么这个地址怎么来的,以及前面说过我们的第一阶段的程序不是在内存中运行而是在垫脚石中运行,垫脚石是从0地址开始的。
1、我们去链接一个程序的时候,如果这个程序由多个文件组成,那么它的链接地址是由链接器脚本决定的。
在uboot的顶层目录下面的config.mk里面,这个文件会被makefile包含进去,
代码段的基地址
那么这个TEXT_BASE在哪儿定义的呢?
在
如果TEXT_BASE修改为30008000,那么变化如下:
链接地址并不等于pc指针的值!!!!!!!!!!!!!!!!!!
如果是ldr pc,0x30008000,则pc指针的值就会为30008000
第二阶段程序分析
在这部分它会做一些硬件初始化和一些软件初始化(可能初始化环境变量等等)
分析:
首先分析上面的for循环,首先,使用一个指针指向一个函数数组,把数组里面的函数都取出来调用
上面函数里面,在硬件上对串口进行初始化,
上面是对LCD的初始化
上面是对网卡的初始化;以及初始化led;
main_loop()执行用户输入的命令!!它的作用是对用户输入到控制台的命令进行解析,并执行用户输入的命令。
下面是对6410的分析:
打开链接器脚本
跟上面分析差不多!!!
外设基地址初始化,这是6410上面才有的
上面有点亮led灯为了调试,然后是关闭看门狗,在2440上其实是有的,为什么他没有这个操作呢,其实它是有这个操作额,它做在系统时钟初始化里面,同时在里面还有关闭所有中断这个操作,这是在初始化系统时钟之前做的。
start_armboot是2440与6410共用的!!!
210初始化流程:
IROM(固化程序)把BL1(NANDFLASH中的)程序复制到IRAM中去,BL1的大小最大为16KB,在IRAM中运行的BL1会把NANDFLASH中后面的内容BL2复制到IRAM中剩下的地址中去,最大为80KB,如果还有的话,就只能往内存里面复制了。其实uboot编译出来BL2是大于80KB的,所以uboot还是采用往内存中去复制的这种情况,
在2440和6410里面的BL1和BL2是烧写到同一个bin文件里面的,而在210中是把BL1和BL2烧写到不同的bin文件中的,
BL1是位于下面
然后打开u-boot-spl.lds文件,它决定了BL1是怎么产生出来的