U-boot 启动流程分析 2

Uboot重定位 rel.dyn 包含了需要重定位的变量的信息, 叫做变量重定位表(包含全局变量和静态函数的符号).rel.plt 包含了需要重定位的函数的信息, 叫做函数重定位表/*Address *//*/*Addend */Elf64_Rela;//.rela.dyn重定位表的表项entry结构 ,可以用readelf -r test来查看该段tbl index) *///符号的名字,其实际值为字符串表.strtab的索引,真正的字符串放在.strtab中。 阅读详情

下面根据具体的代码分析start.S

start.S位于arch/riscv/cpu下面,每一种框架都有自己的目录,本文用risc-v作为参考。
根据链接脚本发现start.S里面的_start将是uboot的执行入口,我们从这里开始分析。

1. 在代码的最开始,根据cpu的bit定义了一套后续使用的宏定义。

#ifdef CONFIG_32BIT
#define LREG lw
#define SREG sw
#define REGBYTES 4
#define RELOC_TYPE R_RISCV_32
#define SYM_INDEX 0x8
#define SYM_SIZE 0x10
#else
#define LREG ld
#define SREG sd
#define REGBYTES 8
#define RELOC_TYPE R_RISCV_64
#define SYM_INDEX 0x20
#define SYM_SIZE 0x18
#endif

2. 对_start进行修饰
.section .text
.globl _start
_start:     /* 链接脚本里面指定了这里是uboot的入口 */
#if CONFIG_IS_ENABLED(RISCV_MMODE)
	csrr	a0, CSR_MHARTID
#endif
保存上一级boot传下来的参数
	/*
	 * Save hart id and dtb pointer. The thread pointer register is not
	 * modified by C code. It is used by secondary_hart_loop.
	 */
	mv	tp, a0   /* 上一级boot传下来的 hart id */
	mv	s1, a1   /* 上一级boot传下来的 uboot的fdt地址,如果有,没有就是0 */

	/*
	 * Set the global data pointer to a known value in case we get a very
	 * early trap. The global data pointer will be set its actual value only
	 * after it has been initialized.
	 */
	mv	gp, zero
设置异常入口函数
	/*
	 * Set the trap handler. This must happen after initializing gp because
	 * the handler may use it.
	 */
	la	t0, trap_entry  
	csrw	MODE_PREFIX(tvec), t0
##### 关中断
	/*
	 * Mask all interrupts. Interrupts are disabled globally (in m/sstatus)
	 * for U-Boot, but we will need to read m/sip to determine if we get an
	 * IPI
	 */
	csrw	MODE_PREFIX(ie), zero  /* sie寄存器清零,关中断 */

#if CONFIG_IS_ENABLED(SMP)
	/* check if hart is within range */
	/* tp: hart id */
	li	t0, CONFIG_NR_CPUS
	bge	tp, t0, hart_out_of_bounds_loop

	/* set xSIE bit to receive IPIs */
#if CONFIG_IS_ENABLED(RISCV_MMODE)
	li	t0, MIE_MSIE
#else
	li	t0, SIE_SSIE
#endif
	/* sie寄存器中,SSIE bit置为1 ,SSIE:interrupt-enable bits for supervisor level software interrupts.*/
	csrs	MODE_PREFIX(ie), t0   
#endif
设置堆栈,地址对齐,每个core都会分配自己的对站地址,挑选一个主core进行初始化,其他的core wait在wait_for_gd_init
/*
 * Set stackpointer in internal/ex RAM to call board_init_f
 */
call_board_init_f:
	li	t0, -16   /* -16 的16进制就是 0xffff fff0 ,用来对齐使用的 */
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) /* 这里是给SPL使用的 */
	li	t1, CONFIG_SPL_STACK
#else
	li	t1, CONFIG_SYS_INIT_SP_ADDR
#endif
	and	sp, t1, t0		/* 设置堆栈指针,并16byte对齐,force 16 byte alignment */

call_board_init_f_0:
	mv	a0, sp
	jal	board_init_f_alloc_reserve  /* 从sp高地址开始预留一段内存给global_data使用,返回的是减去预留后的地址,也就是gd的首地址*/

	/*
	 * Save global data pointer for later. We don't set it here because it
	 * is not initialized yet.
	 */
	mv	s0, a0

	/* setup stack ,设置新的堆栈,根据core的数量进行划分 */
