系统移植-(二)u-boot:启动过程做的工作(汇编阶段、C阶段)
u-boot 启动过程
- (一)ctags 安装
- (二)uboot 启动过程
- (1)链接脚本u-boot.lds
- (2)start.S分析
- (3)Reset handler 分析
- (1)bl cpu_init_cp15
- (2)bl cpu_init_crit
- b lowlevel_init
- (3)board_init_f
- (4)board_init_r
- (三)u-boot 启动总结
(一)ctags 安装
ubuntu下的代码追踪工具:ctags
windows下的代码追踪工具:Source Insight
(1)安装ctags,在ubuntu中默认已经安装好ctags.
sudo apt-get install ctags
(2)进入到要追踪的源码的顶层目录下,
ctags -R:在源码的顶层目录下生成tags文件, -R:递归
执行以下命令:
vi -t 想追的内容
(3)只能在tags所在目录下,vim/vi + 绝对路径,打开u-boot下的源码文件。
vi 从源码顶层开始的路径/xxx.c vi arch/arm/cpu/slsiap/s5p6818/start.S
注意:只能一步到位使用:vim + 绝对路径,打开想要追踪的文件;
cd /ls /vim:一步一步打开错误。
eg错误方式:cd arch/arm/cpu/slsiap/s5p6818/ -> vi start.S
(4)代码追踪
- 将光标放到要追踪的函数处,按ctrl + ] 进入追踪的界面
- 选择位置序号,进入追踪的代码定义处
ctrl + t : 返回上一级
注意:
(1)如果函数的调用和定义都在当前文件,则直接命令行搜索:/要追踪的内容
(2)如果不在当前文件中定义,选中要追踪的内容,ctrl + ]使用ctags工具进行追踪
(二)uboot 启动过程
(1)链接脚本u-boot.lds
uboot启动过程中做的工作,可以通过追踪u-boot代码的执行过程。即找到ubootpak.bin文件执行的第一条指令。需要查看链接脚本文件,u-boot.lds。
u-boot.lds :指导编译器链接编译目标文件[.o]生成可执行文件[.elf]时,代码在内存空间中的排布。
u-boot.lds脚本源码(部分):
2 OUTPUT_ARCH(arm)3 ENTRY(_stext) //指定程序入口,在start.S中可看到地址符号_stext: 4 SECTIONS //整个链接脚本5 {6 . = 0x00000000;//当前地址7 . = ALIGN(4); //申请2^4 = 16字节的占位内存空间8 .text ://文本段9 {10 *(.__image_copy_start)//当前字段是一个变量:表示可以申请的占位内存空间11 arch/arm/cpu/slsiap/s5p6818/start.o (.text*)//程序入口执行的第一个文件:start.S12 arch/arm/cpu/slsiap/s5p6818/vectors.o (.text*)//第二个是中断异常向量表vectors.S13 *(.text*)//其他文件,根据编译器自动排布14 }
- __image_copy_start代码追踪查看:
char __image_copy_start[0] :占用0字节内存
在arch/arm/lib/sections.c中定义:22 char __bss_start[0] __attribute__((section(".__bss_start")));23 char __bss_end[0] __attribute__((section(".__bss_end")));24 char __image_copy_start[0] __attribute__((section(".__image_copy_start"))); 25 char __image_copy_end[0] __attribute__((section(".__image_copy_end")));26 char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));27 char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));28 char _end[0] __attribute__((section(".__end")));~
(2)start.S分析
打开 vi arch/arm/cpu/slsiap/s5p6818/start.S:
2 * armboot - Startup Code for NXPxxxx/ARM Cortex CPU-core//启动代码-ARM14 * Exception vectors as described in ARM reference manuals15 *16 * replace arm/lib/vectors.S20 .globl _stext 21 _stext: //程序入口,以下8个指令作用:构建异常向量表,各异常顺序不可改变22 b reset//执行的第一个指令:跳转到reset异常下 -》搜索/reset23 ldr pc, _undefined_instruction24 ldr pc, _software_interrupt25 ldr pc, _prefetch_abort26 ldr pc, _data_abort27 ldr pc, _not_used28 ldr pc, _irq29 ldr pc, _fiq30 31 _undefined_instruction: .word undefined_instruction32 _software_interrupt: .word software_interrupt33 _prefetch_abort: .word prefetch_abort34 _data_abort: .word data_abort35 _not_used: .word not_used36 _irq: .word irq37 _fiq: .word fiq38 39 .balignl 16,0xdeadbeef40 ~
(3)Reset handler 分析
76 .globl reset77 78 reset:79 bl save_boot_params 跳转到save_boot_params:保存启动参数80 /*81 * set the cpu to SVC32 mode82 */ 设置SVC工作模式83 mrs r0, cpsr 把cpsr中的值保存到r0中84 bic r0, r0, #0x1f 清除r0后5位并保存到r085 orr r0, r0, #0xd3 86 msr cpsr,r0 切换到SVC,确保进入SVC工作模式87 88 /* disable watchdog*/ 禁止看门狗:看门狗上电时默认状态是启动的,禁止WTD防止启动不起来 89 ldr r0, =0xC001900090 mov r1, #091 str r1, [r0]94 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 因为没有定义此变量,需执行下面两个指令95 bl cpu_init_cp15 完成:96 bl cpu_init_crit97 #endif100 relocate_to_text: u-boot代码自搬移到内存存放文本的位置
101 /*
102 * relocate(搬移) u-boot code on memory to text base
103 * for nexell arm core (add by jhkim)
104 */
105 adr r0, _stext /* r0 <- current position of code */
106 ldr r1, TEXT_BASE /* test if we run from flash or RAM */
107 cmp r0, r1 /* don't reloc during debug */
108 beq clear_bss
109
110 ldr r2, _bss_start_ofs
111 add r2, r0, r2 /* r2 <- source end address */
112
113 copy_loop_text:
114 ldmia r0!, {r3-r10} /* copy from source address [r0] */
115 stmia r1!, {r3-r10} /* copy to target address [r1] */
116 cmp r0, r2 /* until source end addreee [r2] */
117 ble copy_loop_text
118
119 ldr r1, TEXT_BASE /* restart at text base */
120 mov pc, r1122 clear_bss: //清除bss段
123 #ifdef CONFIG_MMU_ENABLE
124 bl mmu_turn_on
125 #endif
126 ldr r0, _bss_start_ofs
127 ldr r1, _bss_end_ofs
128 ldr r4, TEXT_BASE /* text addr */
129 add r0, r0, r4
130 add r1, r1, r4
131 mov r2, #0x00000000 /* clear */
...
144 bl board_init_f
...
160 ldr pc, =board_init_r 自搬移/* this is auto-relocated! */
...
162 #else /* CONFIG_RELOC_TO_TEXT_BASE */
163
164 bl _main 跳转到主函数
165 #endif
~
(1)bl cpu_init_cp15
禁止MMU和cache,设置协处理器
207 /* cpu_init_cp15
208 *
209 * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
211 *设置CP15寄存器(缓存,MMU, TLBs)。除非定义了CONFIG_SYS_ICACHE_OFF打开I-cache。
212 *************************************************************************/
213 ENTRY(cpu_init_cp15)
214 /*
215 * Invalidate L1 I/D
216 */
217 mov r0, #0 @ set up for MCR 设置协处理器:忽略TLBs、icache、BP组
218 mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
219 mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
220 mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
221 #ifndef CONFIG_MACH_S5P6818
222 mcr p15, 0, r0, c7, c10, 4 @ DSB
223 mcr p15, 0, r0, c7, c5, 4 @ ISB
224 #endif
225
226 /*
227 * disable MMU stuff and caches
228 */禁止MMU和cache:MMU内存管理单元,进行物理内存和虚拟内存映射;本阶段使用的都是物理内存,所以需要禁止mmu。
229 mrc p15, 0, r0, c1, c0, 0
230 bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
231 bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
232 orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
233 orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
234 #ifdef CONFIG_SYS_ICACHE_OFF
235 bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache
236 #else
237 orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
238 #endif
239 mcr p15, 0, r0, c1, c0, 0 返回到跳转前的位置处
240 mov pc, lr @ back to my caller
241 ENDPROC(cpu_init_cp15)
(2)bl cpu_init_crit
244 /*************************************************************************
245 *
246 * CPU_init_critical registers CPU临界资源初始化寄存器
247 *
248 * setup important registers
249 * setup memory timing
250 *
251 *************************************************************************/
252 ENTRY(cpu_init_crit)
253 /*
254 * Jump to board specific initialization...
255 * The Mask ROM will have already initialized
256 * basic memory. Go here to bump up clock rate and handle
257 * wake up conditions.
258 */
259 b lowlevel_init @ go setup pll,mux,memory
260 ENDPROC(cpu_init_crit)
261 #endif
b lowlevel_init
11 lowlevel_init: 低电平初始化 12 13 /* get cpu id */ 获取cpu的id14 mrc p15, 0, r0, c0, c0, 5 @ Read CPU ID register15 ands r0, r0, #0x03 @ Mask off, leaving the CPU ID field16 mov r1, #0xF @ Move 0xF (represents all four ways) into r117 18 /* join SMP */19 mrc p15, 0, r0, c1, c0, 1 @ Read ACTLR20 mov r1, r021 orr r0, r0, #0x040 @ Set bit 622 cmp r0, r123 mcrne p15, 0, r0, c1, c0, 1 @ Write ACTLR24 25 /* enable maintenance broadcast */使能保持广播设置26 mrc p15, 0, r0, c1, c0, 1 @ Read Aux Ctrl register27 mov r1, r028 orr r0, r0, #0x01 @ Set the FW bit (bit 0)29 cmp r0, r130 mcrne p15, 0, r0, c1, c0, 1 @ Write Aux Ctrl register31 32 mov pc, lr @ back to caller 返回调用处
(3)board_init_f
追踪代码:对bd_t/gd_t等底板信息的结构体变量,进行初始化赋值操作。
263 void board_init_f(ulong bootflag)
264 {
265 bd_t *bd;
266 init_fnc_t **init_fnc_ptr;
267 gd_t *id;
268 ulong addr, addr_sp;... }
(4)board_init_r
board_init_r函数:完成了大部分串口,内存,flash,cache等硬件的初始化
509 void board_init_r(gd_t *id, ulong dest_addr)
510 {
511 ulong malloc_start;
512 #if !defined(CONFIG_SYS_NO_FLASH)
513 ulong flash_size;
514 #endif
521 /* Enable caches */使能cache
522 enable_caches();
524 debug("monitor flash len: %08lX\n", monitor_flash_len);
525 board_init(); /* Setup chipselects */ 底板初始化
533 set_cpu_clk_info(); /* Setup clock information */ 615 /* initialize environment */初始化环境变量
616 if (should_load_env())
617 env_relocate();
618 else
619 set_default_env(NULL);
625 stdio_init(); /* get the devices list going. */ 设备启动列表
626
627 jumptable_init();
628
629 #if defined(CONFIG_API)
630 /* Initialize API */ 初始化API接口
631 api_init();
632 #endif
633
634 console_init_r(); /* fully init console as a device */ 控制台初始化
635
636 #ifdef CONFIG_PMIC_REG_DUMP
637 power_init_board(); 底板上电初始化
638 #endif
...
708
709 /* main_loop() can return to retry autoboot, if so just run it again. */main_loop()可以返回重复自动引导u-boot启动,如果是这样的话,只需再次运行它710 for (;;) {711 main_loop();
712 }713 除了引导之外,没有方法跳出命令循环
714 /* NOTREACHED - no way out of command loop except booting */
715 }
(三)u-boot 启动总结
uboot启动阶段,主要干了哪些事?
阶段1:汇编阶段
1》构建异常向量表
2》ARM切换到SVC工作模式,关闭看门狗WTD,禁止中断
3》关闭MMU和cache
4》一些串口、定时器、环境变量、I2C/SPI总线等的初始化
5》完成u-boot代码的自搬移,清除bss段阶段2:c语言阶段
1》完成对bd和gd结构体的初始化
2》完成大部分硬件的初始化:串口,网卡,flash,使能中断等等
3》根据bootdelay倒计时是否为0,切换uboot进入自启动模式还是交互模式
4》执行u-boot环境变量bootcmd中的命令,并将bootargs参数传递给内核
系统移植-(二)u-boot:启动过程做的工作(汇编阶段、C阶段)相关推荐
- [Spring Boot] 2. Spring Boot 启动过程定制化
在上一篇文章中,从源码角度介绍了Spring Boot的启动过程.启动的代码虽然只有短短的一行,但是背后所做的工作还真不少,其中有一些可以定制化的部分,主要分为以下几个方面: 初始化器(Initial ...
- Android 面试必备 - 系统、App、Activity 启动过程
前言 最近准备更新 Android 面试必备基础知识系列,有兴趣的可以关注我的微信公众号 stormjun94,有更新时,第一时间会在微信公众号上面发布,同时,也会同步在 GitHub 上面更新,如果 ...
- Spring Boot启动过程(七):Connector初始化
Connector实例的创建已经在Spring Boot启动过程(四):Spring Boot内嵌Tomcat启动中提到了: Connector是LifecycleMBeanBase的子类,先是设置L ...
- Spring Boot启动过程(二)
书接上篇 该说refreshContext(context)了,首先是判断context是否是AbstractApplicationContext派生类的实例,之后调用了强转为AbstractAppl ...
- Linux程序下载到板子上,uclinux系统移植到bf561板子上过程
uclinux系统移植 主要工作包括: 1.选择处理器对应的交叉编译器(交叉编译器,运行于通用机上,目的为了编译出能够在特定平台上运行的软件) 2.选择并修改bootloader 3.修改链接文件,定 ...
- Linux内核移植之四:内核启动过程
内容来自 韦东山<嵌入式Linux应用开发完全手册> 与移植U-Boot的过程相似,在移植Linux之前,先了解它的启动过程.Linux的启动过程可以分为两部分:架构/开发板相关的引导过程 ...
- Android系统(117)---Activity启动过程
Activity启动过程 ###一些基本的概念 ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期 ActivityThread,App的 ...
- Android 系统(16)---应用启动过程
在Android系统中,启动四大组件中的任何一个都可以启动应用程序.但绝大部分时候我们是通过点击Launcher图标来启动应用程序.本文依据Android7.0源码,从点击Launcher图标开始,分 ...
- Android 系统(15)---Launcher启动过程
Launcher概述 SystemServer进程主要用于启动系统的各种服务,其中就包含了Launcher服务,LauncherAppService. Android系统默认第一个启动的应用程序是Ho ...
最新文章
- 【C】linux下切换工作目录至程序所在目录
- async/await工作机制探究--NodeJS
- Linux网络编程——浅谈 TCP 三次握手和四次挥手
- sigmoid函数解决溢出_梯度消失和梯度爆炸及解决方法
- .NET Core 项目指定SDK版本
- web开发软件,HTML如何添加锚点,成功入职阿里
- 【C++深度剖析教程6】C++之友元
- C++基础与深度解析第二章:对象与基本类型
- php imagefill,PHP图像处理技术实例总结【绘图、水印、验证码、图像压缩】
- 【渝粤教育】国家开放大学2018年春季 7385-21T公共关系学(本) 参考试题
- Python基础_文件操作
- Network in Network 算法解析
- 随机森林 ---sklearn
- 收集的一些discuz插件常用插件。
- ABB机器人GSD文件获取的几种方法
- Shell 教程 - 菜鸟教程
- topcoder java_Topcoder 练习小记,Java 与 Python 分别实现。
- 本周最新文献速递20220327
- win18系统如何打开c语言,控制面板在哪里打开(Windows打开控制面板的方法)
- 若x,y均定义为int型,z定义为double型,以下不合法的scanf函数调用语句是: A)scanf(“ %d%lx,%le“,x,y,z); B)scanf(“%2d * %d%lf“,