上一部分讲到 uboot 跳转到 start_armboot 处执行(中间插了一篇 异常中断处理)。
这次主要是记录 start_armboot 的实现。
文件为 /lib_arm/board.c
1、参数声明
1 void start_armboot (void)
2 {
3 init_fnc_t **init_fnc_ptr; //这里实际上是创建数组指针
//指向的数组为 start_armboot 之前的 init_sequence 数组
4 char *s;
5 #if defined(CONFIG_VFD) || defined(CONFIG_LCD)
6 unsigned long addr;
7 #endif
2、两个结构体与内存屏障
8
9 /* Pointer is writable since we allocated a register for it */
10 gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
11 /* compiler optimization barrier needed for GCC >= 3.4 */
12 __asm__ __volatile__('': : :'memory');
这里有两个结构体要展开
1)uboot所调用的配置信息,文件为/include/asm-arm/Global_data.h
typedef struct global_data {
bd_t *bd;
unsigned long flags;
unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */
unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long fb_base; /* base address of frame buffer */
#ifdef CONFIG_VFD
unsigned char vfd_type; /* display type */
#endif
#ifdef CONFIG_FSL_ESDHC
unsigned long sdhc_clk;
#endif
#if 0
unsigned long cpu_clk; /* CPU clock in Hz! */
unsigned long bus_clk;
phys_size_t ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
#endif
void **jt; /* jump table */
} gd_t;
2)板子所调用的板级配置信息,文件为/include/asm-arm/U-boot.h
typedef struct bd_info {
int bi_baudrate; /* serial console baudrate */
unsigned long bi_ip_addr; /* IP Address */
struct environment_s *bi_env;
ulong bi_arch_number; /* unique id for this board */
ulong bi_boot_params; /* where this board expects params */
struct /* RAM configuration */
{
ulong start;
ulong size;
} bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;
这里的 gd 实际指向了一个地址,地址位置可以看下图
注意,这里为小端模式
_bss_start
|
TEXT/DATA
| // = 0x100000 + 0x4000
CONFIG_SYS_MALLOC_LEN
| // = sizeof(gd_t)
gd_t // gd 实际指向的地址
| // = sizeof(bd_t)
bd_t // gd_t 的第一部分就是 bd_t
|
_armboot_start // 定义在 start.S 中
|
STACK // IRQ_STACK_START FIQ_STACK_START
然后是内存屏障
12 __asm__ __volatile__('': : :'memory');
简单理解起来就是:禁止编译器优化此处的汇编代码。
这样做,可以有效防止 编译器将当前的寄存器的值 直接替换在代码中。
这行代码大量地使用在内存屏障函数中,例如 mb()函数组。
更详细的介绍可以参详
http://blog.sina.com.cn/s/blog_7e741b830100wz1f.html
3、分配空间
13
14 memset ((void*)gd, 0, sizeof (gd_t)); //清空 gd 的对应空间
15 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); //设置 bd 指向地址
16 memset (gd->bd, 0, sizeof (bd_t)); //清空 bd 的对应空间
17
18 gd->flags |= GD_FLG_RELOC;
// #define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM*/
19
20 monitor_flash_len = _bss_start - _armboot_start;
4、初始化
21
22 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
23 if ((*init_fnc_ptr)() != 0) {
24 hang ();
25 }
26 }
这里的 hang 其实是死循环,函数如下
void hang (void)
{
puts ('### ERROR ### Please RESET the board ###n');
for (;;);
}
意味着如果有初始化函数不存在,或者初始化失败(返回不为0),则出错。
5、清空 code 区
27
28 /* armboot_start is defined in the board-specific linker script */
29 mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
30 CONFIG_SYS_MALLOC_LEN);
此处有
void mem_malloc_init(ulong start, ulong size)
{
mem_malloc_start = start;
mem_malloc_end = start + size;
mem_malloc_brk = start;
memset((void *)mem_malloc_start, 0, size);
}
6、之后有大量的可配置项,这些可配置项的内部实现都很简单清晰,所以仅列出标题了
32 #ifndef CONFIG_SYS_NO_FLASH
37 #ifdef CONFIG_VFD
50 #ifdef CONFIG_LCD
75 #ifdef CONFIG_HAS_DATAFLASH
7、变量搬移
79
80 /* initialize environment */
81 env_relocate ();
具体实现在 /common/Env_common.c 中
8、可配置项
83 #ifdef CONFIG_VFD
88 #ifdef CONFIG_SERIAL_MULTI
9、这一段代码量较长、不继续深入
主要功能看代码自注
复制代码
91
92 /* IP Address */
93 gd->bd->bi_ip_addr = getenv_IPaddr ('ipaddr');
94
95 stdio_init (); /* get the devices list going. */
96
97 jumptable_init ();
10、可配置项
99 #if defined(CONFIG_API)
11、控制台初始化
104 console_init_r (); /* fully init console as a device */
12、可配置项
106 #if defined(CONFIG_ARCH_MISC_INIT)
110 #if defined(CONFIG_MISC_INIT_R)
13、使能中断
114
115 /* enable exceptions */
116 enable_interrupts ();
14、可配置项
119 #ifdef CONFIG_DRIVER_TI_EMAC
129 #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
16、
137
138 /* Initialize from environment */
139 if ((s = getenv ('loadaddr')) != NULL) {
140 load_addr = simple_strtoul (s, NULL, 16);
141 }
17、可配置项
142 #if defined(CONFIG_CMD_NET)
148 #ifdef BOARD_LATE_INIT
152 #ifdef CONFIG_GENERIC_MMC
157 #ifdef CONFIG_BITBANGMII
160 #if defined(CONFIG_CMD_NET)
161 #if defined(CONFIG_NET_MULTI)
18、网卡设置
164 eth_initialize(gd->bd);
19、可配置项
165 #if defined(CONFIG_RESET_PHY_R)
20、进入主循环
170 /* main_loop() can return to retry autoboot, if so just run it again. */
171 for (;;) {
172 main_loop ();
173 }
174
175 /* NOTREACHED - no way out of command loop except booting */
文件路径为 /common/Main.c