#if CONFIG_IS_ENABLED(SMP)
	/* tp: hart id */
	slli	t0, tp, CONFIG_STACK_SIZE_SHIFT  /* tp保存的是当前core id,根据core id 进行sp的划分,每一个core分一块内存用作sp */
	sub	sp, a0, t0
#else
	mv	sp, a0
#endif

#ifndef CONFIG_XIP
	/*
	 * Pick hart to initialize global data and run U-Boot. The other harts
	 * wait for initialization to complete.
	 * 挑选一个core用来初始化uboot,其他的core等待gd初始化完成,opensbi/kernel都有类似的动作
	 */
	la	t0, hart_lottery
	li	t1, 1
	amoswap.w s2, t1, 0(t0)
	bnez	s2, wait_for_gd_init
#else
	/*
	 * FIXME: gp is set before it is initialized. If an XIP U-Boot ever
	 * encounters a pending IPI on boot it is liable to jump to whatever
	 * memory happens to be in ipi_data.addr on boot. It may also run into
	 * problems if it encounters an exception too early (because printf/puts
	 * accesses gd).
	 */
	mv	gp, s0
	bnez	tp, secondary_hart_loop
#endif

#ifdef CONFIG_OF_PRIOR_STAGE
	la	t0, prior_stage_fdt_address
	SREG	s1, 0(t0)   /* 把prior_stage_fdt_address 地址放在s1里面,如果不走这里,s1保存的是上级boot传下来的fdt地址,在下面会保存在gp里面*/
#endif

	jal	board_init_f_init_reserve  /* 参数a0 还是前面的gd的首地址,初始化global_data指针 */

	SREG	s1, GD_FIRMWARE_FDT_ADDR(gp)  /* 保存上面的prior_stage_fdt_address或者fdt的地址  -------www */
	/* save the boot hart id to global_data */
	SREG	tp, GD_BOOT_HART(gp)   /* 保存core   id */

#ifndef CONFIG_XIP
	la	t0, available_harts_lock
	/* t0地址里面的值1和数值0进行交换,原子操作,此时available_harts_lock就等于0了, rl: 被置位的原子指令保证其它线程在此之前看到顺序的原子操作 */
	amoswap.w.rl zero, zero, 0(t0) 

wait_for_gd_init:
	la	t0, available_harts_lock  /* 上面设置完后,available_harts_lock就是0了,available_harts_lock是一个全局的变量 */
	li	t1, 1
1:	amoswap.w.aq t1, t1, 0(t0)  /* t0的0赋值为t1, t1的1赋值为t0 */
	bnez	t1, 1b  /* 如果 t1 != 0, 循环,从这几行代码看,一次只有一个core能接着往下走,其他的core只能在这里循环???? */

	/*
	 * Set the global data pointer only when gd_t has been initialized.
	 * This was already set by arch_setup_gd on the boot hart, but all other
	 * harts' global data pointers gets set here.
	 */
	mv	gp, s0   /* s0里面就是global_data地址 */

	/* register available harts in the available_harts mask */
	li	t1, 1
	sll	t1, t1, tp
	LREG	t2, GD_AVAILABLE_HARTS(gp)  /* 先读取保存的 hart id */
	or	t2, t2, t1           /* 或上当前的hart id */
	SREG	t2, GD_AVAILABLE_HARTS(gp) /* 新的值回写到gp里面 */

	amoswap.w.rl zero, zero, 0(t0) /* available_harts_lock设置为0,上面死循环的core可以接着往下走了,释放其他的core吗? */

	/*
	 * Continue on hart lottery winner, others branch to
	 * secondary_hart_loop.
	 */
	 /* 
	  * s2里面存的是hart_lottery的值,第一个core获取到的hart_lottery是0,其他的core获取都是1 
	  * 其他的core进入secondary_hart_loop->wfi,第一个进来的core继续初始化。
	  */
	bnez	s2, secondary_hart_loop
#endif
设置icache和dcache
	/* Enable cache, 打开icache和dcache */
	jal	icache_enable
	jal	dcache_enable

#ifdef CONFIG_DEBUG_UART
	jal	debug_uart_init
#endif
设置参数调用board_init_f 进行环境的初始化,后面会详细讲board_init_f
	mv	a0, zero		/* a0 <-- boot_flags = 0 */
	/* 
	 * 如果是uboot,那么会调用common下面的board_f.c里面的函数,spl可能不是这个,要看编译配置 
	 * 这个函数会顺序执行init_sequence_f数组里面的函数
	 */
	la	t5, board_init_f 
	jalr	t5			/* jump to board_init_f(),执行完后,跳到本文件里面的relocate_code继续往下走 */
