uboot 代码执行顺序
ref:http://blog.chinaunix.net/uid-30352139-id-5128405.html
uboot: 2014.07
1.1 U-boot相关文件
boards.cfg:
ARCH = ARM
CPU = ARMv7
SOC = exynos
BOARD = smdkc210
VENDER = samsung
files:
Include/configs/smdkc210.h
arch/$(ARCH)/cpu/$(CPU)/start.S
board/$(VENDER)/$(BOARD)/smdkc210.c
arch/$(ARCH)/lib/board.c
arch/$(ARCH)/lib/crto.S
arch/$(ARCH)/lib/relocate.S
1.2 初始化流程
1) start.S -> _start
2) start.S -> reset
3) crt0.S -> _main ==>> board.c -> board_init_f
4) relocate.S -> relocate_code
5) crt0.S -> here
6) board.c -> board_init_r
7) main.c -> main_loop
1.3 初始化实现(以ARM为例)
《ARM Cortex-A Series Programmer’s Guide》中列出了Cortex-A系列的初始化方法(第十三章:Boot Code)。
ARM启动时,会从异常向量表的reset异常处启动(0或0xffff0000)。对于u-boot,不需要实现所有启动流程,只需要实现几个必须的程:
1) Initialize exception vectors.
1) Initialize the memory system, including the MMU.
1) Initialize core mode stacks and registers.
1) Initialize any critical I/O devices.
1) Call the main()application.
code |
comments |
.globl _start _start: b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq _undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt _prefetch_abort: .word prefetch_abort _data_abort: .word data_abort _not_used: .word not_used _irq: .word irq _fiq: .word fiq _pad: .word 0x12345678 /* now 16*4=64 */ .global _end_vect _end_vect: .balignl |
初始化中断向量表 (Initialize exception vectors) 中断向量表 |
reset: bl save_boot_params /* * disable interrupts (FIQ and IRQ), also set * except if in HYP mode already */ mrs r0, cpsr and r1, r0, #0x1f @ mask mode bits teq r1, #0x1a @ test for HYP mode bicne r0, r0, #0x1f @ clear all mode bits orrne r0, r0, #0x13 @ set SVC mode orr r0, r0, #0xc0 @ disable FIQ and IRQ msr cpsr,r0 |
禁止中断 (FIQ and IRQ), 设置CPU模式为SVC32 (Initialize core mode stacks and registers.) |
/* Set mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register bic r0, #CR_V @ V = 0 mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register /* Set ldr r0, =_start mcr p15, 0, r0, c12, c0, 0 @Set VBAR |
设置中断向量表 (Initialize exception vectors) |
ENTRY(cpu_init_cp15) /* * Invalidate L1 I/D */ mov r0, #0 @ set up for MCR mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs mcr p15, 0, r0, c7, c5, 0 @ invalidate icache mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array mcr p15, 0, r0, c7, c10, 4 @ DSB mcr p15, 0, r0, c7, c5, 4 @ ISB |
Invalidate L1 I/D cache (Initialize |
/* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002000 @ clear bits 13 (--V-) bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache mcr p15, 0, r0, c1, c0, 0 mov pc, lr @ back to my caller |
禁止 MMU and caches (Initialize |
ENTRY(_main) /* * Set up */ ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ sub sp, #GD_SIZE /* allocate one GD above SP */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ mov r9, sp /* GD is above SP */ |
设置C运行环境 (Initialize core mode stacks and registers.) |
mov r0, #0 bl board_init_f |
调用 board_init_f(0) 对串口进行初始化(Initialize any critical I/O devices) |
/* * Set up * * 'here' but */ ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ ldr r9, [r9, #GD_BD] /* r9 = gd->bd */ sub r9, r9, #GD_SIZE /* new GD is below bd */ |
设置临时运行环境 |
adr lr, here ldr r0, [r9, #GD_RELOC_OFF] /* add lr, lr, r0 ldr r0, [r9, #GD_RELOCADDR] /* b relocate_code here: |
代码重定向,保证u-boot迁入内存后能够正常运行 (Relocate the code) |
ENTRY(c_runtime_cpu_setup) /* * invalidate */ mcr p15, 0, r0, c7, c5, 0 @ invalidate icache mcr p15, 0, r0, c7, c10, 4 @ DSB mcr p15, 0, r0, c7, c5, 4 @ ISB |
这几步操作前面已经进行过,感觉可以去掉 |
/* * Move */ /* Set ldr r0, =_start mcr p15, 0, r0, c12, c0, 0 @Set VBAR |
This is auto-relocated! This is useful, cause the u-boot has been moved The reall assembly code is below: 由于u-boot经过了重定向,代码位置发生了改变,所以这里需要重新设置VBAR寄存器。 实际的代码如下: ldr r0, [pc, #736] 利用PC保证加载的是当前地址,而不是u-boot在ROM中的地址。 |
ldr r0, ldr r1, =__bss_end /* this is auto-relocated! */ mov r2, #0x00000000 /* prepare zero to clear BSS */ clbss_l:cmp r0, r1 /* while not at strlo r2, [r0] /* clear 32-bit BSS word */ addlo r0, r0, #4 /* move to next */ blo clbss_l |
把 .bss 段清零 |
/* call mov r0, r9 /* gd_t */ ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */ /* call ldr pc, =board_init_r /* this is auto-relocated! */ |
调用 board_init_r(gd_t *id, |
1.4 board_init_f
下面是board_init_f执行的操作。
function |
comments |
arch_cpu_init |
Do nothing on smdkc210 |
timer_init |
Do nothing on smdkc210 |
env_init |
初始化环境变量, 实际上是把default_environment设置到gd->env_addr. default_environment是一个字符串数组,每一个字符串用一个宏表示,我们通过在“include/configs/smdkc210.h”定义这些宏的方式设置环境变量。 |
init_baudrate |
设置波特率,其实它来自于 gd->baud. |
serial_init |
调用串口初始化函数 |
dram_init |
设置RAM位置与大小 |
Set gd. |
The most 设置gd表,用于保存配置 |
最新文章
- Linux命令全称
- Acadia Lab 203 + Lab 231
- Nginx负载均衡和LVS负载均衡的比较分析
- 【BZOJ】【3530】【SDOI2014】数数
- source导入错码解决办法
- Android 各版本信息 (维基百科)
- server的散热和Linux中温度的检測
- Android消息提示框Toast
- [转]Axis2创建WebService实例
- Hybrid容器设计之第三方网站
- http的CA证书安装(也就是https)
- 关于当前Web前端技术的一些感悟和笔记
- Linux-硬件
- 【读书笔记】iOS-应用内购买
- python-列表,元组,range
- Tag文件的创建与应用
- SpringMVC学习笔记:表单提交 参数的接收
- HTML上传文件支持大文件上传,下载
- python2 里边自定义线程池
- 内核早期内存分配器:memblock
热门文章
- linux内核中设备树的维护者仓库地址
- pytorch中的学习率调整函数
- 36 Flutter仿京东商城项目 用户登录 退出登录 事件广播更新状态
- flutter 引入第三方 Icon 图标(以阿里图标库为例)
- Springboot集成MapperFactory(ma.glasnost.orika.MapperFactory)类属性复制
- Treeview控件如何获得子节点的所有父节点的名称
- (六)Centos之目录作用介绍
- nginx利用fastcgi_cache模块缓存
- laravel5.2总结
- .Net Core 常用开发工具