u-boot start.S启动文件分析

u-boot start.S启动文件分析

u-bootstart.SBL1

      • u-boot start.S启动文件分析

        • 一、start.S来源

          • 1.为何要分析start.S
          • 2.start.S的来源
          • 3.头文件包含
        • 二、start.S分析
          • 1.Start.S分析

            • 16字节校验头
            • 异常向量表
            • 16字节内存对齐
            • 设置CPU为SVC模式
            • L2 cache操作
            • Invalidate L1 I/D
            • 关掉MMU
            • 读取启动引脚信息
            • 第一次设置栈
            • ./board/samsung/x210/lowlevel_init.S
            • 第二次设置栈
            • 再次判断当前代码执行的位置
            • 判断是否进入SD2卡启动
            • ./cpu/s5pc11x/movi.c
            • 使能MMU域访问(cp15的c3寄存器)
            • 设置TTB(cp15的c2寄存器)
            • 使能MMU
            • 第三次设置栈
            • 清BBS段
            • 进入BL2
          • 2.lowlevel_init.S分析
            • lr压栈
            • 检查复位状态
            • IO状态恢复
            • 关看门狗
            • SRAM与SROM配置
            • 供电锁存
            • 判断当前代码执行的位置
            • 初始化系统时钟
            • 初始化DDR
            • 初始化串口,发送O
            • trust zone初始化
            • 串口发送K
        • 三、我认为有用的步骤

u-boot start.S启动文件分析

??本分析采用的不是官方u-boot,而是采用九鼎移植之后的u-boot,原u-boot版本为1.3.4。

一、start.S来源

1.为何要分析start.S

??start.S相当于BL1,对我们理解uboot启动至关重要

2.start.S的来源

??可以通过link.lds链接脚本来得到start.S的位置

3.头文件包含
head file position description
config.h ./include/configs/x210_sd.h 输入make x210_sd_config后执行mkconfig最终生成,是最为关键的头文件
version.h ./include/version_autogenerated.h 主makefile第一步中生成,包含版本信息
asm/proc/domain.h include/asm-arm/proc-armv/domain.h 运用mkconfig中的符号链接,包含domain.h,有关IO,内核,用户内存
regs.h ./include/s5pc110.h 运用mkconfig中的符号链接,包括s5pc110中的寄存器定义

二、start.S分析

1.Start.S分析

16字节校验头

十六字节校验头

#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
	.word 0x2000
	.word 0x0
	.word 0x0
	.word 0x0
#endif

异常向量表

.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

16字节内存对齐

.balignl 16,0xdeadbeef

设置CPU为SVC模式

msr	cpsr_c, #0xd3		

@ I & F disable, Mode: 0x13 - SVC

cpsr寄存器

??0xd3 = 1101 0011 b,工作状态为arm态,关闭FIQ,IRQ,使工作模式为SVC。

L2 cache操作
bl	disable_l2cache				// 禁止L2 cache
bl	set_l2cache_auxctrl_cycle	// l2 cache相关初始化
bl	enable_l2cache				// 使能l2 cache

Invalidate L1 I/D

@ 刷新L1 cache的icache和dcache。
mov	r0, #0                  @ set up for MCR
mcr	p15, 0, r0, c8, c7, 0   @ invalidate TLBs
mcr	p15, 0, r0, c7, c5, 0   @ invalidate icache

关掉MMU

@ disable MMU stuff and 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 12 (Z---) BTB
mcr 	p15, 0, r0, c1, c0, 0

读取启动引脚信息

/* 在210内部有一个寄存器(地址是0xE0000004)
 * 这个寄存器中的值是硬件根据OM引脚的设置而自动设置值的
 * 可以通过读取这个寄存器的值然后判断其值来确定当前选中的启动介质是Nand还是SD还是其他的。
 */