下面是SPL专用的代码,主要用于清bss,设置堆栈,最后跳到board_init_r
#ifdef CONFIG_SPL_BUILD
spl_clear_bss:
	la	t0, __bss_start
	la	t1, __bss_end
	beq	t0, t1, spl_stack_gd_setup

spl_clear_bss_loop:
	SREG	zero, 0(t0)
	addi	t0, t0, REGBYTES
	blt	t0, t1, spl_clear_bss_loop

spl_stack_gd_setup:
	jal	spl_relocate_stack_gd

	/* skip setup if we did not relocate */
	beqz	a0, spl_call_board_init_r
	mv	s0, a0

	/* setup stack on main hart */
#if CONFIG_IS_ENABLED(SMP)
	/* tp: hart id */
	slli	t0, tp, CONFIG_STACK_SIZE_SHIFT
	sub	sp, s0, t0
#else
	mv	sp, s0
#endif

#if CONFIG_IS_ENABLED(SMP)
	/* set new stack and global data pointer on secondary harts */
spl_secondary_hart_stack_gd_setup:
	la	a0, secondary_hart_relocate
	mv	a1, s0
	mv	a2, s0
	mv	a3, zero
	jal	smp_call_function

	/* hang if relocation of secondary harts has failed */
	beqz	a0, 1f
	mv	a1, a0
	la	a0, secondary_harts_relocation_error
	jal	printf
	jal	hang
#endif

	/* set new global data pointer on main hart */
1:	mv	gp, s0

spl_call_board_init_r:
	mv	a0, zero
	mv	a1, zero
	jal	board_init_r
#endif                      /* end  --- CONFIG_SPL_BUILD  */
下面是代码的重定位汇编程序,uboot会在board_init_f 的最后跳到这里执行,不再返回
/*
 * void relocate_code(addr_sp, gd, addr_moni)
 *
 * This "function" does not return, instead it continues in RAM
 * after relocating the monitor code.
 *
 */
.globl relocate_code
relocate_code:          /* 注意函数参数:relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr); */
	mv	s2, a0			/* save addr_sp */
	mv	s3, a1			/* save addr of gd */
	mv	s4, a2			/* save addr of destination */

/*
 *Set up the stack
 */
stack_setup:
#if CONFIG_IS_ENABLED(SMP)
	/* tp: hart id,这里使用的应该是重定向后的sp地址 */
	slli	t0, tp, CONFIG_STACK_SIZE_SHIFT
	sub	sp, s2, t0
#else
	mv	sp, s2
#endif

	la	t0, _start
	sub	t6, s4, t0		/* t6 <- relocation offset,t6里面存的是现在的地址和新地址之间的offset,s4里面存放的是重定向的目的地址 */
	beq	t0, s4, clear_bss	/* skip relocation,如果现在的start地址和新的目的地址一样,就不用重定位了 */

	mv	t1, s4			/* t1 <- scratch for copy_loop */
	la	t3, __bss_start
	sub	t3, t3, t0		/* t3 <- __bss_start_ofs */
	add	t2, t0, t3		/* t2 <- source end address */
	
//下面是代码的copy重定向,太长了,懒得看了
copy_loop:
	LREG	t5, 0(t0)
	addi	t0, t0, REGBYTES
	SREG	t5, 0(t1)
	addi	t1, t1, REGBYTES
	blt	t0, t2, copy_loop

/*
 * Update dynamic relocations after board_init_f
 */
fix_rela_dyn:
	la	t1, __rel_dyn_start
	la	t2, __rel_dyn_end
	beq	t1, t2, clear_bss
	add	t1, t1, t6		/* t1 <- rela_dyn_start in RAM */
	add	t2, t2, t6		/* t2 <- rela_dyn_end in RAM */

/*
 * skip first reserved entry: address, type, addend
 */
	j	10f

6:
	LREG	t5, -(REGBYTES*2)(t1)	/* t5 <-- relocation info:type */
	li	t3, R_RISCV_RELATIVE	/* reloc type R_RISCV_RELATIVE */
	bne	t5, t3, 8f		/* skip non-RISCV_RELOC entries */
	LREG	t3, -(REGBYTES*3)(t1)
	LREG	t5, -(REGBYTES)(t1)	/* t5 <-- addend */
	add	t5, t5, t6		/* t5 <-- location to fix up in RAM */
	add	t3, t3, t6		/* t3 <-- location to fix up in RAM */
	SREG	t5, 0(t3)
	j	10f

