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阶段)相关推荐

  1. [Spring Boot] 2. Spring Boot 启动过程定制化

    在上一篇文章中,从源码角度介绍了Spring Boot的启动过程.启动的代码虽然只有短短的一行,但是背后所做的工作还真不少,其中有一些可以定制化的部分,主要分为以下几个方面: 初始化器(Initial ...

  2. Android 面试必备 - 系统、App、Activity 启动过程

    前言 最近准备更新 Android 面试必备基础知识系列,有兴趣的可以关注我的微信公众号 stormjun94,有更新时,第一时间会在微信公众号上面发布,同时,也会同步在 GitHub 上面更新,如果 ...

  3. Spring Boot启动过程(七):Connector初始化

    Connector实例的创建已经在Spring Boot启动过程(四):Spring Boot内嵌Tomcat启动中提到了: Connector是LifecycleMBeanBase的子类,先是设置L ...

  4. Spring Boot启动过程(二)

    书接上篇 该说refreshContext(context)了,首先是判断context是否是AbstractApplicationContext派生类的实例,之后调用了强转为AbstractAppl ...

  5. Linux程序下载到板子上,uclinux系统移植到bf561板子上过程

    uclinux系统移植 主要工作包括: 1.选择处理器对应的交叉编译器(交叉编译器,运行于通用机上,目的为了编译出能够在特定平台上运行的软件) 2.选择并修改bootloader 3.修改链接文件,定 ...

  6. Linux内核移植之四:内核启动过程

    内容来自 韦东山<嵌入式Linux应用开发完全手册> 与移植U-Boot的过程相似,在移植Linux之前,先了解它的启动过程.Linux的启动过程可以分为两部分:架构/开发板相关的引导过程 ...

  7. Android系统(117)---Activity启动过程

    Activity启动过程 ###一些基本的概念 ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期 ActivityThread,App的 ...

  8. Android 系统(16)---应用启动过程

    在Android系统中,启动四大组件中的任何一个都可以启动应用程序.但绝大部分时候我们是通过点击Launcher图标来启动应用程序.本文依据Android7.0源码,从点击Launcher图标开始,分 ...

  9. Android 系统(15)---Launcher启动过程

    Launcher概述 SystemServer进程主要用于启动系统的各种服务,其中就包含了Launcher服务,LauncherAppService. Android系统默认第一个启动的应用程序是Ho ...

最新文章

  1. 【C】linux下切换工作目录至程序所在目录
  2. async/await工作机制探究--NodeJS
  3. Linux网络编程——浅谈 TCP 三次握手和四次挥手
  4. sigmoid函数解决溢出_梯度消失和梯度爆炸及解决方法
  5. .NET Core 项目指定SDK版本
  6. web开发软件,HTML如何添加锚点,成功入职阿里
  7. 【C++深度剖析教程6】C++之友元
  8. C++基础与深度解析第二章:对象与基本类型
  9. php imagefill,PHP图像处理技术实例总结【绘图、水印、验证码、图像压缩】
  10. 【渝粤教育】国家开放大学2018年春季 7385-21T公共关系学(本) 参考试题
  11. Python基础_文件操作
  12. Network in Network 算法解析
  13. 随机森林 ---sklearn
  14. 收集的一些discuz插件常用插件。
  15. ABB机器人GSD文件获取的几种方法
  16. Shell 教程 - 菜鸟教程
  17. topcoder java_Topcoder 练习小记,Java 与 Python 分别实现。
  18. 本周最新文献速递20220327
  19. win18系统如何打开c语言,控制面板在哪里打开(Windows打开控制面板的方法)
  20. 若x,y均定义为int型,z定义为double型,以下不合法的scanf函数调用语句是: A)scanf(“ %d%lx,%le“,x,y,z); B)scanf(“%2d * %d%lf“,

热门文章

  1. Android AsyncTask详解
  2. 电源原副边电气间隔和爬电距离
  3. Allegro使用总结-查看Layout基本操作:
  4. 小程序云开发db封装
  5. JDBC Statement RETURN_GENERATED_KEYS返回自动生成的ID
  6. PHP 十六大魔术方法学习
  7. stm32启用内部晶振(stm32设置外部晶振)
  8. Excel中如何快速地将成绩按比例来划分为等级?
  9. 2021年河南高考--各高校在河南录取分数线预测(本科二批——文科)
  10. MYSQL数据库更改目录及NAVACATamp;nbs…