ldr	r0, =PRO_ID_BASE
ldr	r1, [r0,#OMR_OFFSET]
bic	r2, r1, #0xffffffc1

??经过一系列比较,得到

/* SD/MMC BOOT */
cmp     r2, #0xc	// c即为SD或MMC启动
moveq   r3, #BOOT_MMCSD
// r3中存储了0x03

??然后再将0x3放入INFORM3寄存器

第一次设置栈
	ldr	sp, =0xd0036000 /* end of sram dedicated to u-boot */
	sub	sp, sp, #12	/* set stack */
	mov	fp, #0

??这个栈地址设置在SROM中,并且没有按照三星要求来做。因为接下来需要调用C函数,所以需要先设置Stack。

./board/samsung/x210/lowlevel_init.S

??主要完成关看门狗,供电锁存,判断当前代码执行位置,初始化时钟,初始化DDR,初始化串口。

第二次设置栈
	/* get ready to call C functions */
	ldr	sp, _TEXT_PHY_BASE	/* setup temp stack pointer */
	sub	sp, sp, #12
	mov	fp, #0			/* no previous frame, so fp=0 */

??_TEXT_PHY_BASE = 0x33E0 0000,这里的栈设置在DDR中,沿着uboot起始地址向下。

再次判断当前代码执行的位置

判断是否进入SD2卡启动

#if defined(CONFIG_EVT1)
	/* If BL1 was copied from SD/MMC CH2 */
	ldr	r0, =0xD0037488		//	V210_SDMMC_BASE current boot channel
	ldr	r1, [r0]
	ldr	r2, =0xEB200000		//	SD卡通道二
	cmp	r1, r2
	beq     mmcsd_boot
#endif

??当前启动状态与SD卡通道2的启动地址比较,进入mmcsd_boot。

#if DELETE
	ldr     sp, _TEXT_PHY_BASE
	sub     sp, sp, #12
	mov     fp, #0
#endif
	bl      movi_bl2_copy
	b       after_copy

??进入movi_bl2_copy函数

./cpu/s5pc11x/movi.c

??复制uboot代码到DDR中

void movi_bl2_copy(void)
{
	ulong ch;
#if defined(CONFIG_EVT1)
	ch = *(volatile u32 *)(0xD0037488);	// EB20_0000通道2启动
	copy_sd_mmc_to_mem copy_bl2 =
	    (copy_sd_mmc_to_mem) (*(u32 *) (0xD0037F98));

	#if defined(CONFIG_SECURE_BOOT)
	ulong rv;
	#endif
#else
	ch = *(volatile u32 *)(0xD003A508);
	copy_sd_mmc_to_mem copy_bl2 =
	    (copy_sd_mmc_to_mem) (*(u32 *) (0xD003E008));
#endif
	u32 ret;
	//	iNand
	if (ch == 0xEB000000) {
		ret = copy_bl2(0, MOVI_BL2_POS, MOVI_BL2_BLKCNT,
			CFG_PHY_UBOOT_BASE, 0);

#if defined(CONFIG_SECURE_BOOT)
		/* do security check */
		rv = Check_Signature( (SecureBoot_CTX *)SECURE_BOOT_CONTEXT_ADDR,
				      (unsigned char *)CFG_PHY_UBOOT_BASE, (1024*512-128),
			              (unsigned char *)(CFG_PHY_UBOOT_BASE+(1024*512-128)), 128 );
		if (rv != 0){
				while(1);
			}
#endif
	}
	// SD卡2
	else if (ch == 0xEB200000) {
		ret = copy_bl2(2, MOVI_BL2_POS, MOVI_BL2_BLKCNT,
			CFG_PHY_UBOOT_BASE, 0);

#if defined(CONFIG_SECURE_BOOT)
		/* do security check */
		rv = Check_Signature( (SecureBoot_CTX *)SECURE_BOOT_CONTEXT_ADDR,
				      (unsigned char *)CFG_PHY_UBOOT_BASE, (1024*512-128),
			              (unsigned char *)(CFG_PHY_UBOOT_BASE+(1024*512-128)), 128 );
		if (rv != 0) {
			while(1);
		}
#endif
	}
	else
		return;

	if (ret == 0)
		while (1)
			;
	else
		return;
}

??从上一步图片中的寄存器判断是SD0还是SD2启动,然后再使用device copy function复制代码到DDR中。

使能MMU域访问(cp15的c3寄存器)
#if defined(CONFIG_ENABLE_MMU)
enable_mmu:
	/* enable domain access */
	ldr	r5, =0x0000ffff
	mcr	p15, 0, r5, c3, c0, 0		@load domain access register

设置TTB(cp15的c2寄存器)

	/* Set the TTB register */
	// 开启translation table base
	ldr	r0, _mmu_table_base
	ldr	r1, =CFG_PHY_UBOOT_BASE
	ldr	r2, =0xfff00000
	bic	r0, r0, r2
	orr	r1, r0, r1
	mcr	p15, 0, r1, c2, c0, 0

??MMU映射表是其中关键。

	/* form a first-level section entry */
	// .macro用于生成宏,.endm用于结束宏,.word表示的数即为表项
.macro FL_SECTION_ENTRY base,ap,d,c,b
	.word (\base << 20) | (\ap << 10) | 	      (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)
.endm
.section .mmudata, "a"
	.align 14
	// the following alignment creates the mmu table at address 0x4000.
	.globl mmu_table
mmu_table:
	.set __base,0
	// Access for iRAM
	// 伪指令.rept相当于循环开始,0x100为循环次数
	.rept 0x100
	FL_SECTION_ENTRY __base,3,0,0,0
	.set __base,__base+1
	// 循环结束
	.endr

	// Not Allowed
	.rept 0x200 - 0x100
	.word 0x00000000
	.endr

	.set __base,0x200
	// should be accessed
	.rept 0x600 - 0x200
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr

	.rept 0x800 - 0x600
	.word 0x00000000
	.endr

	.set __base,0x800
	// should be accessed
	.rept 0xb00 - 0x800
	FL_SECTION_ENTRY __base,3,0,0,0
	.set __base,__base+1
	.endr

/*	.rept 0xc00 - 0xb00
	.word 0x00000000
	.endr */

	.set __base,0xB00
	.rept 0xc00 - 0xb00
	FL_SECTION_ENTRY __base,3,0,0,0
	.set __base,__base+1
	.endr

	// 0xC000_0000映射到0x3000_0000
	.set __base,0x300
	//.set __base,0x200
	// 256MB for SDRAM with cacheable
	.rept 0xD00 - 0xC00
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr

	// access is not allowed.
	@.rept 0xD00 - 0xC80
	@.word 0x00000000
	@.endr

	.set __base,0xD00
	// 1:1 mapping for debugging with non-cacheable
	.rept 0x1000 - 0xD00
	FL_SECTION_ENTRY __base,3,0,0,0
	.set __base,__base+1
	.endr	

	#else	// CONFIG_MCP_AC, CONFIG_MCP_H, CONFIG_MCP_B
物理地址 映射地址
0x0000_0000-0FFF_FFFF 0x0000_0000-0FFF_FFFF
0x1000_0000-1FFF_FFFF Not allowed
0x2000_0000-5FFF_FFFF 0x2000_0000-5FFF_FFFF
0x6000_0000-7FFF_FFFF Not allowed
0x8000_0000-AFFF_FFFF 0x8000_0000-AFFF_FFFF
0xB000_0000-BFFF_FFFF 0xB000_0000-BFFF_FFFF
0xC000_0000-CFFF_FFFF 0x3000_0000-3FFF_FFFF
0xD000_0000-FFFF_FFFF 0xD000_0000-FFFF_FFFF
使能MMU
	/* Enable the MMU */
	// 使能MMU
mmu_on:
	mrc	p15, 0, r0, c1, c0, 0
	orr	r0, r0, #1
	mcr	p15, 0, r0, c1, c0, 0
	nop
	nop

第三次设置栈

	// 第三次设置栈
	/* Set up the stack						    */
stack_setup:
#if defined(CONFIG_MEMORY_UPPER_CODE)
	ldr	sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)

