📄 boot.s
字号:
;/* ***************************************************************************
; 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 + -