• 系统篇: uboot 启动流程


    bootloader是系统上电后最初加载运行的代码。它提供了处理器上电复位后最开始需要执行的初始化代码。在PC机上引导程序一般由BIOS开始执行,然后读取硬盘中位于MBR(Main Boot Record,主引导记录)中的Bootloader(例如LILO或GRUB),并进一步引导操作系统的启动。然而在嵌入式系统中通常没有像BIOS那样的固件程序,因此整个系统的加载启动就完全由bootloader来完成。它主要的功能是加载与引导内核映像 。

    一、u-boot的作用

    初始化CPU,初始化内存、串口、时钟等硬件资源,加载内核、引导内核,为操作系统的运行提供环境准备

    在这里插入图片描述

    二、u-boot的启动流程

    1、第一阶段依赖于cpu体系结构的代码,从存储介质中读取小部分程序到cpu中,这部分程序要完成引导linux所用的硬件的初始化以及加载uboot其余程序到RAM中

    • 初始化CPU(中断向量表、时钟、内存等资源)
    • 禁止IRQ和FIQ
    • 拷贝u-boot第二阶段的代码到内存
    • 为第二阶段C程序的运行建立堆栈空间
    • 跳转到第二阶段的入口处执行

    2、继续初始化必备硬件,加载linux镜像到RAM中,把执行权限交给linux

    • 本阶段所需的硬件资源的初始化,为引导linux kernel做准备
    • 将内核镜像从flash读取到内存中
    • 微内核设置启动参数
    • 引导内核
    三、源码分析

    目录结构:

    • board中存放于开发板相关的配置文件,每一个开发板都以子文件夹的形式出现。
    • commom文件夹实现u-boot行下支持的命令,每一个命令对应一个文件。
    • cpu中存放特定cpu架构相关的目录,每一款cpu架构都对应了一个子目录。
    • Drivers中是u-boot支持的各种设备的驱动程序。
    • Include文件夹是u-boot使用的头文件,还有各种硬件平台支持的汇编文件,系统配置文件和文件系统支持的文件。

    启动流程代码分析:

    .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
    
    reset:
    	/*
    	 * set the cpu to SVC32 mode		//切换CPU模式为SVC模式,关闭中断,以便访问更多硬件资源
    	 */
    	mrs	r0, cpsr
    	bic	r0, r0, #0x1f
    	orr	r0, r0, #0xd3
    	msr	cpsr,r0
    
    	/*
    	 * disable MMU stuff and caches		//关闭MMU与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
    	mcr	p15, 0, r0, c1, c0, 0
    
    
    after_ziju:
    	/* init PLL/DDRC/pin mux/... */			//初始化时钟、内存、IO
    	ldr	r0, _blank_zone_start
    	ldr	r1, _TEXT_BASE
    	sub	r0, r0, r1
    	cmp 	r3, r2
    	beq	pcie_slave_addr
    	ldr	r1, =RAM_START_ADRS
    	ldr	sp, =STACK_TRAINING
    	b	ziju_ddr_init
    pcie_slave_addr:
    	ldr	r1, =0x0
    	ldr	sp, =PCIE_SLV_STACK
    	ldr	r4, =SYS_CTRL_REG_BASE
    	str	r2, [r4, #HI3531D_SYSBOOT10]
    ziju_ddr_init:
    	add	r0, r0, r1
    	mov	r1, #0x0		/* flags: 0->normal 1->pm */
    	bl	init_registers		/* init PLL/DDRC/... */
    
    
    copy_loop:				@ copy 32 bytes at a time					//循环拷贝u-boot到内存
    	ldmia	r0!, {
       r3 - r10}		@ copy from source address [r0]
    	stmia	r1!, {
       r3 - r10}		@ copy to target address [r1]
    	cmp	r0, r2			@ until source end addreee [r2]
    	ble	copy_loop
    
    /* Set up the stack */		//设置堆栈
    stack_setup:
    	ldr	r0, _TEXT_BASE		@ upper 128 KiB: relocated uboot
    	sub	r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area
    	sub	r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo
    #ifdef CONFIG_USE_IRQ
    	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)
    #endif
    	sub	sp, r0, #12		@ leave 3 words for abort-stack
    	and	sp, sp, #~7		@ 8 byte alinged for (ldr/str)d
    
    	ldr	pc, _start_armboot	@ jump to C code		//跳转到start_armboot函数执行
    _start_armboot: .word start_armboot
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    void start_armboot (void)
    /* Pointer is writable since we allocated a register for it */
    	gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t))
    • 1
    • 2
  • 相关阅读:
    MATLAB命令
    Python 编写确定个位、十位以上方法及各数位的和程序
    java计算机毕业设计航帆学院网站MyBatis+系统+LW文档+源码+调试部署
    【服务器数据恢复】infortrend存储RAID6数据恢复案例
    android代码中打开系统设置界面(无线和网络设置,日期和时间设置, 辅助功能设置,电池信息)
    lambda表达式
    【cartographer_ros】七: 主要配置参数说明
    Nginx源码分析 --时间 日期 日志
    旅游网页设计 web前端大作业 全球旅游私人订制 旅游公司网站模板(HTML+CSS+JavaScript)
    器学习算法(六)基于天气数据集的XGBoost分类预测
  • 原文地址:https://blog.csdn.net/GCQ19961204/article/details/126679837