uboot-2009-11版本學習分析

以下內容是自己一條一條分析的,主要是個大概不是很詳細,因爲本人也是剛剛開始看這個代碼,下面的代碼裏註釋了所有start.s裏使用的彙編指令和自己的理解,如果有不正確的地方希望大家指出共同進步

/*
 *  armboot - Startup Code for ARM920 CPU-core
 *
 *  Copyright (c) 2001	Marius Gr�ger <[email protected]>
 *  Copyright (c) 2002	Alex Z�pke <[email protected]>
 *  Copyright (c) 2002	Gary Jennejohn <[email protected]>
 *
 * 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
 */

#include <common.h>
#include <config.h>

/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */


.globl _start /*global:聲明全局函數或者變量,此處的_start爲一個程序的入口*/
/*異常向量表的設置
 *當發生異常時CPU會直接跳到對應的異常向量表處執行,此時就可以理解爲什麼使用了 b start_code而不是 bl start_code了
 *異常向量表的位置依次是0x0,0x4,0x8,0xc,0x10,0x14,0x18,0x1c
 */
_start:	b	start_code               /**/
	ldr	pc, _undefined_instruction  /*此處根據ldr指令理解,ldr是將內存中的值賦值給寄存器,
									 *在_undefined_instruction函數下只有定義了一個undefined_instruction
									 *表示某個地址,ldr執行操作取_undefined_instruction地址處的內容undefined_instruction
									 *給pc寄存器,但是undefined_instruction表示的是一個地址值那麼cpu直接跳轉到改地址執行
									 *此時還應該考慮.word的含義就是聲明一個值,只不過這個值是個內存地址而已
									 *_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

	.balignl 16,0xdeadbeef   /*此處用來進行字節對齊用的*/


/*
 *************************************************************************
 *
 * Startup Code (called from the ARM reset exception vector)
 *
 * do important init only if we don't start from memory!
 * relocate armboot to ram
 * setup stack
 * jump to second stage
 *
 *************************************************************************
 */

_TEXT_BASE:
	.word	TEXT_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

#ifdef 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

/*
 * the actual start code
 * arm920t:是CPU的型號
 */

start_code:
	/*
	 * set the cpu to SVC32 mode
	 *
	 * arm處理器7種工作模式:(除了usr其它爲特權模式)
	 * usr:正常程序執行模式 (非特權模式)
	 * fiq:用於高速數據傳輸或通道處理 (高優先級中斷)
	 * irq:通用中斷處理 (低優先級中斷)
	 * svc:supervisor 操作系統保護模式 (復位或軟中斷)
	 * abt:abort 數據訪問終止模式,當數據或者指令預取終止時進入該模式,
	 *      用於虛擬存儲器或存儲器保護 (數據存取異常)
	 * und:undefined 當未定義的指令執行時進入該模式,用於硬件協處理器
	 *      的軟件仿真 (執行未定義指令)
	 * sys:運行特權操作系統任務
	 */
	mrs	r0, cpsr    
	/* 程序狀態寄存器訪問指令:mrs,msr (m:move)
	 * cpsr(current program status register)
	 * 當前指令,將cpsr中的內容保存到r0寄存器中
	 */
	bic	r0, r0, #0x1f /*(bit clear)將r0與0x1f的反碼按位與運算保存到r0*/
	orr	r0, r0, #0xd3 /*將r0與0xd3按位或運算保存到r0*/
	/*以上兩條指令:禁止中斷,置爲thumb態,切換爲svc工作模式*/
	msr	cpsr, r0 /*將r0中的數據保存到cpsr寄存器中*/

	bl	coloured_LED_init /*bl:將下一條指令地址保存到lr寄存器,然後跳轉*/
	bl	red_LED_on

#if	defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
/*#if defined表示 宏 是否已經定義過*/
	/*
	 * relocate exception table ,設置異常向量表
	 */
	ldr	r0, =_start /*僞指令,將_start函數的地址保存到r0寄存器*/
	ldr	r1, =0x0    /*將常數賦給寄存器,將0保存到r1寄存器*/
	mov	r2, #16     /*數據傳送指令,將立即數16保存到r2寄存器*/
	/*立即數記作<immediate>, 8位常數記作immed_8, 4位的循環右移值記作rotate_imm,則有:
	 *		  <immediate> = immed_8   循環右移(2 * rotate_imm)
	 *例如:       0x3f0     = 0x3f      循環右移(2 * 0xe)
	 *arm下當立即數數值在0和0xFF範圍時,零immmed_8=<immediate>,rotate_imm=0
	 *其他情況下,彙編編譯器選擇使rotate_imm數值最小的
	 */