??其中CFG_UBOOT_BASE=0xC3E0_0000CFG_UBOOT_SIZE=2M

清BBS段
clear_bss:
	ldr	r0, _bss_start		/* find start of bss segment        */
	ldr	r1, _bss_end		/* stop here                        */
	mov 	r2, #0x00000000		/* clear                            */

clbss_l:
	str	r2, [r0]		/* clear loop...                    */
	add	r0, r0, #4
	cmp	r0, r1
	ble	clbss_l

进入BL2

	ldr	pc, _start_armboot

_start_armboot:
	.word start_armboot

2.lowlevel_init.S分析

lr压栈

	push	{lr}

检查复位状态

??CPU允许多种复位状况。我们需要在复位代码中检测复位状态。

	ldr	r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
	ldr	r1, [r0]
	bic	r1, r1, #0xfff6ffff
	cmp	r1, #0x10000
	beq	wakeup_reset_pre
	cmp	r1, #0x80000
	beq	wakeup_reset_from_didle
IO状态恢复
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)
	ldr	r1, [r0]
	ldr	r2, =IO_RET_REL
	orr	r1, r1, r2
	str	r1, [r0]

关看门狗

	ldr	r0, =ELFIN_WATCHDOG_BASE	/* 0xE2700000 */
	mov	r1, #0
	str	r1, [r0]