8:
	la	t4, __dyn_sym_start
	add	t4, t4, t6

9:
	LREG	t5, -(REGBYTES*2)(t1)	/* t5 <-- relocation info:type */
	srli	t0, t5, SYM_INDEX	/* t0 <--- sym table index */
	andi	t5, t5, 0xFF		/* t5 <--- relocation type */
	li	t3, RELOC_TYPE
	bne	t5, t3, 10f		/* skip non-addned entries */

	LREG	t3, -(REGBYTES*3)(t1)
	li	t5, SYM_SIZE
	mul	t0, t0, t5
	add	s5, t4, t0
	LREG	t0, -(REGBYTES)(t1)	/* t0 <-- addend */
	LREG	t5, REGBYTES(s5)
	add	t5, t5, t0
	add	t5, t5, t6		/* t5 <-- location to fix up in RAM */
	add	t3, t3, t6		/* t3 <-- location to fix up in RAM */
	SREG	t5, 0(t3)
10:
	addi	t1, t1, (REGBYTES*3)
	ble	t1, t2, 6b
设置新的重定向后的异常入口地址
/*
 * trap update, 代码已经重定位完成,设置tvec为重定位后的地址
*/
	la	t0, trap_entry
	add	t0, t0, t6
	csrw	MODE_PREFIX(tvec), t0
清bss
clear_bss:  /*  clear 重定位后的bss段内存 */
	la	t0, __bss_start		/* t0 <- rel __bss_start in FLASH */
	add	t0, t0, t6		/* t0 <- rel __bss_start in RAM */
	la	t1, __bss_end		/* t1 <- rel __bss_end in FLASH */
	add	t1, t1, t6		/* t1 <- rel __bss_end in RAM */
	beq	t0, t1, relocate_secondary_harts

clbss_l:
	SREG	zero, 0(t0)		/* clear loop... */
	addi	t0, t0, REGBYTES
	blt	t0, t1, clbss_l
relocate_secondary_harts:
#if CONFIG_IS_ENABLED(SMP)
	/* send relocation IPI */
	la	t0, secondary_hart_relocate
	add	a0, t0, t6

	/* store relocation offset */
	mv	s5, t6

	mv	a1, s2
	mv	a2, s3
	mv	a3, zero
	jal	smp_call_function

	/* hang if relocation of secondary harts has failed */
	beqz	a0, 1f
	mv	a1, a0
	la	a0, secondary_harts_relocation_error
	jal	printf
	jal	hang

	/* restore relocation offset */
1:	mv	t6, s5
#endif
调用board_init_r,进行第二阶段的初始化
/*
 * We are done. Do not return, instead branch to second part of board
 * initialization, now running from RAM.
 * 开始第二阶段的初始化,跳到board_init_r新的地址开始执行,不再返回了.......
 */
call_board_init_r:
	jal	invalidate_icache_all  //使icache无效
	jal	flush_dcache_all       //flush dcache
	la	t0, board_init_r        /* offset of board_init_r(),uboot使用的是common下面的board_r.c,spl要自己实现 */
	add	t4, t0, t6		/* real address of board_init_r() ,计算出新的重定位后的board_init_r的地址*/
/*
 * setup parameters for board_init_r
 */
	mv	a0, s3			/* gd_t */
	mv	a1, s4			/* dest_addr */

/*
 * jump to it ...
 */
	jr	t4			/* jump to board_init_r() */
#if CONFIG_IS_ENABLED(SMP)
hart_out_of_bounds_loop:
	/* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */
	wfi
	j	hart_out_of_bounds_loop

/* SMP relocation entry */
secondary_hart_relocate:
	/* a1: new sp */
	/* a2: new gd */
	/* tp: hart id */

	/* setup stack */
	slli	t0, tp, CONFIG_STACK_SIZE_SHIFT
	sub	sp, a1, t0

	/* update global data pointer */
	mv	gp, a2
#endif

/*
 * Interrupts are disabled globally, but they can still be read from m/sip. The
 * wfi function will wake us up if we get an IPI, even if we do not trap.
 */
secondary_hart_loop:
	wfi