copyex:
	subs	r2, r2, #1 /*sub減法,r2=r2-1,s表示將結果更新到cpsr寄存器的條件標誌位(N Z C V)*/
	ldr	r3, [r0], #4   /*從內存中讀取數據到寄存器r3中,#4:將內存中的數據加載到r3後地址自加4*/
	str	r3, [r1], #4   /*將寄存器r3中的值保存到r1存儲的內存中,#4:r1 += 4*/
	bne	copyex         /*ne:不相等,當cpsr中z標誌位Z=0時進行跳轉*/
#endif

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
	/* turn off the watchdog */

# if defined(CONFIG_S3C2400)
#  define pWTCON	0x15300000
#  define INTMSK	0x14400008	/* Interupt-Controller base addresses */
#  define CLKDIVN	0x14800014	/* clock divisor register */
#else    /*s3c2410*/
#  define pWTCON	0x53000000   /*看門狗地址*/
#  define INTMSK	0x4A000008	/* Interupt-Controller base addresses 設置各種中斷是否啓用*/
#  define INTSUBMSK	0x4A00001C  /* 設置各種中斷是否啓用 */
#  define CLKDIVN	0x4C000014	/* clock divisor register */
# endif

	ldr	r0, =pWTCON
	mov	r1, #0x0
	str	r1, [r0]   /* 看門狗地址處設爲0,關閉看門狗 */

	/*
	 * mask all IRQs by setting all bits in the INTMR - default
	 */
	mov	r1, #0xffffffff
	ldr	r0, =INTMSK
	str	r1, [r0]
# if defined(CONFIG_S3C2410)
	ldr	r1, =0x3ff
	ldr	r0, =INTSUBMSK
	str	r1, [r0]
# endif

	/*此處花時間看看如何設置的,時鐘分頻比*/
	/* FCLK:HCLK:PCLK = 1:2:4 */
	/* default FCLK is 120 MHz ! */
	ldr	r0, =CLKDIVN
	mov	r1, #3
	str	r1, [r0]
#endif	/* CONFIG_S3C2400 || CONFIG_S3C2410 */

	/*
	 * we do sys-critical inits only at reboot,
	 * not when booting from ram!
	 */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
	bl	cpu_init_crit
#endif

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:				/* relocate U-Boot to RAM	    */
	adr	r0, _start		/* r0 <- current position of code   */
	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
	cmp	r0, r1			/* don't reloc during debug         */
	beq	stack_setup

	ldr	r2, _armboot_start
	ldr	r3, _bss_start
	sub	r2, r3, r2		/* r2 <- size of armboot            */
	add	r2, r0, r2		/* r2 <- source end address         */

copy_loop:
	/*ldm, stm批量內存訪問指令
	 * ldm:將r0地址中的內容複製到r3-r10寄存器中,r0自增加
	 * stm:將r3-r10寄存器中的值複製到r1地址中,r1自增加
	 * ia:先複製後增加,ib:先增加後複製,da:先複製後減操作,db:先減操作後複製
	 **/
	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
#endif	/* CONFIG_SKIP_RELOCATE_UBOOT */

	/* 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    */

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

	ldr	pc, _start_armboot

_start_armboot:	.word start_armboot


/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */


#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
	/*
	 * flush v4 I/D caches
	 */
	mov	r0, #0
	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */ /*協處理器指令,協處理器操作,待查資料*/
	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */

	/*
	 * disable MMU stuff and caches
	 */
	mrc	p15, 0, r0, c1, c0, 0
	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align
	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
	mcr	p15, 0, r0, c1, c0, 0

	/*
	 * before relocating, we have to setup RAM timing
	 * because memory timing is board-dependend, you will
	 * find a lowlevel_init.S in your board directory.
	 */
	mov	ip, lr

	bl	lowlevel_init /*當調用bl時r14(lr)保存r15(pc)的備份,當調用bl指令時lr寄存器內容會被修改所有有
						* 如下操作,還原lr內容*/

	mov	lr, ip
	mov	pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */

@
@ IRQ stack frame.
@
#define S_FRAME_SIZE	72

#define S_OLD_R0	68
#define S_PSR		64
#define S_PC		60
#define S_LR		56
#define S_SP		52

#define S_IP		48
#define S_FP		44
#define S_R10		40
#define S_R9		36
#define S_R8		32
#define S_R7		28
#define S_R6		24
#define S_R5		20
#define S_R4		16
#define S_R3		12
#define S_R2		8
#define S_R1		4
#define S_R0		0

#define MODE_SVC	0x13
#define I_BIT		0x80

/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 */

	.macro	bad_save_user_regs   /*.macro和.endm是一對,類似於C中的宏函數*/
	sub	sp, sp, #S_FRAME_SIZE
	stmia	sp, {r0 - r12}			@ Calling r0-r12
	ldr	r2, _armboot_start
	sub	r2, r2, #(CONFIG_STACKSIZE)
	sub	r2, r2, #(CONFIG_SYS_MALLOC_LEN)
	/* set base 2 words into abort stack */
	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
	ldmia	r2, {r2 - r3}			@ get pc, cpsr
	add	r0, sp, #S_FRAME_SIZE		@ restore sp_SVC

	add	r5, sp, #S_SP
	mov	r1, lr
	stmia	r5, {r0 - r3}			@ save sp_SVC, lr_SVC, pc, cpsr
	mov	r0, sp
	.endm

	.macro	irq_save_user_regs
	sub	sp, sp, #S_FRAME_SIZE
	stmia	sp, {r0 - r12}			@ Calling r0-r12
	add	r7, sp, #S_PC
	stmdb	r7, {sp, lr}^			@ Calling SP, LR
	str	lr, [r7, #0]			@ Save calling PC
	mrs	r6, spsr
	str	r6, [r7, #4]			@ Save CPSR
	str	r0, [r7, #8]			@ Save OLD_R0
	mov	r0, sp
	.endm

	.macro	irq_restore_user_regs
	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
	mov	r0, r0
	ldr	lr, [sp, #S_PC]			@ Get PC
	add	sp, sp, #S_FRAME_SIZE
	/* return & move spsr_svc into cpsr */
	subs	pc, lr, #4
	.endm

	.macro get_bad_stack
	ldr	r13, _armboot_start		@ setup our mode stack
	sub	r13, r13, #(CONFIG_STACKSIZE)
	sub	r13, r13, #(CONFIG_SYS_MALLOC_LEN)
	/* reserve a couple spots in abort stack */
	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8)

	str	lr, [r13]			@ save caller lr / spsr
	mrs	lr, spsr
	str	lr, [r13, #4]

	mov	r13, #MODE_SVC			@ prepare SVC-Mode
	@ msr	spsr_c, r13
	msr	spsr, r13
	mov	lr, pc
	movs	pc, lr
	.endm

	.macro get_irq_stack			@ setup IRQ stack
	ldr	sp, IRQ_STACK_START
	.endm

	.macro get_fiq_stack			@ setup FIQ stack
	ldr	sp, FIQ_STACK_START
	.endm

/*
 * exception handlers
 */
	.align  5
undefined_instruction:
	get_bad_stack
	bad_save_user_regs
	bl	do_undefined_instruction   /*在此處調用bl之後cpu重啓所以不會再跳回了,以下中斷都是進行reset*/

	.align	5
software_interrupt:
	get_bad_stack
	bad_save_user_regs
	bl	do_software_interrupt

	.align	5
prefetch_abort:
	get_bad_stack
	bad_save_user_regs
	bl	do_prefetch_abort

	.align	5
data_abort:
	get_bad_stack
	bad_save_user_regs
	bl	do_data_abort

	.align	5
not_used:
	get_bad_stack
	bad_save_user_regs
	bl	do_not_used

#ifdef CONFIG_USE_IRQ

	.align	5
irq:
	get_irq_stack
	irq_save_user_regs
	bl	do_irq
	irq_restore_user_regs

	.align	5
fiq:
	get_fiq_stack
	/* someone ought to write a more effiction fiq_save_user_regs */
	irq_save_user_regs
	bl	do_fiq
	irq_restore_user_regs

#else

	.align	5
irq:
	get_bad_stack
	bad_save_user_regs
	bl	do_irq

	.align	5
fiq:
	get_bad_stack
	bad_save_user_regs
	bl	do_fiq

#endif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章