⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 boot.s

📁 HAL硬件抽象层源码
💻 S
📖 第 1 页 / 共 2 页
字号:
;/* ***************************************************************************
; Copyright ? Intel Corporation, March 18th 1998.  All rights reserved.
; Copyright ? ARM Limited 1998.  All rights reserved.
; Copyright ? Hynix Semiconductor Limited 2002.  All rights reserved.
;***************************************************************************/


	INCLUDE bits.s
	INCLUDE sizes.s
	INCLUDE platform.s
	INCLUDE except_h.s
	GET	target.s			; Target specific macros

	IMPORT	ResetStart		;leb1207
	IMPORT	main				; Start of user program
 IF :DEF: USE_C_LIBRARY
	IMPORT	__entry
 ENDIF

	IMPORT	uHALir_DebugUndefinedInst		; in irq.c
	IMPORT	uHALir_DisableInt			; in irqlib.s
	IMPORT	uHALir_PlatformInit		; in platform.c
	IMPORT	uHALir_InitTargetMem		; in driver.s
	
 IF :LNOT: :DEF: USE_C_LIBRARY
	EXPORT	|__main|			; Program Entry Point
	EXPORT	|_main|				; Program Entry Point
	EXPORT	|_main_arg|			; Program arguments
	EXPORT	|__rt_exit|			; ARM Linker needs these..
	EXPORT	__rt_stkovf_split_small
	EXPORT	__rt_stkovf_split_big		; ..but they do nothing.
 ENDIF

	EXPORT	_memcpy				; Required by 2.50 SDT ARMCC 
	IMPORT	uHALr_memcpy			; Required by _memcpy

	EXPORT	uHALr_TrapSWI			; SWI exception handler
	EXPORT	uHALr_StartOfRam		; Returns 1st free RAM address
	EXPORT	uHALr_EndOfFreeRam		; Returns last free RAM address
	EXPORT	uHALr_EndOfRam			; Returns top of available RAM
	EXPORT	uHALir_InitBSSMemory		; Init 'C' variable space
	EXPORT	uHALiv_TopOfHeap		; Variables holding above values
	EXPORT	uHALiv_TopOfMemory
	EXPORT	uHALiv_MemorySize		; Memory Size
	EXPORT	uHALv_BootSwitcherStatus	; Boot Switcher Status
	EXPORT	uHALip_FirstVector

	AREA	SelfBoot, CODE, READONLY

	; Start of executable code - label must follow ENTRY for scripts
	; to automatically convert between different assemblers.
 IF :LNOT: :DEF: USE_C_LIBRARY
	ENTRY
 ENDIF
|__main| 
|_main| 

	b	uHALip_FirstVector			;leb1207-reserved for Remapped SRAM
		
	%	0x1000-4				;leb1207-reserved for Remapped SRAM



; Vectors are copied to RAM at zero. If memory at 0 is ROM, this code will
; have no effect (provided the hardware handles writes to ROM gracefully)!
; uHALip_LastVector should be after _FIQVector _and_ the FIQ interrupt code
; which may follow to avoid an unnecessary branch. If RAM at 0, init. after
; switching FlashROM shadow away.

; First 8 addresses are interrupt vectors.
;
;	Addr.   Exception Type		Mode    Priority
;	0x00    Reset			svc	1	(1 = High)
;	0x04    Undefined instruction   undef   6	(6 = Low)
;	0x08    Software Interrupt SWI  svc	6
;	0x0C    Prefetch Abort		abort   5
;	0x10    Data Abort		abort   2
;	0x14    Reserved		NA	N/A
;	0x18    Interrupt IRQ		irq	4
;	0x1C    Fast Interrupt FIQ	fiq	3
;

	; NOTE: Can't use simple branches which are relative and would
	;	be wrong when moved!
