u-boot第二阶段分析(二)
2017-06-26 23:24
316 查看
start_armboot函数(二)
注:本次分析的u-boot是九鼎官方的u-boot代码下载地址:链接:http://pan.baidu.com/s/1gfpDZqj 密码:7cqe
接着上一章节的内容,继续往下分析start_armboot函数;
1.for循环执行init_sequence
代码如下:
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } }
分析代码:
(1)init_fnc_ptr二重指针指向了init_sequence,init_sequence是一个函数指针数组,数组中存储了很多个函数指针,这些指向指向的函数都是init_fnc_t类型(特征是接收参数是void类型,返回值是int)。
init_sequence在定义时就同时给了初始化,初始化的函数指针都是一些函数名。(函数名的实质就是函数指针)
代码如下:
typedef int (init_fnc_t) (void); init_fnc_t *init_sequence[] = { cpu_init, /* basic cpu dependent setup */ #if defined(CONFIG_SKIP_RELOCATE_UBOOT) reloc_init, /* Set the relocation done flag, must do this AFTER cpu_init(), but as soon as possible */ #endif board_init, /* basic board dependent setup */ interrupt_init, /* set up exceptions */ env_init, /* initialize environment */ init_baudrate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ consol 4000 e_init_f, /* stage 1 init of console */ display_banner, /* say that we are here */ #if defined(CONFIG_DISPLAY_CPUINFO) print_cpuinfo, /* display cpu info (and speed) */ #endif #if defined(CONFIG_DISPLAY_BOARDINFO) checkboard, /* display board info */ #endif #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) init_func_i2c, #endif dram_init, /* configure available RAM banks */ display_dram_config, NULL, };
(2)for循环的条件是*init_fnc_ptr,也就是*init_fnc_ptr != NULL;
遍历指针数组一般有两种方法,一种是根据数组下标来进行遍历,第二种是在数组的有效元素末尾放一个标志,依次遍历到标准处即可截至。代码中的for循环遍历方式采用的是第二种方式,这张遍历方式的好处是不用知道数组元素的个数,可以在数组中进行增减元素。
(3)init_fnc_t的这些函数的返回值定义方式一样的,都是:函数执行正确时返回0,不正确时返回-1.所以我们在遍历时去检查函数返回值,如果遍历中有一个函数返回值不等于0则hang()挂起。从分析hang函数可知:uboot启动过程中初始化板级硬件时不能出任何错误,只要有一个错误整个启动就终止,除了重启开发板没有任何办法。hang()代码如下:
void hang (void) { puts ("### ERROR ### Please RESET the board ###\n"); for (;;); }
下面对数组里的函数名逐个分析:
2.cpu_init
这个是cpu内部的初始化,在u-boot的第一阶段已经完成了,所以这里的函数体为空的;
3.board_init
board_init在uboot/board/samsung/x210/x210.c中,这个看名字就知道是x210开发板相关的初始化,代码如下:
int board_init(void) { DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_DRIVER_SMC911X smc9115_pre_init(); #endif #ifdef CONFIG_DRIVER_DM9000 dm9000_pre_init(); #endif gd->bd->bi_arch_number = MACH_TYPE; gd->bd->bi_boot_params = (PHYS_SDRAM_1+0x100); return 0; }
(1)我们使用的网卡型号是dm9000,所以dm9000_pre_init()可以得到运行,函数主要功能是网卡的初始化。CONFIG_DRIVER_DM9000这个宏是x210_sd.h中定义的,这个宏用来配置开发板的网卡的。开发板移植uboot时,如果要移植网卡,主要的工作就在这里。
这个函数中主要是网卡的GPIO和端口的配置,而不是驱动。因为网卡的驱动都是现成的正确的,移植的时候驱动是不需要改动的,关键是这里的基本初始化,因为这些基本初始化是硬件相关的。
(2)gd->bd->bi_arch_number = MACH_TYPE;
这句代码是将机器码的值赋值给bi_arch_number。
(1)bi_arch_number是board_info中的一个元素,含义是:开发板的机器码。所谓机器码就是uboot给这个开发板定义的一个唯一编号。
(2)机器码的主要作用就是在uboot和linux内核之间进行比对和适配。
(3)嵌入式设备中每一个设备的硬件都是定制化的,不能通用。嵌入式设备的高度定制化导致硬件和软件不能随便适配使用。这就告诉我们:这个开发板移植的内核镜像绝对不能下载到另一个开发板去,否则也不能启动,就算启动也不能正常工作,有很多隐患。因此linux做了个设置:给每个开发板做个唯一编号(机器码),然后在uboot、linux内核中都有一个软件维护的机器码编号。然后开发板、uboot、linux三者去比对机器码,如果机器码对上了就启动,否则就不启动(因为软件认为我和这个硬件不适配)。
(4)MACH_TYPE在x210_sd.h中定义,值是2456,并没有特殊含义,只是当前开发板对应的编号。这个编号就代表了x210这个开发板的机器码,将来这个开发板上面移植的linux内核中的机器码也必须是2456,否则就启动不起来。
(5)uboot中配置的这个机器码,会作为uboot给linux内核的传参的一部分传给linux内核,内核启动过程中会比对这个接收到的机器码,和自己本身的机器码相对比,如果相等就启动,如果不想等就不启动。
(6)理论上来说,一个开发板的机器码不能自己随便定。理论来说有权利去发放这个机器码的只有uboot官方,所以我们做好一个开发板并且移植了uboot之后,理论上应该提交给uboot官方审核并发放机器码(好像是免费的)。但是国内的开发板基本都没有申请(主要是因为国内开发者英文都不行,和国外开源社区接触比较少),都是自己随便编号的。随便编号的问题就是有可能和别人的编号冲突,但是只要保证uboot和kernel中的编号是一致的,就不影响自己的开发板启动。
(3)gd->bd->bi_boot_params = (PHYS_SDRAM_1+0x100);
这句代码是linux内核启动时的传参的内存地址赋值给bi_boot_params。
(1)bd_info中另一个主要元素,bi_boot_params表示uboot给linux kernel启动时的传参的内存地址。也就是说uboot给linux内核传参的时候是这么传的:uboot事先将准备好的传参(字符串,就是bootargs)放在内存的一个地址处(就是bi_boot_params),然后uboot就启动了内核(uboot在启动内核时真正是通过寄存器r0 r1 r2来直接传递参数的,其中有一个寄存器中就是bi_boot_params)。内核启动后从寄存器中读取bi_boot_params就知道了uboot给我传递的参数到底在内存的哪里。然后自己去内存的那个地方去找bootargs。
(2)PHYS_SDRAM_1是第一个内存片的起始地址,大小为0x30000000。所以经过计算,X210中bi_boot_params的值为0x30000100
相关文章推荐
- u-boot源码分析 --- 启动第二阶段002
- u-boot源码分析 --- 启动第二阶段004
- u-boot-2010.06 源码分析<3>--第二阶段
- u-boot源码分析 --- 启动第二阶段003
- U-Boot启动第二阶段代码分析
- u-boot第二阶段board.c分析
- u-boot-1.1.6 源码分析(3)--第二阶段
- u-boot源码分析 --- 启动第二阶段001
- u-boot源码分析 --- 启动第二阶段006
- u-boot源码分析 --- 启动第二阶段005
- u-boot源码分析 --- 启动第二阶段 ,基于2410 启动代码 分析
- U-Boot 启动过程和源码分析(第二阶段)
- u-boot第二阶段源码分析
- 图解U-Boot:第二阶段源码分析
- u-boot源码分析 --- 启动第二阶段003
- u-boot源码分析 --- 启动第二阶段 ,基于2410 启动代码 分析
- 图解U-Boot:第二阶段源码分析
- u-boot源码分析 --- 启动第二阶段004
- 图解U-Boot:第二阶段源码分析
- U-Boot学习-第二阶段代码分析