- 程序的加载
启动时候根据管脚BOOT_MODE0 BOOT_MODE1决定是正常启动还是usb烧录,根据BT_CFG1的配置来决定是从sd卡 mmc nand哪个里启动, 正常启动过程中cpu内有固化的程序会从例如nand前面读取一小部分数据,结构类似下面这样,左边是flash中的分布,右面是加载到内存之后的分布
这一小部分类似elf的头文件一样的IVT,记录着程序从flash加载到内存哪里从哪里启动, DCD是内存 时钟等一些需要预先初始化的寄存器列表。
这部分是uboot编译出来二进制文件之后,通过tools下的mkimage的imximage_generate函数生成的,并和生成的二进制文件组成imx文件,就是cpu固化的程序识别的镜像格式,其中entry是uboot入口的地址,也需要一起传进来
- 板卡的选择
在configs文件夹下有很多种板子的默认配置,例如
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_ddr3_arm2_nand_defconfig
就会根据mx6ull_14x14_ddr3_arm2_nand_defconfig生成默认.config 文件通过CONFIG_TARGET_MX6ULL_DDR3_ARM2 就取到了需要编译的文件和头文件
if TARGET_MX6ULL_DDR3_ARM2
config SYS_BOARD
default "mx6ull_ddr3_arm2"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "mx6ull_ddr3_arm2"
endif
其中
libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
include/configs/<CONFIG_SYS_CONFIG_NAME>.h
设置了要编译的板卡的目录和宏定义的目录
- 启动过程
整个程序的入口在u-boot.lds中ENTRY(_start)定义,在连接时候指定到CONFIG_SYS_TEXT_BASE宏上,这个地址也是1中要传给打包程序时候让cpu知道该把程序放到哪里,紧接着最前的一点程序因为会被cpu自动加载到内存里并执行,要放个程序加载整个镜像到内存里的程序
.text :
{
*(.__image_copy_start)
*(.vectors)
arch/arm/cpu/armv7/start.o (.text*)
*(.text*)
}
char __image_copy_start[0] __attribute__((section(".__image_copy_start")));
是一个空的数组,作用只是指向代码段的开头实际是和_start和中断向量表指向同一个地址
紧接着就是向量表和start.S中的reset中断的代码
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
设置中断向量表
然后继续会关mmu cache 设置sp 跳转到s_init _main 函数
最后,因为uboot适配了很多种平台 所以同一个函数很出现在很多文件中,有时候很难找到是使用哪个编译的,尝试了下可以通过查看那些文件生成.o了来查找,脚本
my $fun_name = shift;
my $cmd = 'find ./ -name "*.[sSc]" | xargs grep "'.$fun_name."\"";
my $output = `$cmd`;
my @a = split(/\n/, $output);
my %c_hash;
foreach my $line(@a){
if($line =~/^(.*?)\.[sSc]/){
$c_hash{$1} = 1;
}
}
my $output = `find ./ -name "*.o"`;
my @a = split(/\n/, $output);
my %o_hash;
foreach my $line(@a){
if($line =~/^(.*?)\.o/){
if( exists($c_hash{$1} ) ){
print "$1\n";
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。