uHALip_FirstVector
	; If the uHAL application is executing from a different address
	; to the address it was built for (such as a system where 
	; memory management hasn't been turned on yet), the first
	; instruction may _have_ to be different. So use a macro.

	STEP_ONE	; You find a girl to love...

	LDR	PC, uHALip_UndefVector
	LDR	PC, uHALip_SWIVector
	LDR	PC, uHALip_PreAbtVector
	LDR	PC, uHALip_DataAbtVector
	LDR	PC, uHALip_ReservdVector
	LDR	PC, uHALip_IRQVector
	LDR	PC, uHALip_FIQVector	; Routine for FIQs - normally code is

					; placed here for max. speed, but
					; a branch would work just as well.

; Put after FIQ code if inline (Then FIQ code will be in fast ram too).

	; If this were a real embedded application, all these vectors
	; would have to be properly defined.

uHALip_ResetStart	DCD	uHALir_ResetGo	; Branch on Reset & go
uHALip_UndefVector	DCD	uHALir_UndefProcess ; Reset on unknown instruction
uHALip_SWIVector	DCD	uHALr_TrapSWI	; Routine to handle SWI
uHALip_PreAbtVector	DCD	uHALir_ResetStop	; Not handled in this example..
uHALip_DataAbtVector	DCD	uHALir_ResetStop
uHALip_ReservdVector	DCD	uHALir_ResetStop
uHALip_IRQVector	DCD	uHALir_IRQProcess	; Routine for IRQs
uHALip_FIQVector	DCD	uHALir_ResetStop 	; Routine for FIQs

uHALip_LastVector		; EVERYTHING before this point is copied to RAM

	; Skip over vector table & FIQ code (if any) to HERE
uHALir_ResetStop

	; If DEBUG is not defined, ResetStop and ResetGo are the same.

 IF :DEF: DEBUG

	; Post Mortem assumes memory system (uses stacks) is working and
	; OS_COMPORT has been initialised (see below).
	B	PostMortem
	NOP
	NOP
	NOP

 ENDIF

uHALir_ResetGo


 IF :DEF: SEMIHOSTED
	MOV	r12, #0		; No Boot Switcher, therefore it can not fail.
 ELSE	
	IMPORT	uHALir_prePlatformInit
	;leb1207 booting memory remap
	bl	uHALir_prePlatformInit

		
	; Run the boot switcher if it exists at link time.
	;
	; THIS ROUTINE MAY DESTORY ALL REGISTERS
	;
	; r0 will contain a return status (zero is success)

	IMPORT	boot_switcher, WEAK

	MOV	r0, #0		; Assume success.
	LDR	r4, =boot_switcher
	CMP	r4, #0
	BLNE	boot_switcher
	MOV	r12, r0		; Save status for later.
 ENDIF

	; Switch to high memory (and handle any other instant start needs)
	GOTO_ROM	r0, r1

	; When cold-booting, processor interrupts are disabled, but this is
	; not guaranteed when running under a debugger.

	; External interrupt controller mode is undefined on reset. By
	; clearing all the flags, we make sure the system is under control.
	; NOTE: Hardware/Debugger implementation dependant!

 IF :DEF: SEMIHOSTED

	; SEMIHOSTED - get into SVC mode
	; As this change is not balanced, only switch if USR mode
	MRS	r4, CPSR
	AND	r4, r4, #ModeMask
	CMP	r4, #User32Mode

	MOV	r0, #angel_SWIreason_EnterSVC
	SWINE	SWI_Angel		; Returns EnterUSR routine in r0

 ENDIF

	; Put interrupts into a known state - off (if possible)
	INIT_INTS	r0, r1, r8

	; If doing some sort of memory initialisation, it is obvious there
	; is no stack!

	; And the default top of memory is...
	LDR	r0, =uHAL_MEMORY_SIZE 

	; NOTE: RAM may need to be kick-started, so this 'routine' should
	; always be called!

	BL	uHALir_InitTargetMem	; Memory size returns in r0

	LDR	r4, =uHALiv_MemorySize
	STR	r0, [r4]		; Save memory size

	;
	; Now that memory has been initialised we can save the boot
	; switcher status.
	;
	; Unfortunately uHALir_InitTargetMem is not guaranteed to preserve
	; registers on all platforms.  Because of this currently the status
	; is zeroed before it is saved on all platforms except Integrator.
	; 

	LDR	r4, =uHALv_BootSwitcherStatus
	STR	r12, [r4]		; Save boot switcher status

	; >> Non-linear Memory management needs to happen here
	;    - before stacks are set up. Else, do it after stack/vector init.


	; uHAL is not currently multiprocessor aware. If the platform
	; supports multiple CPUs, platform-specific initialisation
	; will be required.
	CHECK_PRIMARY_CPU

	; Under a debugger, IRQ vector is only changed when IRQ is installed.
	; But standalone, all vectors are installed now.
 IF :LNOT: :DEF: SEMIHOSTED

	; Copy vectors (and any in-line FIQ code) to RAM at zero.
	; NOTE: Can't do this before memory is initialised (AND it will break
	;	debuggers).
	MOV	r4, #0
	LDR	r5, =uHALip_FirstVector	; Copy from here..
	LDR	r6, =uHALip_LastVector	; ..to here