SRAM与SROM配置

??略过。

供电锁存
	/* PS_HOLD pin(GPH0_0) set to high */
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)
	ldr	r1, [r0]
	orr	r1, r1, #0x300
	orr	r1, r1, #0x1
	str	r1, [r0]

判断当前代码执行的位置

	/* when we already run in ram, we don‘t need to relocate U-Boot.
	 * and actually, memory controller must be configured before U-Boot
	 * is running in ram.
	 */
	ldr	r0, =0xff000fff
	bic	r1, pc, r0		/* r0 <- current base addr of code */
	ldr	r2, _TEXT_BASE		/* r1 <- original base addr in ram */
	bic	r2, r2, r0		/* r0 <- current base addr of code */
	cmp     r1, r2                  /* compare r0, r1                  */
	beq     1f			/* r0 == r1 then skip sdram init   */
	//	1表示编号,f表示
	forward,向后找

??这里采用的方法是截取现在地址的12-14位,以及链接时地址的12-14位,如果相等,则可以判断程序已经在DDR中,否则可认为程序仍然在SROM中。

初始化系统时钟

??进入system_clock_init函数

初始化DDR

??进入mem_ctrl_asm_init函数,DMC0_MEMCONFIG_0,在裸机中配置值为0x20E01323;在uboot中配置为0x30F01313.这个配置不同就导致结果不同。

??在 裸机中DMC0的256MB内存地址范围是0x20000000-0x2FFFFFFF;

??在uboot中DMC0的256MB内存地址范围为0x30000000-0x3FFFFFFF。

初始化串口,发送O

??进入uart_asm_init函数,初始化完成后发送一个O

trust zone初始化

??进入tzpc_init函数

串口发送K

??发送K后,返回pop {pc}

三、我认为有用的步骤

原文地址:https://www.cnblogs.com/0nism/p/12380583.html

时间: 2024-10-09 21:36:36

u-boot start.S启动文件分析的相关文章

STM32启动过程--启动文件--分析

一.概述 1.说明 每一款芯片的启动文件都值得去研究,因为它可是你的程序跑的最初一段路,不可以不知道.通过了解启动文件,我们可以体会到处理器的架构.指令集.中断向量安排等内容,是非常值得玩味的. STM32作为一款高端Cortex-M3系列单片机,有必要了解它的启动文件.打好基础,为以后优化程序,写出高质量的代码最准备. 本文以一个实际测试代码--START_TEST为例进行阐述. 2.整体过程概括 STM整个启动过程是指从上电开始,一直到运行到main函数之间的这段过程,步骤为(以使用微库为例

关于ARM CM3的启动文件分析

下面以ARM Cortex_M3裸核的启动代码为例,做一下简单的分析.首先,在启动文件中完成了三项工作: 1.  堆栈以及堆的初始化 2.  定位中断向量表 3.  调用Reset Handler. 在介绍之前,我们先了解一下ARM芯片启动文件中涉及到的一些汇编指令的用法. 补充一下,其中DCD相当于C语言当中的&,定义地址. 1.堆栈以及堆的初始化 1.1 堆栈的初始化 Startup_xxx.s中的堆栈初始化代码 Stack_Size  EQU  0x00000400,这个语句相当于Stac

关于启动文件分析的(MDK-ARM) 【转】

;******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** ;* File Name : startup_stm32f10x_hd.s ;* Author : MCD Application Team ;* Version : V3.4.0 ;* Date : 10/15/2010 ;* Description : STM32F10x High Density Devices vector ta

stm32f407启动文件分析

; Amount of memory (in bytes) allocated for Stack; Tailor this value to your application needs; <h> Stack Configuration; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h> Stack_Size EQU 0x00000400      ;EQU定义栈空间的大小,栈空间由编译器自动分配变量所占

关于 ARM Cortex-M3 的启动文件分析及分散加载

原文 https://blog.strongwong.top/posts/%E5%85%B3%E4%BA%8E-ARM-Cortex-M3-%E7%9A%84%E5%90%AF%E5%8A%A8%E6%96%87%E4%BB%B6%E5%88%86%E6%9E%90%E5%8F%8A%E5%88%86%E6%95%A3%E5%8A%A0%E8%BD%BD.html 原文地址:https://www.cnblogs.com/dreamblog/p/11404104.html

spring boot应用启动原理分析

spring boot quick start 在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个Web Server. 如果之前没有使用过spring boot可以通过下面的demo来感受下. 下面以这个工程为例,演示如何启动Spring boot项目: git clone [email protected]:hengyunabc/spring-boot-demo.git mvn spring-b

ubuntu为什么没有/etc/inittab文件? 深究ubuntu的启动流程分析

最近,因和队友一起做linux开发,因为用的不是同一版本linux(他用arch, 我用ubuntu),再配置上经常就不一样,就如这个inittab文件,于是深究了一下原因: Linux 内核启动 init ,init进程ID是1,是所有进程的父进程,所有进程由它控制. Ubuntu 的启动由upstart控制,自9.10后不再使用/etc/event.d目录的配置文件,改为/etc/init. 查看当前的运行级别,Ubuntu 桌面默认是2. ? 1 runlevel Ubuntu 的系统运行

涨姿势:Spring Boot 2.x 启动全过程源码分析

上篇<Spring Boot 2.x 启动全过程源码分析(一)入口类剖析>我们分析了 Spring Boot 入口类 SpringApplication 的源码,并知道了其构造原理,这篇我们继续往下面分析其核心 run 方法. [toc] SpringApplication 实例 run 方法运行过程 上面分析了 SpringApplication 实例对象构造方法初始化过程,下面继续来看下这个 SpringApplication 对象的 run 方法的源码和运行流程. public Conf

u-boot启动流程分析(1)_平台相关部分

转自:http://www.wowotech.net/u-boot/boot_flow_1.html 1. 前言 本文将结合u-boot的“board—>machine—>arch—>cpu”框架,介绍u-boot中平台相关部分的启动流程.并通过对启动流程的简单分析,掌握u-boot移植的基本方法. 注1:本文所使用的u-boot版本,是2016/4/23从u-boot官网(git://git.denx.de/u-boot.git)导入的一个快照,具体可参考“https://github