#if CONFIG_IS_ENABLED(SMP)
	csrr	t0, MODE_PREFIX(ip)
#if CONFIG_IS_ENABLED(RISCV_MMODE)
	andi	t0, t0, MIE_MSIE
#else
	andi	t0, t0, SIE_SSIE
#endif
	beqz	t0, secondary_hart_loop

	mv	a0, tp
	jal	handle_ipi
#endif

	j	secondary_hart_loop
后面会分2个章节来讲解 board_init_f 和 board_init_r
正点原子嵌入式linux驱动开发——U-boot启动流程详解 正点原子linux驱动开发的学习笔记,这一篇是uboot的源码解读,来学习uboot的启动详细流程 阅读详情

相关推荐

riscv u-boot的hart_lottery机制

在多cpu中,第一个运行到这个位置的cpu(cpu0),t0为hart_lottery的地址,里面存储了0,amoswap.w.aqrl s2, t1, 0(t0)后使得s2存储了0,同时hart_lottery的地址里存储了t1的内容,这里t1在前面的代码赋了非0值,因此hart_lottery的地址里非0,因此cpu0中s2=0,不会到wait_for_gd_init。这段代码实现了一个自旋锁的获取过程。:在多核系统中,如果不同的Harts尝试同时访问同一资源(如内存、外设等),可能会导致资源冲突。

zhangqing2002的博客 807

玄铁处理器的Linux移植(三)—U-Boot、OpenSBI

如前所述,SPL级就是一个精简的U-Boot,所以U-Boot级的整体流程与SPL级很类似:初始化(start.S)—>board_init_f()—>重定位到DDR顶部(start.S)—>board_init_r(),然后board_init_r()函数中执行hush shell(U-Boot使用的一种小型shell),当输入启动命令时加载并启动OpenSBI(和Linux)。

qq_30031349的博客 3197

ADB详细(从下载安装到灵活运用)

ADB(Android Debug Bridge)是一种允许模拟器或已连接的 Android 设备进行通信的命令行工具,它可为各种设备操作提供便利,如安装和调试应用,并提供对 Unix shell(可用来在模拟器或连接的设备上运行各种命令)的访问。可以在Android SDK/platform-tools中找到 adb 工具或下载ADB Kits。

LiuYong_01的博客 10万+

RISC-V体系结构的U-Boot引导过程

flyfish

二分掌柜的 1万+

保姆级教程:手把手教你为裕泰微YT8521 PHY芯片编写Linux设备树(DTS)节点与驱动

本文提供了一份详细的保姆级教程,手把手教你为裕泰微YT8521 PHY芯片编写Linux设备树(DTS)节点与驱动。从基础配置到RGMII接口的特殊设置,再到驱动开发的关键步骤和调试技巧,帮助开发者快速掌握PHY芯片的移植与开发。

weixin_33734785的博客 333

Mediapipe手势识别实战——基于关节角度计算实现动态手势分类

本文详细介绍了如何利用Mediapipe进行手势识别,通过计算手指关节弯曲角度实现动态手势分类。文章从基础原理出发,讲解了关节角度计算的数学方法,并提供了Python实现代码。同时,还分享了数字手势和OK手势的识别实战经验,以及性能优化和工程实践中的关键技巧,帮助开发者快速掌握实时手势识别技术。

weixin_26891599的博客 403

Tiny4412 u-boot分析(2)u-boot启动流程

从大方面来说,u-boot的启动分成两个阶段,第一个阶段主要的职责是准备初始化的环境,主要有以下几点 ①设置异常向量表 ②把CPU的工作模式设置为SVC32模式 ③关闭中断、MMU和cache ④关闭看门狗 ⑤初始化内存、时钟、串口 ⑥设置堆栈 ⑦代码搬移 ⑧清bss段 ⑨跳转到c语言中执行(第二阶段) 此时系统还没有进入C语言的运行阶段,并没有堆栈,也就不需要额外的...

adl30141的博客 233

硬件描述语言Verilog学习(一)

主要学习综合和仿真、模块结构和信号类型Verilog 是用代码的形式描述硬件的功能,最终在硬件电路上实现该功能。在 Verilog 描述出硬件功能后需要使用综合器对 Verilog 代码进行解释并将代码转化成实际的电路来表示,最终产生实际的电路,也被称为网表。这种将 Verilog 代码转成网表的工具就是综合器。 上图左上角是一段 Verilog 代码,该代码实现了一个加法器的功能。在经过综合器解释后该代码被转化成一个加法器电路。QUARTUS、ISE 和 VIVADO 等 FPGA 开发工具都是综合器,

安静到无声 1499

ARMv8架构u-boot启动流程详细分析(2)

uboot

weixin_44810385的博客 2723

鲁棒控制理论 --- H∞ 控制(被裁篇)

鲁棒控制理论 --- H∞ 控制

记录老板的每次pua,分享领导每天的毒鸡汤... 6万+

8、 使用TPM密钥:从理论到实践的全面指南

本文全面介绍了如何使用TPM(可信平台模块)进行密钥管理,涵盖密钥的创建、存储、加载、迁移以及特殊密钥类型的使用。通过详细的操作步骤和代码示例,帮助读者掌握TPM密钥管理技术,确保系统的安全性和可靠性。

weixin_36212459的博客 242

Mini2440学习日记(2)_U-boot的启动流程分析

Mini2440学习日记(1) --U-boot简介及启动流程分析 一、U-boot的引入 我们来回忆一下PC的体系结构:PC机中的引导加载程序是由BIOS和位于硬盘MBR中的OS Boot Loader(比如LILO和GRUB等)一起组成的,BIOS在完成硬件检测和资源分配后,将硬盘MBR中的Boot Loader读到系统的RAM中,然后将控制权交给OS Boot Loader。B

qq_17691347的博客 321

2025最新!视频动作识别算法的前沿研究与论文解读

2025最新!视频动作识别算法的前沿研究与论文解读 ,人工智能,计算机视觉,大模型,AI,本文聚焦2025年视频动作识别算法前沿,先介绍其定义、意义及核心挑战,再阐述传统与深度学习方法。还解读了基于Transformer、轻量化、跨模态融合和半监督学习的前沿研究,解释关键概念,列举常用数据集、评价指标,分析当前问题与未来趋势,为该领域研究提供全面参考。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 7万+

u-boot移植启动流程详细分析(2)

u-boot的第二阶段的启动过程究竟是怎样的呢,相信看过的你,会对你的内存有所扩充

疯子阳1991 3859

工业相机,大恒,面振相机8脚电源线和I/O触发接口线,颜色和接法说明和触发软件设定

上图: 说明一下,工业相机有TTL逻辑电平触发,也有光耦触发等。 这里一般我们用电路板驱动,就用GPIO触发模式, 这里,准备了两个GPIO触发模式,为LINE2,LINE3都可以选择,然后有一个GPIO_GND 如果,你只有一个触发接口,那么如图,选两个就好了。 实际接法如图。 ...

山云的专栏 1万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

u-boot启动流程分析(2)_板级(board)部分

1. 前言书接上文(u-boot启动流程分析(1)_平台相关部分),本文介绍u-boot启动流程中和具体版型(board)有关的部分,也即board_init_f/board_init_r所代表的、board有关初始化过程。该过程将持续u-boot的整个生命周期,直到main_loop(即传说中的命令行)。注1:由于u-boot后初始化过程,基本上涉及到了所有的软件模块,因此本文不能一一分析,基本...

coolJoezhou的博客 1140

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Linux启动lumerical服务,u-boot启动流程分析(2)_板级(board)部分

u-boot启动流程分析(2)_板级(board)部分作者:wowo 发布于:2016-6-7 22:06分类:u-boot分析1. 前言书接上文(u-boot启动流程分析(1)_平台相关部分),本文介绍u-boot启动流程中和具体版型(board)有关的部分,也即board_init_f/board_init_r所代表的、board有关初始化过程。该过程将持续u-boot的整个生命周期,直到ma...

weixin_42123456的博客 1007

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Hi3556v200 u-boot+Liteos方案启动流程分析--2.通用uboot start.S分析

目录1.前言2.主要流程2.1 _start2.2 reset2.3 set SVC32 mode2.4 Setup vector2.5 cpu_init_cp152.6 _main2.6.1 设置初始运行环境2.6.2 board_init_fboard_init_f_alloc_reserveboard_init_f_init_reserveboard_init_f2.6.3 Set up intermediate environment参考文档 1.前言 本文主要就Hi3556v200的U-boot+

HZero 1090
上一篇: U-boot 启动流程分析 1
下一篇: U-boot 启动流程分析 3
Runner_Linux
博客等级 码龄6年 17粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值