3
	LDR	r7, [r5], #4		; get word and store to RAM	 
	STR	r7, [r4], #4
	CMP	r5, r6			; Repeat until all done
	BLO	%3

 ENDIF

	; target.s knows how debugging is done on each board
	MOV	r4, #5
	DO_DEBUG	r4, r5, r6

 IF :DEF: SEMIHOSTED

	; Get the heap info from Semihosted. NOTE: requires a ptr to a ptr to
	; 4 bytes of RAM
	LDR	r0, =angel_SWI_SYS_HEAPINFO

	; Ptr to ptr, not used as heap until after InitStacks
	LDR	r1, =uHALiv_TopOfHeap
	LDR	r2, =uHALiv_BaseOfMemory; Heap info actually stored here
	STR	r2, [r1]		; Semihosted promises to preserve r2
	SWI	SWI_Angel
	LDR	r0, [r2, #4]		; Read top of Semihosted heap

 ENDIF

	; Now set up the stack pointers for all the different modes. 
	BL	uHALir_InitStacks

	STMFD	sp!, {r0-r1}		; Protect TopOfMemory & TopOfHeap

 IF :LNOT: :DEF: SEMIHOSTED

 IF uHAL_PCI <> 0
	; Configure PCI memory space (even if not connected to PCI)
	LDR	r7, =PCI_DRAMSIZE
	SETUP_PCI	r4, r5, r6, r7
 ENDIF

 ENDIF

	;
	; Save contents of uHALv_BootSwitcherStatus & uHALiv_MemorySize
	;
	LDR	r4, =uHALv_BootSwitcherStatus
	LDR	r0, [r4]
	LDR	r4, =uHALiv_MemorySize
	LDR	r1, [r4]
	STMFD	sp!, {r0-r1}
	
	;
	; Initialise memory required by 'C'.
	;
	BL	uHALir_InitBSSMemory
	
	;
	; Restore contents of uHALv_BootSwitcherStatus & uHALiv_MemorySize
	;
	LDMFD	sp!, {r0-r1}
	LDR	r4, =uHALv_BootSwitcherStatus
	STR	r0, [r4]
	LDR	r4, =uHALiv_MemorySize
	STR	r1, [r4]

	; Now all memory is cleared, save TopOfMemory
	LDMFD	sp!, {r0-r1}
	SUB	r0, r0, #4		; Last accessable word
	BIC	r0, r0, #3		; Make it word-aligned
	LDR	r4, =uHALiv_TopOfMemory	; Top of installed memory
	STR	r0, [r4]
	LDR	r4, =uHALiv_TopOfHeap
	SUB	r1, r1, #4		; Last accessable word
	BIC	r1, r1, #3		; Make it word-aligned
	STR	r1, [r4]		; Here's the top of free RAM

 IF :LNOT: :DEF: SEMIHOSTED
	; These variables are used if the application wants to
	; define a stack of its own. They overlap with the heap,
	; but should start at opposite ends.

	LDR	r4, =uHALiv_TopOfStack
	STR	r1, [r4]		; Put at top of heap space
	LDR	r4, =uHALiv_BaseOfStack
	SUB	r1, r1, #SZ_64K
	STR	r1, [r4]
 ENDIF

	; Do the C based platform specific platform initialization
	BL	uHALir_PlatformInit	; Everything required to init HW
									
 IF :DEF: USE_C_LIBRARY
	BL	__entry 
 ENDIF						

	; ARM Procedure Call Standard nomenclature
	MOV	r0, #0			; set argc to 0
	MOV	r1, #0			; and argv to NUL
	BL	main			; Call main, falling through to
					; exit on return.

 IF :LNOT: :DEF: USE_C_LIBRARY
|__rt_exit|				; exit
;
; void __rt_exit(int code);
; Terminate execution, optionally setting return code (ignored here).
; MUST NOT RETURN IN STAND-ALONE SYSTEM.

; Stop interrupts.
	BL	uHALir_DisableInt	

   IF :DEF: SEMIHOSTED

	LDR	r0, =angel_SWIreason_ReportException
	LDR	r1, =ADP_Stopped_ApplicationExit
	SWI	SWI_Angel

   ENDIF
 ENDIF
0
	; Might be nice to inform world of termination by putting some
	; unique status operation (such as a flashing LED inside this loop).
	B	%0			; Loop forever


;===========================================================================
;	uHALir_InitStacks
;
; 'Routine' called from boot-up to set all stacks.
; Although we have no stack yet, r14 contains return address. r0 contains
; top of memory (don't corrupt!) and all stacks are relative to this value.
;
; FIQ stack isn't set in this example.
;
uHALir_InitStacks
	MOV	r6, r14			; !!! Protect the return address !!!

	; Any modes which are only used to cause a reset can all work in
	; the same stack space, since only one can occur at any one time.
	MRS	r4, cpsr
	ORR	r4, r4, #NoIRQ		; No IRQs & blank mode
	ORR	r4, r4, #NoFIQ		; Or FIQs
	BIC	r4, r4, #ModeMask

	; Undefined & Abort modes share same space.
	ORR	r5, r4, #Undef32Mode
	MOV	r2, #User32Mode
	MSR	cpsr_c, r5
	MSR	spsr_c, r2
	BIC	r7, r0, #3		; Must be word-aligned
	MOV	sp, r7			; Initial Undefined stack pointer...
	ORR	r5, r4, #Abort32Mode
	MSR	cpsr_c, r5
	MSR	spsr_c, r2

	; If you want seperate stacks for abort & Undefined, uncomment these:
;	SUB	r7, r7, #AbortStackSize
;	BIC	r7, r7, #3		; Must be word-aligned

	MOV	sp, r7			; Initial Abort stack pointer...
	SUB	r7, r7, #UndefStackSize
	BIC	r7, r7, #3		; Must be word-aligned

	; Setup FIQ stacks.
	; NOTE: This example doesn't alter anything to do with FIQs. If you
	; want to use FIQs, uncomment this code. FIQs are left disabled.
;	ORR	r5, r4, #(NoFIQ | FIQ32Mode)
;	MSR	cpsr_c, r5
;	MSR	spsr_c, r2
;	MOV	sp, r7			; Initial FIQ stack pointer...
;	SUB	r7, r7, #FIQStackSize
;	BIC	r7, r7, #3		; Must be word-aligned

	; Setup IRQ stacks.
	ORR	r5, r4, #IRQ32Mode
	MSR	cpsr_c, r5
	MSR	spsr_c, r2
	MOV	sp, r7			; Initial IRQ stack pointer...
	SUB	r7, r7, #IRQStackSize
	BIC	r7, r7, #3		; Must be word-aligned

	; Setup Supervisor stacks.
	ORR	r5, r4, #SVC32Mode
	MSR	cpsr_c, r5

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -