uboot启动流程概述_Uboot启动流程分析(一)

阅读: 评论:0

uboot启动流程概述_Uboot启动流程分析(⼀)
1、前⾔
Linux系统的启动需要⼀个bootloader程序,该bootloader程序会先初始化DDR等外设,然后将Linux内核从Flash中拷贝到DDR中,最后启动Linux内核,uboot的全称为Universal Boot Loader,Linux系统中常⽤的bootloader就是uboot,接下来,将会进⾏简单的uboot启动流程分析,uboot的源码为uboot-imx-rel_imx_4.15_2.1.0。
2、uboot⼊⼝
转向轴在分析之前,需要对整个uboot⼯程进⾏编译,⽣成⼀些分析时需要⽤到的⽂件,例如链接⽂件uboot.lds和uboot映射⽂件uboot.map,通过链接⽂件,可以到uboot的⼊⼝,到uboot启动后运⾏的第⼀⾏代码。
在uboot源码根⽬录下到链接⽂件uboot.lds,如下:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)//当前⼊⼝_start
SECTIONS
{
.= 0x00000000;
.= ALIGN(4);
.text :
{*(.__image_copy_start) //⼊⼝
*(.vectors) //中断向量表
液压卸车翻板arch/arm/cpu/armv7/start.o (.text*) //arch/arm/cpu/armv7/start.S代码段
*(.text*)
}
.
= ALIGN(4);
.rodata : {*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
.= ALIGN(4);
.data : {*(.data*)
}
.= ALIGN(4);
.=.;
.= ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
.
= ALIGN(4);
.image_copy_end :
{*(.__image_copy_end)
}
.rel_dyn_start :
{*(.__rel_dyn_start)
}
.rel.dyn : {*(.rel*)
}
.rel_dyn_end :
{*(.__rel_dyn_end)
}
.end :
{*(.__end)
}
_image_binary_end=.;
.= ALIGN(4096);
.mmutable : {*(.mmutable)
}
.bss_start __rel_dyn_start (OVERLAY) : { KEEP(*(.__bss_start));
__bss_base=.;
}
.
bss __bss_base (OVERLAY) : {*(.bss*)
.= ALIGN(4);
__bss_limit=.;
互联互通软件}
.bss_end __bss_limit (OVERLAY) : {
KEEP(*(.__bss_end));
}
.dynsym _image_binary_end : {*(.dynsym) } .dynbss : {*(.dynbss) }
.dynstr : {*(.dynstr*) }
.dynamic : {*(.dynamic*) }
.plt : {*(.plt*) }
.
interp : {*(.interp*) }
.gnu.hash : {*(.gnu.hash) }
.gnu : {*(.gnu*) }
.idx : {*(.idx*) }
.gnu.linkonce.armexidx : {*(.gnu.linkonce.armexidx.*) }
}
在上⾯的链接⽂件中,可以确定uboot的⼊⼝为_start,该定义在arch/arm/lib/vectors.S⽂件中:
_start:
#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
.word CONFIG_SYS_DV_NOR_BOOT_CFG#endifb reset//中断向量表,跳转到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
进⼊到_start后,运⾏b reset语句,跳转到reset中运⾏,b reset后⾯跟着中断向量表,reset的定义,对于不同的CPU架构不⼀样,对于NXP的i.mx6ul芯⽚,该定义在arch/arm/cpu/armv7/start.S⽂件中:
.globl reset
.globl save_boot_params_ret
reset:/*Allow the board to save important registers*/b save_boot_params//跳到save_boot_params
save_boot_params_ret:/** disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,实心锥形喷嘴
* except if in HYP mode already*/mrs r0, cpsr//读取cpsr寄存器的值到r0寄存器中(cpsr:bit0~bit4保存处理器⼯作模式)
and r1, r0, #0x1f @ mask mode bits //r0的值与0x1f相与,结果保存到r1寄存器
teq r1, #0x1a @ test for HYP mode //判断当前处理器模式是否是HYP模式
bicne r0, r0, #0x1f @ clear all mode bits //如果CPU不处于HYP模式,则清除bit0~bit4
orrne r0, r0, #0x13 @ set SVC mode //设置为SVC模式
orr r0, r0, #0xc0 @ disable FIQ and IRQ //禁⽌FIQ和IRQ
msr cpsr,r0 //将当前r0寄存器的值回写到cpsr寄存器
/** Setup vector:
* (OMAP4 spl TEXT_BASE is not 32 byte aligned.
* Continue to use ROM code vector only in OMAP4 spl)*/
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
/*Set V=0 in CP15 SCTLR register - for VBAR to point to vector*/mrc p15,0, r0, c1, c0, 0 @ Read CP15 SCTLR Register //读取SCTLR寄存器
bic r0, #CR_V @ V = 0 //设置V = 0
mcr p15, 0, r0, c1, c0, 0@ Write CP15 SCTLR Register/*Set vector address in CP15 VBAR register*/ldr r0,=_start //设置vector地址到CP15 VBAR寄存器
mcr p15, 0, r0, c12, c0, 0@Set VBAR#endif
/*the mask ROM code should have PLL and others stable*/#ifndef CONFIG_SKIP_LOWLEVEL_INITHDPE多孔加筋缠绕波纹管
bl cpu_init_cp15//跳转到cpu_init_cp15
单点系泊系统
bl cpu_init_crit //跳转到cpu_init_crit
#endifbl _main//跳转到_main
在上⾯的代码中主要是对arm架构处理器的运⾏模式进⾏设置,对⼀些寄存器进⾏赋值操作,对于cpu_init_crit函数的实现如下:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT/*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************/ENTRY(cpu_init_crit)/** Jump to board
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.*/b lowlevel_init @ go setup pll,mux,memory//跳到lowlevel_init,设置pll、mux和memory
ENDPROC(cpu_init_crit)#endif
在cpu_init_crit函数中,跳到了lowlevel_init函数中运⾏,接下来,将详细分析⼀下lowlevel_init和_main函数。
3、lowlevel_init函数
在uboot源码中lowlevel_init的定义在arch/arm/cpu/armv7/lowlevel_init.S⽂件中,该定义如下所⽰:
ENTRY(lowlevel_init)/** Setup a temporary stack. Global data is not available yet.*/ldr sp,=CONFIG_SYS_INIT_SP_ADDR //设置sp指针指向CONFIG_SYS_INIT_SP_6ul内部RAM)
bic sp, sp, #7 /*8-byte alignment for ABI compliance*/ //sp指针8字节对齐处理
#ifdef CONFIG_SPL_DM
mov r9, #0
#else
/** Set up global data for boards that still need it. This will be
* removed soon.*/#ifdef CONFIG_SPL_BUILD
ldr r9,=gdata#elsesub sp, sp, #GD_SIZE//sp = sp - 248
bic sp, sp, #7mov r9, sp//将sp指针保存到r9寄存器
#endif
#endif
/** Save the old lr(passed in ip) and the current lr to stack*/push {ip, lr}//将ip和lr进⾏压栈
/** Call the very early init function. This should do only the
* absolute bare minimum to get started. It should not:
*
* - set up DRAM
* - use global_data
* - clear BSS
* - try to start a console
*
* For boards with SPL this should be empty since SPL can do all of
* this init in the SPL board_init_f() function which is called
* immediately after this.*/bl s_init//跳转到s_init(对与im6ul啥也没⼲,直接返回)
pop {ip, pc} //将ip和pc指针出栈
ENDPROC(lowlevel_init)
函数进来后,⾸先设置了sp指针的值为CONFIG_SYS_INIT_SP_ADDR,该值为⼀个宏定义,对于i.mx6ul芯⽚定义在⽂件
include/configs/mx6ul_14x14_evk.h,如下:
#define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR //0x00900000(OCRAM的基地址)
#define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE //0x00020000(OCRAM的⼤⼩,容量为128KB)
#define CONFIG_SYS_INIT_SP_OFFSET (CONFIG_SYS_INIT_RAM_SIZE- GENERATED_GBL_DATA_SIZE) //0x00020000 -256 = 0x1FF00
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_INIT_RAM_ADDR+ CONFIG_SYS_INIT_SP_OFFSET) //0x00900000 + 0x1FF00 = 0x0091FF00
OCRAM的基地址和⼤⼩可以在imx6ul的数据⼿册中的系统内存映射表中查到:
对于GENERATED_GBL_DATA_SIZE宏的定义在include/generated/generic-asm-offsets.h⽂件中:
#define GENERATED_GBL_DATA_SIZE 256 /* (sizeof(struct global_data) + 15) & ~15 @ */
#define GENERATED_BD_INFO_SIZE 80 /* (sizeof(struct bd_info) + 15) & ~15 @ */
#define GD_SIZE 248 /* sizeof(struct global_data) @ */
#define GD_BD 0 /* offsetof(struct global_data, bd) @ */
#define GD_MALLOC_BASE 192 /* offsetof(struct global_data, malloc_base) @ */

本文发布于:2023-05-18 14:59:36,感谢您对本站的认可!

本文链接:https://patent.en369.cn/patent/4/104559.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:寄存器   模式   启动   指针   函数
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 369专利查询检索平台 豫ICP备2021025688号-20 网站地图