📄 boot.s
字号:
MSR spsr_c, r2
MOV sp, r7 ; Initial SVC stack pointer...
SUB r7, r7, #SVCStackSize
BIC r7, r7, #3 ; Must be word-aligned
MOV r10, r7 ; Bottom of SVC stack
; Need to protect stack pointer from the SWI. When switching
; modes Semihosted also switches stack so we end up with the user
; stack. Semihosted SWIs promise to protect r1, r2 and r3, so copy
; TopOfMemory to r2 and sp to r3.
MOV r2, r0 ; Protect TopOfMemory
MOV r3, sp ; Protect SVC stack
; Setup User/System mode stacks.
ORR r5, r4, #User32Mode
MSR cpsr_c, r5
MOV sp, r7 ; Initial User stack pointer...
SUB r7, r7, #UserStackSize
BIC r7, r7, #3 ; Must be word-aligned
MOV r10, r7 ; Bottom of stacks
; Save the top of free RAM = TopOfMemory - all stacks
MOV r1, r7 ; Return top of free RAM in r1
; Switch back to supervisor & recover stack & TopOfMemory.
MOV r0, #angel_SWIreason_EnterSVC
SWI SWI_Angel ; Returns EnterUSR routine in r0
MOV sp, r3 ; Restore SVC stack
MOV r0, r2 ; Restore TopOfMemory
MOV r11, #0 ; No previous frame, so fp=0
MOV pc, r6 ; Branch back to boot-up code
INCLUDE linkdata.s ; Any compiler dependencies are in here
; uHALir_InitBSSMemory
;
; Routine called from boot-up to initialise all memory used by 'C' and any
; predefined assembler data areas. Use of indirect links to real linker
; variables allows any memory map to be used & hides linker specifics.
; This is a real subroutine, called after stack initialisation.
uHALir_InitBSSMemory
STMFD sp!, {r4-r8, r14}
LDR r4, uHAL_TopOfROM ; Copy predefined variables from here..
LDR r5, uHAL_StartOfBSS ; ..to here
LDR r6, uHAL_ZeroBSS ; 'C' BSS starts here
CMP r4, r5 ; Make sure there are some..
BEQ %8
7
CMP r5, r6 ; Check if done..
LDRCC r7, [r4], #4 ; if not, get word and store to RAM
STRCC r7, [r5], #4
BCC %7
8
LDR r4, uHAL_EndOfBSS ; Top of zero init memory
; FIXME! vvvv! How do I reserve sequential data areas which are not zero-init?
LDR r7, uHAL_NonZeroBSS ; Start of MMU tables
LDR r8, uHAL_EndOfNonZ ; End of MMU tables
; FIXME! ^^^^!
MOV r5, #0
9
; FIXME! vvvv! See above comment.
; Don't zero NonZero area!
CMP r6, r7 ; > uHAL_NonZeroBSS
CMPCS r6, r8 ; & < uHAL_EndOfNonZ ?
MOVCC r6, r8 ; Yes, just skip completely
; FIXME! ^^^^!
CMP r6, r4 ; Check if done..
STRCC r5, [r6], #4 ; if not, clear another word
BCC %9
; Save the Base of Free RAM.
; NOTE: When running semihosted, this overwrites the value
; returned by the host because the uHAL application is
; running _in_ that memory space.
LDR r5, =uHALiv_BaseOfMemory
BIC r4, r4, #3 ; Make it word-aligned
ADD r4, r4, #8 ; Next accessable word + 1
STR r4, [r5]
LDMFD sp!, {r4-r8, pc} ; restore registers and return
; Routines to return addresses of start & end of free & end of installed RAM.
uHALr_StartOfRam
LDR r0, uHAL_EndOfBSS ; 1st available uninitialised RAM
MOV pc, r14 ; Return
uHALr_EndOfRam
STMFD sp!, {r4, r14}
LDR r4, =uHALiv_TopOfMemory
LDR r0, [r4]
LDMFD sp!, {r4, pc} ; restore registers and return
uHALr_EndOfFreeRam
STMFD sp!, {r4, r14}
LDR r4, =uHALiv_TopOfHeap
LDR r0, [r4]
LDMFD sp!, {r4, pc} ; restore registers and return
; STacK OVerFlow handling routine - minimum required by ARM Linker without
; defining no stack checking.
; void __rt_stkovf_split_big(void);
|__rt_stkovf_split_big|
MOV pc, r14 ; just return
; STacK OVerFlow handling routine - minimum required by ARM Linker without
; defining no stack checking.
; void __rt_stkovf_split_small(void);
|__rt_stkovf_split_small|
MOV pc, r14 ; just return
|_main_arg|
MOV pc, r14 ; just return
; SWI handler - currently only handles switch to SVC mode.
uHALr_TrapSWI
; SWI switches to SVC mode, with no IRQs (ARM Architecture Reference)
STMFD sp!, {r0-r1}
LDR r0, [r14, #-4] ; Read SWI instruction
BIC r0, r0, #0xff000000 ; extract the SWI number
LDR r1, =SWI_Angel
CMP r0, r1
LDMFD sp!, {r0-r1} ; restore register
BNE uHALil_ExitSWI ; Unknown SWI
CMP r0, #angel_SWIreason_EnterSVC
BEQ uHALir_SWIEnterOS ; return in SVC mode
CMP r0, #angel_SWI_SYS_HEAPINFO
BNE uHALil_ExitSWI ; Unknown SWI
; Load area pointed to by r1 with heap and stack info
STMFD sp!, {r0-r4}
LDR r0, [r1] ; Pointer to variables
LDR r4, =uHALiv_TopOfHeap
LDR r3, [r4], #4 ; top of free RAM
LDR r2, [r4], #8 ; base of free RAM
STR r2, [r0], #4
STR r3, [r0], #4
LDR r2, [r4], #4 ; base of stack
LDR r3, [r4]
STR r2, [r0], #4
STR r3, [r0]
LDMFD sp!, {r0-r4} ; restore register
uHALil_ExitSWI
MOV r0, #0 ; Pretend it was all okay
MOVS pc, r14 ; just ignore SWI
uHALir_SWIEnterOS
MOV pc, r14 ; return without restoring mode!
; Dummy IRQ handler - gets overwritten
uHALir_IRQProcess
STMFD sp!, {r4}
MRS r4, cpsr ; Re-enable interrupt
BIC r4, r4, #NoIRQ
MSR cpsr_c, r4
LDMFD sp!, {r4}
SUBS pc, r14, #4 ; return from IRQ
; Try and capture some sensible data after undefined instruction.
uHALir_UndefProcess
MOV r0, sp
; Hacked from vector copy. Should be done properly to a system
; defined address.
MOV r0, #0
LDR r1, =uHALip_FirstVector ; Copy from here..
LDR r2, =uHALip_LastVector ; ..to here
MOV r6, #0x00010000 ; Debug - make a copy of originals
MOV r5, r14 ; Old return address (if any)
STR r5, [r6], #4
MRS r5, cpsr ; CPSR
STR r5, [r6], #4
MRC p15, 0, r5, c5, c0, 0 ; Coproc 5 - 1 byte of status
STR r5, [r6], #4
MRC p15, 0, r5, c6, c0, 0 ; Coproc 6 - Fault address
STR r5, [r6],#4
MOV r5, sp
STR r4, [r6],#4 ; Old Stack
STR r5, [r6],#4 ; New Stack
_undefLoop
LDR r4, [r5], #-4 ; Look at stack
STR r4, [r6], #4
CMP r1,r2 ; Repeat until all done
BLO _undefLoop
; Okay, we've done enough, add further specific initialisation here
BL uHALir_DebugUndefinedInst
_Undef4ever
B _Undef4ever ; Try and restart..
;
; The 2.50 C compiler makes references to _memcpy,
; we don't have this routine, therefore will map this
; to uHALr_memcpy.
;
_memcpy
B uHALr_memcpy
IF :DEF: DEBUG
IMPORT sputchar
EXPORT PostMortem
EXPORT spitword
;===========================================================================
; Ths routine will put a word value via sputchar
;===========================================================================
PutWord
mov r4, r14
mov r5, r0
mov r0, #0x20 ; ' '
bl sputchar
PutWord2
mov r3, #28
01 mov r0, r5, LSR r3
ands r0, r0, #0xf
bne %f02 ; the first non-zero
; subs r3, r3, #4
; bne %b01 ; all but the last digit
; mov r0, r5 ; Get the only digit
02 cmp r0, #10
addlo r0, r0, #0x30 ; 0 - 9
addhs r0, r0, #0x61 - 10 ; a - f
bl sputchar
subs r3, r3, #4
mov r0, r5, LSR r3
and r0, r0, #0xf
bpl %b02
mov pc, r4
; 'C' callable version of PutWord
spitword
STMFD sp!, {r3-r5, r14}
BL PutWord
LDMFD sp!, {r3-r5, pc}
spitstr
MOV r4, r14
MOV r5, r0
3
LDRB r0, [r5], #1
CMP r0, #0
MOVEQ pc, r4
BL sputchar
B %B03
;===========================================================================
; It's dead Jim, dead. Who, what where, when, how?
;
; 'Routine' to print out r0-r12, r14, spsr, fsr & far, ttb, tlb & contents
; Called only when debug system crashes (doesn't return). Uses stack so
; memory must be working and sputchar() - serial-only version of putchar().
; Make sure 'DEBUG' is defined for 'C' too.
;===========================================================================
PostMortem
STMFD sp!, {r9-r12, r14} ; X marks the spot
MOV r9, r0
MOV r10, r3
MOV r11, r4
MOV r12, r5
LDR r0, =Mort0 ; Tell user what kind of error
BL spitstr
MRS r0, cpsr
BL PutWord
LDR r0, =Mort1
BL spitstr
MOV r0, r9
BL PutWord ; r0
MOV r0, r1
BL PutWord ; r1
MOV r0, r2
BL PutWord ; r2
MOV r0, r10
BL PutWord ; r3
MOV r0, r11
BL PutWord ; r4
MOV r0, r12
BL PutWord ; r5
MOV r0, r6
BL PutWord ; r6
LDR r0, =Mort2
BL spitstr
MOV r0, r7
BL PutWord ; r7
MOV r0, r8
BL PutWord ; r8
LDMFD sp!, {r9-r12, r14} ; X marks the spot
MOV r8, r14
MOV r0, r9
BL PutWord ; r9
MOV r0, r10
BL PutWord ; r10
MOV r0, r11
BL PutWord ; r11
MOV r0, r12
BL PutWord ; r12
MOV r0, r13
STMFD r0!, {r13, r14}^ ; Assembler warns about this!
LDMFD r0!, {r6, r7}
MOV r0, r6
BL PutWord ; r13
LDR r0, =Mort3
BL spitstr
MOV r0, r7
BL PutWord ; r14
MOV r0, r8
BL PutWord ; pc
; Mode before exception
LDR r0, =Mort4
BL spitstr
MRS r0, spsr
BL PutWord
; Read Fault Status register and Fault Address register
LDR r0, =Mort5
BL spitstr
RDMMU_FaultStatus r0
BL PutWord
LDR r0, =Mort6
BL spitstr
RDMMU_FaultAddress r0
MOV r8, r0, LSR #20 ; Strip irrelevent bits
BL PutWord
; Read Translation Table Base reg.
LDR r0, =Mort7
BL spitstr
RDMMU_TTBase r0
MOV r9, r0, LSR #14 ; Strip irrelevent bits
BL PutWord
; Now rebuild address of page table entry
MOV r9, r9, LSL #14
ORR r9, r9, r8, LSL #2
LDR r0, =Mort8
BL spitstr
MOV r0, r9
BL PutWord
LDR r0, =':'
BL sputchar
LDR r0, [r9]
BL PutWord
LDR r0, ='\n'
BL sputchar ; Newline
LDR r0, ='\n'
BL sputchar ; Newline
; Try again?
B uHALir_ResetGo
Mort0 DCB "\ncpsr\t", 0
Mort1 DCB "\nr0-r6\t", 0
Mort2 DCB "\nr7-r13\t", 0
Mort3 DCB "\nr14, pc\t", 0
Mort4 DCB "\nspsr\t", 0
Mort5 DCB "\nfsr", 0
Mort6 DCB "\tfar", 0
Mort7 DCB "\nttb\t", 0
Mort8 DCB "\ttlb", 0
ENDIF
IF :DEF: USE_C_LIBRARY
IF :DEF: uHAL_HEAP
LTORG
AREA CONSTANTS, DATA, READONLY
EXPORT __heap_base
EXPORT __heap_limit
EXPORT __stack_base
EXPORT __stack_limit
__heap_base DCD (uHAL_HEAP_BASE)
__heap_limit DCD (__heap_base + uHAL_HEAP_SIZE)
__stack_base DCD (uHAL_STACK_SIZE)
__stack_limit DCD (__stack_base - uHAL_STACK_SIZE)
ENDIF
ENDIF
LTORG
AREA uHAL_BootRam, DATA
uHALiv_TopOfHeap % 4 ; Top of free RAM (below stacks)
uHALiv_BaseOfMemory % 4 ; Semihosted Base of Heap
uHALiv_TopOfMemory % 4 ; Top of installed RAM + 1
uHALiv_BaseOfStack % 4 ; Semihosted Base of Stack
uHALiv_TopOfStack % 4 ; Semihosted Top of Stack
uHALiv_MemorySize % 4 ; Memory size in bytes
uHALv_BootSwitcherStatus % 4 ; Boot Switcher Status
exit
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -