uboot2015.04代码执行流程
记录uboot源码的下载地址。http://ftp.denx.de/pub/u-boot/
其实记录这些东西,我当时的处境是那么多相同名字的文件,相同名字的函数,自己不知道对于i.MX6dl来说,到底执行的是哪个文件里的哪个函数。
所以这里涉及到特定文件、函数的时候,会标红。
说到当初分析代码执行流程,找了N久,找到了链接文件。当初又是打算分析Makefile,又是看编译的最后一步打印日志,闹的头都大了。找这些东西真的坑爹。
我就不知道到底有没有文档来明明白白的把这些问题说清楚。倒是带了很多的ReadMe文件,但是打开一看,你妹的看完这个文件我tm修仙成功了都。。。
/arch/arm/cpu/u-boot.lds还有一个是u-boot-spl.lds,我们没用SPL机制,所以不提他了
文件内容如下:
1 ENTRY(_start) 最开始的入口2 SECTIONS3 {4 . = 0x00000000;5 6 . = ALIGN(4);7 .text :8 {9 *(.__image_copy_start) 需要拷贝的image文件,开始位置标志
10 *(.vectors) 中断向量表
11 CPUDIR/start.o (.text*) start.S函数的代码段,不含数据段
12 *(.text*)
13 }
14
15
16 CONFIG_ARMV7_SECURE_BASE相关的,略
17
18 . = ALIGN(4);
19 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
20
21 . = ALIGN(4);
22 .data : {
23 *(.data*)
24 }
25
26 . = ALIGN(4);
27
28 . = .;
29
30 . = ALIGN(4);
31 .u_boot_list : {
32 KEEP(*(SORT(.u_boot_list*)));
33 }
34
35 . = ALIGN(4);
36
37 .image_copy_end :
38 {
39 *(.__image_copy_end) 需要拷贝的image文件,开始位置标志
40 不包括rel_dyn数据,和bss段的数据
41 }
42
43 .rel_dyn_start :
44 {
45 *(.__rel_dyn_start)
46 }
47
48 .rel.dyn : {
49 *(.rel*)
50 }
51
52 .rel_dyn_end :
53 {
54 *(.__rel_dyn_end)
55 }
56
57 .end :
58 {
59 *(.__end)
60 }
61
62 _image_binary_end = .;
63
64
65 /* bss段
66 * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
67 * __bss_base and __bss_limit are for linker only (overlay ordering)
68 */
69
70 .bss_start __rel_dyn_start (OVERLAY) : {
71 KEEP(*(.__bss_start));
72 __bss_base = .;
73 }
74
75 .bss __bss_base (OVERLAY) : {
76 *(.bss*)
77 . = ALIGN(4);
78 __bss_limit = .;
79 }
80
81 .bss_end __bss_limit (OVERLAY) : {
82 KEEP(*(.__bss_end));
83 }
84
85 //其他数据
86 .dynsym _image_binary_end : { *(.dynsym) }
87 .dynbss : { *(.dynbss) }
88 .dynstr : { *(.dynstr*) }
89 .dynamic : { *(.dynamic*) }
90 .plt : { *(.plt*) }
91 .interp : { *(.interp*) }
92 .gnu.hash : { *(.gnu.hash) }
93 .gnu : { *(.gnu*) }
94 .ARM.exidx : { *(.ARM.exidx*) }
95 .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
96 }
97
最开始的入口是_start,他在vectors.S arch\arm\lib\vector.S中
他的作用就是中断向量表,第一个跳转位置为reset函数,其后的各个函数,是中断入口地址,不过uboot的初始化过程是不涉及中断的,这里先忽略他们。
__image_copy_start这个玩意儿就是个标号,表示需要拷贝的image文件的开始位置。
在SourceInsight里面搜索这个标号,发现定义在 arch\arm\lib\sections.c中。略
于是找到了入口点,i.mx6dl是armv7架构的,所以是arch\arm\cpu\armv7\start.S文件。
首先执行reset标号处的内容,代码的注释很详细:disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode
#ifndef CONFIG_SKIP_LOWLEVEL_INITbl cpu_init_cp15 @[this two func] ALL in this filebl cpu_init_crit @here is lowlevel_init
#endifbl _main @ arch\arm\lib\crt0.S
两个cpu_init都在当前文件中。不管他俩,直接看跳到_main里面做了什么。
另外这个
CONFIG_SKIP_LOWLEVEL_INIT
有没有定义呢,抡起Linux下的板斧,因为别的命令不会,只会grep * -nR -nwR和find -name哈哈哈
搜索【此前已经问飞凌开发板的客服知道了配置文件是include/configs/mx6sabre_common.h】
grep '#define CONFIG_SKIP_LOWLEVEL_INIT' include/configs/mx* -nR
单引号表示搜索的东东是一个整体。
发现没有在include/configs/mx6sabre_common.h当中定义。
下面到_main里面看看,目录在 arch\arm\lib\crt0.S
详细的内存分布,在这个函数里面开始形成,但这不是我的重点,我的重点就是管你怎么分布的呢,我又不写你源代码,我就想看看你代码是怎么个执行过程!
之后就跳转到board_init_f函数了
/*u-boot的基本策略,就是声明一系列的API(如low_level_init、board_init_f、board_init_r等等),并在u-boot的核心逻辑中调用它们。平台的移植和开发者,所需要做的,就是根据实际情况,实现它们。与此同时,为了减少开发的工作量,u-boot为大部分API提供了通用实现(一般通过CONFIG配置项或者若定义去控制是否编译)。以board_init_f和board_init_r两个板级的初始化接口为例,u-boot分别在common/board_f.c和common/board_r.c两个文件中提供了通用实现。查看common/Makefile可知:obj-$(CONFIG_SYS_GENERIC_BOARD) += board_f.o obj-$(CONFIG_SYS_GENERIC_BOARD) += board_r.o ./include/configs/mx6sabre_common.h 里定义了 CONFIG_SYS_GENERIC_BOARD
*/
这句话引自窝窝科技:uboot章节:http://www.wowotech.net/sort/u-boot
/*别的不管,这里是一个初始化函数的数组,会一一调用他们来初始化开发板。
*/
if (initcall_run_list(init_sequence_f))hang();
这里的函数有没有执行,我都是一个个添加打印进去看他的输出日志有没有那句话来判断的,一个个的加,想想就感觉蛋碎!
( 打开debug输出日志的方法是,在 include/common.h 当中 加入 #define DEBUG )
//#define DEBUG#ifdef DEBUG
#define _DEBUG 1
#else
#define _DEBUG 0
#endif#define debug_cond(cond, fmt, args...) \do { \if (cond) \printf(pr_fmt(fmt), ##args); \} while (0)#define debug(fmt, args...) \debug_cond(_DEBUG, fmt, ##args)/* 要想打印输出成功,只能定义DEBUG */
看一下这个数组里的东东:
static init_fnc_t init_sequence_f[] = {前略...env_init, /* initialize environment 环境变量初始化开始 env_mmc.c*/init_baud_rate, /* initialze baudrate settings */serial_init, /* serial communications setup */console_init_f, /* stage 1 init of console */// 如果你想裁剪uboot的启动时间,这里的函数有一部分是可以去掉的。// 初始化DDRdram_init, /* configure available RAM banks */// 为代码重定位所做的工作,主要是操作内存的空间}
之后跳转到代码重定位:
adr lr, hereldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off 新旧地址的偏移长度*/add lr, lr, r0 /* lr = relocate后,新的here地址 */ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */b relocate_code 代码重定位的函数所在文件: /* relocate.S (arch\arm\lib) */
here:
/** now relocate vectors*/bl relocate_vectors
这里对比说为什么新版的uboot代码的重定位搞的这么复杂,又是代码段、又是rel_dyn数据段的,为什么不像以前一样直接打包成一个文件,全部从flash拷贝的内存里去。
看了一篇文章里说,是为了把uboot定位到内存比较高的地址,因为将来内核是加载到内存低地址的。
二一个是,反正都要重定位,你管我怎么做呢?我Fxck,你厉害
代码重定位具体的实现就不说了,韦东山也讲过,很多其他博客也都有讲解。
之后就到了重定位之后的半段:
board_init_r函数,在common\board_r.c,他里面同样有一个初始化函数数组,init_sequence_r
同样,我不能确定这里的宏,哪个定义了与否,便不能确定这个数组里的函数被初始化调用了与否。
所以只能是一个个函数加上打印语句。这样也能根据函数执行的情况,知道当下的这个宏有没有被定义。
#ifdef CONFIG_GENERIC_MMCinitr_mmc, //mmc preinit?
#endif//undef CONFIG_HAS_DATAFLASHinitr_env, /*环境变量重定位,初始化结束,第一次mmc_init*/#ifdef CONFIG_BOARD_LATE_INITboard_late_init, //mmc_init 1次//board_late_mmc_env_init => setenv_ulong => setenv => _do_env_set//board_late_mmc_env_init => run_command[mmc dev N] => do_mmc_dev(cmd_mmc.c)//=> init_mmc_device => mmc_init
#endifrun_main_loop, // 最终大BOSS!!!
};
到这里,板子的MMC也初始化成功了,最后执行到run_main_loop不再返回。
uboot2015.04代码执行流程相关推荐
- 「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析
「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析 前言 一.我的开发环境 二.使用 Vue CLI (Vue 脚手架)快速搭建项目 三.初始项目的目录结构 ...
- JVM03Java代码执行流程
一.Java的跨平台性 Java代码的执行流程 jvm运行原理: 运行一个HelloWorld的类,运行完毕之后,文件夹里出现HelloWorld.class的文件 javac程序是一个Java编译器 ...
- 2021-02-26js学习-arguement,函数,作用域链,js代码执行流程,对象创建,new执过程.
问题: Agurement概念认识? 伪数组概念认识? 函数的两种声明方式? 函数中没有声明而直接使用的变量是全局变量吗? Js块级作用域认识? 作用域链 概念认识? Js引擎执行代码的两步是什么? ...
- Android系统手机开机画面各个阶段代码执行流程分析(Part1)
提到Android系统的UI,我们最先接触到的便是系统在启动过程中所出现的画面了.Android系统在启动的过程中,最多可以出现三个画面,每一个画面都用来描述一个不同的启动阶段.本文将详细分析这三个开 ...
- Scala入门示例反编译分析代码执行流程
javap一下,看反编译结果: package com.zxl.java.chapter01;//分析 // 1. object在底层会生成两个类Hello , Hello$ // 2. Hello中 ...
- java代码执行流程
JIT编译器将热点代码编译成机器指令给缓存起来,主要是解决性能和响应时间的问题.
- Android系统手机开机画面各个阶段代码执行流程分析(Part2)
3. 第三个开机画面的显示过程 第三个开机画面是由应用程序bootanimation来负责显示的.应用程序bootanimation在启动脚本init.rc中被配置成了一个服务,如下所示: servi ...
- Vue项目启动代码执行流程分析
相信来看看这篇文章的童鞋,都对Vue已经有了大致的了解.所以,话不多说,直接进入正题. 首先看下图: 一般一个初步的Vue项目创建好之后都会有这三个文件:index.html .main.js .Ap ...
- 浅谈PHP代码执行的大致流程(opcode)
说到这个代码执行流程啊,咱也不说太多,先给大家分享一张图片: 怎么样?有点了解了么.说实话,单看这个,我本人是有点懵的,不过,不要怕.咱们来慢慢地看下. 首先,在网上找的信息说 ...
- python代码执行过程记录_[原创]IDAPython+OdbgScript动态获取程序执行流程
题记: 最近知道了有一种方法,可以获取到程序的执行流程,具体做法是先获取程序中每一个函数的地址,在这些地址上设置断点,然后让程序运行起来,hook调试器,断点中断时,不要停下来继续执行,并记录命中的断 ...
最新文章
- mybatis批量更新
- 在后台查看product的change history
- 京东笔试4.2-19:00随笔
- Ubuntu 8.04 Linux系统下面编译更新内核版本
- 随便选一张扑克牌_扑克牌魔术手法教学,简单易学的纸牌魔术,三分钟让你成为大师...
- 模拟网页行为之工具篇
- 记录第二次遇到ERROR! MySQL server PID file could not be found!
- (转)Spring+JDBC组合开发
- Allied Vision相机
- vnc远程,在windows下如何实现vnc远程
- 用python爬取网易云评论最多的歌_巧用Python爬取网易云音乐歌曲全部评论
- 软件系统三员管理_3个可怕的系统管理员故事
- 03 Transformation 变换
- 功能安全-26262-理论到实践-基础知识-标准机构与认可、认证
- 如果一笔生意听起来好得让人难以置信
- 设置openwrt,使wifi路由器既可以连接到外网wifi路由器,并且还能够让无线设备来连接。
- TWaver最强大的ShapeNode功能
- v兔无痕补单是什么,无痕补单搭配运营知识怎样玩,无痕补单的意义,哪里可以找到无痕补单
- redis五种数据类型及使用场景
- pdf骑缝章_骑缝章的盖章方法(详细图文教程)
热门文章
- 自己买双色球杀号选号花费中奖记录地址
- 做好芯片设计,这三种能力不可或缺
- 22款奔驰GLE350升级小柏林音响,感受无损动人的音质
- TIOBE 5 月排行榜出炉:C 语言时隔 5 年重回巅峰!
- 电力“十三五” 光伏分布式6000万千瓦迎来机遇
- 初学者指南:GRUB-系统引导管理器
- java:不兼容的类型:推论变量 T具有不兼容的限制范围
- 【分享NVIDIA GTC 23大会干货】从乌龟到兔子转变:人工智能如何将任何车手变成赛车手 [S51328]
- 舞蹈健身房私人教练响应式网站模板
- 牛逼的java程序员写给老婆的情书(转载的)