📄 startrom.s
字号:
; r8 now contains offset from code base to current base (could be 0) ; r1 contains current base ; r0 contains linked location of code LDR r3, =|Image$$RO$$Limit| TEQ r8, #0 BEQ NoCodeCopy ; copy code ; r0 is dest, r0 + r8 is source, r3 is limit01 LDR r1, [r0, r8] STR r1, [r0], #+4 CMP r0, r3 BLO %B01NoCodeCopy ADD r1, r3, r8 ; source address = RO$$Limit + offset LDR r2,=|Image$$RW$$Base| ; destination address LDR r3,=|Image$$ZI$$Base| ; limit ; ; For ROM based applications we must perform the work of ; initialising the RW initialised and BSS data here. For ; non-ROM applications the mapping (and initialisation) of RW ; data is performed by the AIF header, and such applications ; would not be using the "startrom.s" code at all. ; ; Copy the data to the final RAM address: 01 LDR r0,[r1],#4 ; get from ROM STR r0,[r2],#4 ; store to RAM CMP r2,r3 ; check for end condition BLO %BT01 ; if (r2 < r3) we have more to transfer ; ; Now initialise the BSS area. ; LDR r3,=|Image$$RW$$Limit| MOV r0,#002 STR r0,[r2],#4 CMP r2,r3 BLO %BT02 ; NOTE: We could optimise the loop above to use more ; registers. This would improve the initialisation latency of ; ROM systems. ; r1 points to top of image, save this to r7 for now MOV r7, r1 ; Now we have set everything up, we can jump to (possibly) ; re-located code and continue running from there. ; The following instruction forces the PC to be loaded from ; a literal pool. The value loaded is the address of the ; gotoRelocated symbol, suitably relocated. This means when ; we "armlink" the object created we can specify the image ; address, and the code will then be correct. LDR pc, =gotoRelocatedgotoRelocated ; We have just initialised the RAM, so we can now start using ; Angel variables: ; The value in "r7" is the true ROM end address. This can be ; used by ROM systems that have appended data after that ; constructed by the linker. LDR r0,=angel_ROMEnd ; variable to hold true ROM end address STR r7,[r0,#0x00] ; ; The MMU identification word is held in r6 from above. A ; value of zero is used when no MMU is present. LDR r0,=angel_MMUtype STR r6,[r0,#0x00] ; ; We can support the following three system configurations: ; ; 1) ROM at zero, (dataseg, bss) elsewhere ; ; 2) ROM elsewhere, (dataseg, bss) at zero ; ; 3) Vectors at zero, (ROM, dataseg, bss) elsewhere ; ; In the first two configurations, the Vectors will automatically ; be at zero (in (1) because the linker was told to put them there, ; in (2) because they are linked at the start of the "dataseg"); ; in the third configuration we need to copy them from their ; current position to their proper home at zero. ; LDR r0, =|__VectorStart| CMP r0, #0 BEQ VectorsInPlace ; ; we really do need to move the vectors ; LDR r3, =|__Vectors$$Limit| SUBS r3, r3, r0 IF :DEF: ASSERT_ENABLED :LAND: ASSERT_ENABLED <> 0MissingVectors BNE VectorsOK FatalError "Missing Vectors\n" VectorsOK ENDIF MOV r1, #0VectorCopy LDR r2, [r0], #4 STR r2, [r1], #4 SUBS r3, r3, #4 BNE VectorCopy ; ; We now have the processor vectors, and the indirection table ; at address zero. Also, depending on the target, we will have ; mapped RAM to zero. ; ; Initialise the default stack pointers for the various ARM ; processor modes. We do this by switching into all the modes ; (ensuring interrupts stay disabled), setting up the default ; stack top addresses. These addresses are hard-wired into the ; target workspace. Normally an O/S would perform some more ; memory management, and have the concept of dynamic exception ; stacks depending on the task/thread active. However for ; Angel we just have some pre-allocated stacks at fixed ; addresses in the work-space. ; IMPORT Angel_StackBaseVectorsInPlace LDR r5, =Angel_StackBase LDR r5, [r5] ADD sp, r5, #Angel_SVCStackOffset ; SVC mode stack ADD sl, r5, #Angel_SVCStackLimitOffset ; No APCS_STACKGUARD space ; Define a default APCS-3 register state to ensure we can call ; suitably conforming functions: MOV fp,#0x00000000 ; no frame-pointer chain ; We now call the memory sizer if there is one, and adjust ; things if the memory size is not the default. IMPORT angel_FindTopOfMemory, WEAK IMPORT angel_RelocateWRTTopOfMemory, WEAK LDR r1, =angel_FindTopOfMemory CMP r1, #0 BEQ MemorySizeAlreadyCorrect BL angel_FindTopOfMemory BL angel_RelocateWRTTopOfMemory ; If we have just done relocations then go back and set up the SVC ; stack again (and repeat this). CMP r0, #0 BNE VectorsInPlace ; Now everything is all ok, and set up correctly MemorySizeAlreadyCorrect IMPORT angel_InitialiseOneOff ; serialiser initialisation IMPORT angelOS_InitialiseApplication IMPORT angelOS_CPUWrite ; We have to set up the other privileged mode regs right now. MOV r0, #(InterruptMask :OR: IRQmode) MSR cpsr_cf,r0 ADD sp, r5, #Angel_IRQStackOffset ; IRQ mode stack MOV r0, #(InterruptMask :OR: FIQmode) MSR cpsr_cf,r0 ADD sp, r5, #Angel_FIQStackOffset ; FIQ mode stack MOV r0, #(InterruptMask :OR: UNDmode) MSR cpsr_cf,r0 ADD sp, r5, #Angel_UNDStackOffset ; Undefined instruction mode stack MOV r0, #(InterruptMask :OR: ABTmode) MSR cpsr_cf,r0 ADD sp, r5, #Angel_ABTStackOffset ; Abort mode stack MOV r0, #(InterruptMask :OR: SVCmode) MSR cpsr_cf,r0 ; We are now back in SVC mode with IRQs and FIQs disabled. INITMMU r0,r1,r2,r3,r5,r6 ; perform MMU initialisation if required ; INITTIMER r0,r1 ; perform any special timer initialisation ; ; For systems that cannot tell the type of reset that ; occurred, the STARTUPCODE macro will have set "r4" to ; pretend that it is a PowerOnReset. LDR r0,=angel_StartupStatus STR r4,[r0,#0x00] ; store PowerOnReset status IF DEBUG > 0 LDR r0, =angel_DebugTaskArea LDR r1, =DEBUG_BASE STR r1, [r0] ; DebugTaskBase is for info only: you cannot run-time change it! LDR r0, =angel_DebugTaskBase STR r1, [r0] ENDIF IF (MINIMAL_ANGEL = 0) ; initialise the logterm debugging module, if present. ;; Note: it probably doesn't make sense in minimal angel anyway; ;; and certainly would need small changes to work there... IF DEBUG = 1 :LAND: LOGTERM_DEBUGGING = 1 IMPORT |logterm_Initialise|,WEAK ; debug initialisation BL logterm_Initialise ENDIF ;; Initialise the serialiser BL angel_InitialiseOneOff ; init serialiser world ENDIF ; MINIMAL_ANGEL = 0 IF (MINIMAL_ANGEL = 0) ; Now we have to set up the application registers so that ; the world is ready just for the user to type 'go' from armsd. ; angelOS_InitialiseApplication sets up some stuff ... LDR r0, =ADP_HandleUnknown MOV r1, r0 MRS r1, cpsr BL angelOS_InitialiseApplication ENDIF ; (MINIMAL_ANGEL = 0) ; XXX ; ; We *should* restore sp here after passing args to angel_OSCPUWrite, ; but we don't bother as the first thing __main does is reset sp. B |__main| ; start higher-level Angel initialisation LTORG ; --------------------------------------------------------------------- ; The following code fragment is the simple undefined ; instruction handler we use when checking for the presence of ; a MMU co-processor:DummyMMUCode MOV r6,#0x00 ; no MMU present if we have aborted MOVS pc,lr ; return to just after faulting instruction ; --------------------------------------------------------------------- LTORG ; --------------------------------------------------------------------- END ; EOF startrom.s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -