Java教程

start.S分析

本文主要是介绍start.S分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 头文件包含
  • 预留校验头与中断异常向量表
  • 中断异常处理与字节对齐(十六字节)
  • 定义了一个类似指针的东西指向的位置是链接地址
  • 物理地址
  • 中断处理
  • 设置状态寄存器cpsr
  • cache
  • MMU
  • 启动介质
  • 设置栈,调用lowlevel_init
  • 供电锁存
  • 第二次设置栈
  • 判断是否要重定位
  • 判断是SD0还是 SD2启动
  • 真正的重定位操作
  • 虚拟地址映射
  • 第三次设置栈
  • 清BSS段
  • 第一阶段最后一步

头文件包含

/*
 *  armboot - Startup Code for S5PC110/ARM-Cortex CPU-core
 *
 *  Copyright (c) 2009	Samsung Electronics
 *
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 *
 * Base codes by scsuh (sc.suh)
 */

#include <config.h>    	@@在mkconfig里边编译生成的,位置include目录下
#include <version.h>	@@包含一个头文件,头文件里存到版本号
#if defined(CONFIG_ENABLE_MMU)
#include <asm/proc/domain.h>   @@跟mkconfig有关,符号链接
#endif
#include <regs.h>			@@跟mkconfig有关,符号链接

#ifndef CONFIG_ENABLE_MMU
#ifndef CFG_PHY_UBOOT_BASE
#define CFG_PHY_UBOOT_BASE	CFG_UBOOT_BASE
#endif
#endif

预留校验头与中断异常向量表

#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
	.word 0x2000		@@定义了一个变量(四个字节),这个变量的值是0x2000
	.word 0x0
	.word 0x0
	.word 0x0
#endif
@@这十六字节是为了那十六字节的校验头预留的
@@什么要加这十六字节的数据呢;SD卡启动/Nand启动等整个镜像开头需要16字节的校验头,所以先在这占着,SD启动的时候mkv210image.c会给它加16字节的校验头(现在这个校验和是不对的,后边要去计算校验重新填充)
@@这十六字节是为了那十六字节的校验头预留的
.globl _start	@@.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
_pad:
	.word 0x12345678 /* now 16*4=64 */
.global _end_vect
_end_vect:

	.balignl 16,0xdeadbeef		@@di zhi dui qi,这些内存用0xdeadbeef	来填充

定义了一个类似指针的东西指向的位置是链接地址

/*
 *************************************************************************
 *
 * Startup Code (reset vector)
 *
 * do important init only if we don't start from memory!
 * setup Memory and board specific bits prior to relocation.
 * relocate armboot to ram
 * setup stack
 *
 *************************************************************************
 */

_TEXT_BASE:				@@链接地址;TEXT_BASE = 0xc3e00000
	.word	TEXT_BASE		@@在makefile的2591行有给他一个地址(这个值来自于makefile)
	

物理地址

主要用来后边清理bss段

/*
 * Below variable is very important because we use MMU in U-Boot.
 * Without it, we cannot run code correctly before MMU is ON.
 * by scsuh.
 */
_TEXT_PHY_BASE:			@@物理地址
	.word	CFG_PHY_UBOOT_BASE

.globl _armboot_start
_armboot_start:
	.word _start

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
	.word __bss_start

.globl _bss_end
_bss_end:
	.word _end

中断处理

uboot中很少使用

#if defined(CONFIG_USE_IRQ)
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
	.word	0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
	.word 0x0badc0de
#endif

设置状态寄存器cpsr

/*
 * the actual reset code
 */

reset:
	/*
	 * set the cpu to SVC32 mode and IRQ & FIQ disable
	 */
	@;mrs	r0,cpsr
	@;bic	r0,r0,#0x1f
	@;orr	r0,r0,#0xd3
	@;msr	cpsr,r0
	msr	cpsr_c, #0xd3		@ I & F disable, Mode: 0x13 - SVC
	@@cpsr 是cheng xu 状态寄存器;_c 为0~7位;
	@@CPU设置为禁止FIQ和 IRQ,状态是ARM状态,SVC模式

在这里插入图片描述

cache

@@底层的初始化
	bl	disable_l2cache		@@禁止L2 cache

	bl	set_l2cache_auxctrl_cycle		@@L2 cache相关的初始化

	bl	enable_l2cache			@@使能L2 cache
	
       /*
        * Invalidate L1 I/D   	@@刷新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  @@关闭MMU
        */
        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

启动介质

判断是nand还是sd启动

/* Read booting information */		@@读取启动信息
        ldr	r0, =PRO_ID_BASE		@@PRO_ID_BASE寄存器通过读取硬件OM引脚,判断启动介质是nand还是sd
        ldr	r1, [r0,#OMR_OFFSET]
        bic	r2, r1, #0xffffffc1		@@将启动的信息存在r2中,r2的值决定了是从SD启动还是nand启动
/* NAND BOOT */
	cmp	r2, #0x0		@ 512B 4-cycle
	moveq	r3, #BOOT_NAND

	cmp	r2, #0x2		@ 2KB 5-cycle
	moveq	r3, #BOOT_NAND

	cmp	r2, #0x4		@ 4KB 5-cycle	8-bit ECC
	moveq	r3, #BOOT_NAND

	cmp	r2, #0x6		@ 4KB 5-cycle	16-bit ECC
	moveq	r3, #BOOT_NAND

	cmp	r2, #0x8		@ OneNAND Mux
	moveq	r3, #BOOT_ONENAND

	/* SD/MMC BOOT */
	cmp     r2, #0xc
	moveq   r3, #BOOT_MMCSD	
	@@通过比较r2里边的值,确定r3里的值
	/* NOR BOOT */
	cmp     r2, #0x14
	moveq   r3, #BOOT_NOR	

设置栈,调用lowlevel_init

到这要去分析lowlevel_init这个函数
	/*
	 * Go setup Memory and board specific bits prior to relocation.
	 */
	@@设置栈,栈的位置在SRAM(DDR);
	ldr	sp, =0xd0036000 /* end of sram dedicated to u-boot */
	sub	sp, sp, #12	/* set stack */
	mov	fp, #0
	
	bl	lowlevel_init	/* go setup pll,mux,memory */			@@初始化一些底层的东西

供电锁存

没有什么意义,lowleve_init.S里有锁存过

/* To hold max8698 output before releasing power on switch,
	 * set PS_HOLD signal to high
	 */
	ldr	r0, =0xE010E81C  /* PS_HOLD_CONTROL register */	@@供电锁存
	ldr	r1, =0x00005301	 /* PS_HOLD output high	*/
	str	r1, [r0]

第二次设置栈

/* get ready to call C functions */ 			@@设置栈(又),这次栈的位置在DDR里边。为什么要再次设置,因为原来SRAM中的内存少,容易溢出
	ldr	sp, _TEXT_PHY_BASE	/* setup temp stack pointer */
	sub	sp, sp, #12
	mov	fp, #0			/* no previous frame, so fp=0 */

判断是否要重定位

/* 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     after_copy		/* r0 == r1 then skip flash copy   */

判断是SD0还是 SD2启动

#if defined(CONFIG_EVT1)
	/* If BL1 was copied from SD/MMC CH2 */
	ldr	r0, =0xD0037488			@@这个寄存器 硬件会自动往这里给值,通过这个值判断使用的是哪个口SD0是0xEB000000 SD2是0xEB200000
	ldr	r1, [r0]
	ldr	r2, =0xEB200000
	cmp	r1, r2		@@读出来的值跟0xEB200000比较
	beq  
ldr	r0, =INF_REG_BASE			
ldr	r1, [r0, #INF_REG3_OFFSET]		@@在把277行存入的值取出来
cmp	r1, #BOOT_NAND		/* 0x0 => boot device is nand */			@@在比较,确定启动方式,跳转到BOOT_MMCSD
beq	nand_boot
cmp	r1, #BOOT_ONENAND	/* 0x1 => boot device is onenand */
beq	onenand_boot
cmp     r1, #BOOT_MMCSD
beq     mmcsd_boot
cmp     r1, #BOOT_NOR
beq     nor_boot
cmp     r1, #BOOT_SEC_DEV
beq     mmcsd_boot

nand_boot:
mov r0, #0x1000
bl copy_from_nand
b after_copy

onenand_boot:
bl onenand_bl2_copy
b after_copy

mmcsd_boot:
#if DELETE @@设置栈(又又)删掉了
ldr sp, _TEXT_PHY_BASE
sub sp, sp, #12
mov fp, #0
#endif

真正的重定位操作

去movi.c文件分析

	bl      movi_bl2_copy		@@真正的重定位在是这个函数里实现的

虚拟地址映射

	b       after_copy			@@虚拟地址映射

after_copy:

#if defined(CONFIG_ENABLE_MMU)
enable_mmu:
	/* enable domain access */		@@使能预访问
	ldr	r5, =0x0000ffff
	mcr	p15, 0, r5, c3, c0, 0		@load domain access register		
	@@协处理器里的c3是用来控制域访问的
	@@
	@@mcr指令是用来写协处理器的,mrc指令是用来读协处理器的
	/* Set the TTB register */		@@TTB就是转换表的基址;找出重定位到DDR里边的转换表的地址
	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

	/* Enable the MMU */
mmu_on:
	mrc	p15, 0, r0, c1, c0, 0		@@将c1的值读到r0
	orr	r0, r0, #1						@@把1或到r0
	mcr	p15, 0, r0, c1, c0, 0		@@将r0的值写到c1,打开MMU
	nop
	nop
	nop
	nop
#endif

第三次设置栈

skip_hw_init:
	/* Set up the stack						    */
stack_setup:
#if defined(CONFIG_MEMORY_UPPER_CODE)
	ldr	sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)		@@第三次设置栈是在合适的位置设置栈;安全、紧凑不浪费内存;设置在uboot起始地址上方的2M那,栈是满减栈
#else
	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
	sub	r0, r0, #CFG_MALLOC_LEN	/* malloc area                      */
	sub	r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
#if defined(CONFIG_USE_IRQ)
	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
	sub	sp, r0, #12		/* leave 3 words for abort-stack    */

#endif

清BSS段

clear_bss:			@@清BSS段
	ldr	r0, _bss_start		/* find start of bss segment        */@@_bss_start 来自链接脚本,但是他的值在本文件里定义
	ldr	r1, _bss_end		/* stop here                        */				@@_end 来自链接脚本,但是他的值在本文件里定义
	mov 	r2, #0x00000000		/* clear                            */

第一阶段最后一步

clbss_l:
	str	r2, [r0]		/* clear loop...                    */
	add	r0, r0, #4
	cmp	r0, r1
	ble	clbss_l
	
	ldr	pc, _start_armboot				@@第一阶段的最后一步,也是第二阶段的开始;使用的是远跳转,可以从SRAM跳转到DDR中(当前还在SRAM中运行);_start_armboot 相当于一个指针,指向一个函数
										@@在uboot/lib_arm/board.c
这篇关于start.S分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!