执行完 board_init_f 后,跳回到 crt0.S中继续执行汇编语言
1 ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp,gd->start_addr_sp在fdt的初始位置 */ 2 bic r0, r0, #7 /* 8-byte alignment for ABI compliance */ 3 mov sp, r0 /* sp 指向 fdt 初始位置 */ 4 ldr r9, [r9, #GD_BD] /* r9 = gd->bd */ 5 sub r9, r9, #GD_SIZE /* new GD is below bd,r9 为 gd-t 的基地址 */ 6 7 adr lr, here /* 跳转到 here 处执行,gd->relocaddr = 0x3400 0000 */
最后一句,跳转到here处去执行
1 here: 2 /* 3 * now relocate vectors 4 */ 5 bl relocate_vectors /* 重定向向量表 */
一、relocate_vectors 重定向向量表
relocate.S (arch\arm\lib)
这一段主要是对前面所说的向量表进行重定向
1 /* 2 * Copy the relocated exception vectors to the 3 * correct address 4 * CP15 c1 V bit gives us the location of the vectors: 5 * 0x00000000 or 0xFFFF0000. 6 */ 7 ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr。0x3400 0000 */ 8 /* 将 c1 的值读到 r2 寄存器中 */ 9 /* 主要是控制 bit[13]: V */ 10 /* 对于支持高端异常向量表的系统,本控制位控制向量表的位置 */ 11 /* 0 :选择低端异常中断向量 0x0~0x1c */ 12 /* 1 :选择高端异常中断向量0xffff0000~ 0xffff001c */ 13 /* 对于不支持高端异常向量表的系统,读取时该位返回0,写入时忽略 */ 14 mrc p15, 0, r2, c1, c0, 0 /* V bit (bit[13]) in CP15 c1 */ 15 /* ands 后面的 s 会影响CPSR状态的寄存器的标志位 */ 16 /* 若 相与的 结果为0,则CPSR的状态标志位 Z = 1;反之,Z = 0 */ 17 ands r2, r2, #(1 << 13) /* r2 寄存器和 0010 0000 0000 0000 按位与后存入r2中 */ 18 ldreq r1, =0x00000000 /* If V=0,则Z=1,可执行 ldr指令 */ 19 ldrne r1, =0xFFFF0000 /* If V=1,则Z=0,可执行 ldr */ 20 /* 将 r2 -- r8 以及 r10 传入相应的地址,每次传输之后递增R0指向的存储地址,因为是32位,每次递增的地址应该是4bytes */ 21 ldmia r0!, {r2-r8,r10} /* ldmia 多寄存器寻址指令, */ 22 stmia r1!, {r2-r8,r10} /* 将R2-R8 和 r10的数据存储到R1指向的地址上,R1值更新。 */ 23 ldmia r0!, {r2-r8,r10} 24 stmia r1!, {r2-r8,r10} 25 #endif
二、relocate_code
here执行完后,跳回,执行下面的代码
1 ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off,gd->reloc_off = gd->relocaddr */ 2 add lr, lr, r0 /* lr += r0,异常向量表的地址确定 */ 3 /* 重定向地址确定 */ 4 ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr 为 0x3400 0000 - u-boot 大小,即在u-boot的起始地址处 */ 5 b relocate_code /* 重定向代码 */
进入 relocate_code, relocate.S (arch\arm\lib)
1 ENTRY(relocate_code) 2 /* __image_copy_start 在u-boot.lds 文件中定义,为起始地址 0 */ 3 ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */ 4 /* subs 影响借位C标志, */ 5 subs r4, r0, r1 /* r4 <- relocation offset ,r4 为重定向偏移量 */ 6 beq relocate_done /* skip relocation,C变为位为1则执行代码 */ 7 /* r2为需要重定位代码的结束地址,r2 - r1就是需要重定位代码长度了 */ 8 ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */ 9 10 /* 到现在为止,比较重要的几个寄存器的值为 11 * r0 = gd->reloc_off,r0为重定位偏移量,本处也就是目标地址 12 * r1 = __image_copy_start,r1为需要重定位代码当前的起始地址,也就是代码段的开始0 13 * r4 = r0 - r1,r4为重定位的偏移值,偏移值减去0还是0 14 * r2 =__image_copy_end,r2为需要重定位代码的结束地址,r2 - r1就是需要重定位代码长度了 15 */ 16 copy_loop: 17 /* 从源地址 [r1] 开始拷贝,pop到r10与r11里面,一次8个字节 */ 18 ldmia r1!, {r10-r11} /* copy from source address [r1] */ 19 /* 拷贝到目标地址 [r0] */ 20 stmia r0!, {r10-r11} /* copy to target address [r0] */ 21 /* 一直到 [r1] 等于 [r2], 说明代码拷贝结束 */ 22 cmp r1, r2 /* until source end address [r2] */ 23 blo copy_loop 24 25 /* 26 * fix .rel.dyn relocations 27 * 重定位修正 28 */ 29 ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */ 30 ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */ 31 fixloop: 32 ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ 33 and r1, r1, #0xff 34 cmp r1, #R_ARM_RELATIVE 35 bne fixnext 36 37 /* relative fix: increase location by offset */ 38 add r0, r0, r4 39 ldr r1, [r0] 40 add r1, r1, r4 41 str r1, [r0] 42 fixnext: 43 cmp r2, r3 44 blo fixloop 45 46 relocate_done: 47 48 #ifdef __XSCALE__ 49 /* 50 * On xscale, icache must be invalidated and write buffers drained, 51 * even with cache disabled - 4.2.7 of xscale core developer's manual 52 */ 53 mcr p15, 0, r0, c7, c7, 0 /* invalidate icache */ 54 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 55 #endif 56 57 /* ARMv4- don't know bx lr but the assembler fails to see that */ 58 59 #ifdef __ARM_ARCH_4__ 60 mov pc, lr 61 #else 62 bx lr 63 #endif 64 65 ENDPROC(relocate_code)
执行完后,跳回 crt0.S中继续执行
1 /* 2 * now relocate vectors 3 */ 4 bl relocate_vectors /* 重定向向量表 */ 5 6 /* Set up final (full) environment */ 7 bl c_runtime_cpu_setup /* we still call old routine here */ 8 9 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK) 10 11 ldr r0, =__bss_start /* this is auto-relocated! */ 12 ldr r1, =__bss_end /* this is auto-relocated! */ 13 mov r2, #0x00000000 /* prepare zero to clear BSS */ 14 15 clbss_l:cmp r0, r1 /* while not at end of BSS */ 16 strlo r2, [r0] /* clear 32-bit BSS word */ 17 addlo r0, r0, #4 /* move to next */ 18 blo clbss_l 19 20 #if ! defined(CONFIG_SPL_BUILD) 21 /* 这两个函数可以自己实现,或者删除掉 */ 22 bl coloured_LED_init 23 bl red_led_on 24 #endif 25 /* call board_init_r(gd_t *id, ulong dest_addr) */ 26 mov r0, r9 /* gd_t */ 27 ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */ 28 /* call board_init_r */ 29 ldr pc, =board_init_r /* this is auto-relocated! */ 30 /* we should not return here. */ 31 #endif
执行进入 board_init_r 中
三、board_init_r
1 void board_init_r(gd_t *new_gd, ulong dest_addr) 2 { 3 if (initcall_run_list(init_sequence_r)) 4 hang(); 5 /* NOTREACHED - run_main_loop() does not return */ 6 hang(); 7 }
功能函数得实现都在 init_sequeuece_r 中
1 static init_fnc_t init_sequence_r[] = { 2 initr_trace, /* 宏未定义,直接返回 0 */ 3 initr_reloc, /* gd->flags = 1 */ 4 /* TODO: could x86/PPC have this also perhaps? */ 5 #ifdef CONFIG_ARM 6 initr_caches, /* 打印 :Caches not enabled ,暂时未实现*/ 7 #endif 8 initr_reloc_global_data, /* 宏未定义,直接返回 0 */ 9 initr_barrier, /* 宏未定义,直接返回 0 */ 10 initr_malloc, /* malloc 区分配 */ 11 initr_bootstage, /* Needs malloc() but has its own timer */ 12 initr_console_record, /* 终端记录 */ 13 bootstage_relocate, /* 重定向启动阶段 */ 14 #if defined(CONFIG_ARM) || defined(CONFIG_NDS32) 15 board_init, /* Setup chipselects */ 16 #endif 17 stdio_init_tables, /* 设备表格初始化 */ 18 initr_serial, /* 初始化串口,执行得是 Serial.c (drivers\serial) 得serial_initialize()*/ 19 initr_announce, /* 打印 u-boot 运行信息 */ 20 INIT_FUNC_WATCHDOG_RESET 21 power_init_board, /* 执行得 board.c(common) 中得 */ 22 #ifdef CONFIG_MTD_NOR_FLASH 23 initr_flash, /* norflash 初始化 */ 24 #endif 25 INIT_FUNC_WATCHDOG_RESET 26 #ifdef CONFIG_CMD_NAND 27 initr_nand, /* nand flash 初始化 */ 28 #endif 29 initr_env, /* 环境变量初始化 */ 30 INIT_FUNC_WATCHDOG_RESET 31 initr_secondary_cpu, /* CPU第二阶段初始化,里面为空 */ 32 INIT_FUNC_WATCHDOG_RESET 33 stdio_add_devices, /* 宏未定义,里面执行为空 */ 34 initr_jumptable, /* jumptable 初始化 */ 35 console_init_r, /* fully init console as a device */ 36 INIT_FUNC_WATCHDOG_RESET 37 interrupt_init, /* 中断初始化 */ 38 #ifdef CONFIG_ARM 39 initr_enable_interrupts, /* 中断使能初始化 */ 40 #endif 41 /* PPC has a udelay(20) here dating from 2002. Why? */ 42 #ifdef CONFIG_CMD_NET 43 initr_ethaddr, /* 网络地址初始化 */ 44 #endif 45 #ifdef CONFIG_CMD_NET 46 INIT_FUNC_WATCHDOG_RESET 47 initr_net, /* 网络初始化 */ 48 #endif 49 run_main_loop, /* 启动 内核 */ 50 };
重新编译一下,编译OK了,制作补丁