📄 target.s
字号:
SUBT PID board description and Semihosted support > pid/target.s
; ------------------------------------------------------------------
; ------------------------------------------------------------------
IF :DEF: OPT
ASSERT (listopts_s)
old_opt SETA {OPT}
OPT (opt_off) ; disable listing of include files
ENDIF
; ------------------------------------------------------------------
IF :LNOT: :DEF: pid_s
GBLL pid_s
pid_s SETL {TRUE}
; ------------------------------------------------------------------
; The "ROMonly" build variable controls whether the system
; being built supports a system where only ROM is mapped at
; zero, and RAM cannot be mapped there. i.e. where the ARM
; vectors are hard-wired in ROM. We create this variable
; un-conditionally, to ensure that if an attempt is made to
; define it elsewhere then a build error will occur.
GBLL ROMonly ; depends on target
ROMonly SETL {FALSE} ; {TRUE} if no RAM at zero
INCLUDE platform.s
GET mmumacro.s
; ------------------------------------------------------------------
; -- SEMIHOSTED and uHAL Support macros ---------------------------------
; ------------------------------------------------------------------
; ------------------------------------------------------------------
; STEP_ONE
; --------
; First instruction.
; Normally LDR PC, uHALip_ResetStart
; 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 a branch relative:
; B uHALir_ResetGo
MACRO
STEP_ONE
LDR PC, uHALip_ResetStart
MEND
; ------------------------------------------------------------------
; CHECK_PRIMARY_CPU
; -----------------
; The Integrator/SDB hardware support multiple headers, however
; uHAL is not currently multiprocessor aware. If the platform
; supports multiple CPUs, platform-specific initialisation
; will be required before this block can be removed.
MACRO
CHECK_PRIMARY_CPU
MEND
; ------------------------------------------------------------------
; UNMAPROM
; --------
; Provide code to deal with mapping the reset ROM away from zero
; (if required).
MACRO
$label UNMAPROM $w1,$w2
; The PID maps ROM away from 0 by writing a random word to a specific
; address within the Reset and Wait control area.
MOV $w2, #RPCBase
STR $w1, [$w2, #RPC_ClearResetMap]
MEND
; ------------------------------------------------------------------
; STARTUPCODE
; -----------
; Provide code to deal with the main act of mapping the reset
; ROM away from zero (if required), and ensuring that the
; target I/O world is suitably clean before attempting to
; initialise the rest of Semihosted.
;
; NOTE: do not use r4, that's $pos.
;
MACRO
$label STARTUPCODE $w1, $w2, $pos, $ramsize
MEND
; ------------------------------------------------------------------
; GOTO_ROM
; --------
; SEMIHOSTED and uHAL macro to switch from 0 to high alias of ROM.
; On PID I assume that we are running out of ROM at 0x04000000
; and that we need to swap to the Normal (re-mapped) address.
MACRO
GOTO_ROM $w1, $w2
LDR pc,=uHALip_HiReset
uHALip_HiReset
UNMAPROM $w1, $w2
MEND
; ---------------------------------------------------------------------
; VALIDATE_PROCESSOR
; ------------------
;
; Macro to validate that the software and hardware are compatible.
;
; MACRO
; VALIDATE_PROCESSOR $w1, $w2, $w3
;
; CHECK_VENDOR $w1, $w2
; BNE %F01
;
; ; Checks to see if the h/w and s/w match.
; CHECK_CPUID $w1, $w2
; BEQ %F02
;
; ; If we get here then there is a problem. We will flash the
; ; red LED on the motherboard to indicate this.
;1 LDR $w3, =INTEGRATOR_RTC_BASE
; LDR $w1, [$w3]
; ANDS $w1, $w1, #1
; MOVNE $w1, #RED_LED
;
; SET_LEDS $w1, $w2
;
; B %B01
;2
;
; MEND
; ------------------------------------------------------------------
; INIT_RAM
; --------
; SEMIHOSTED and uHAL macro to initialise memory on startup. See the calling
; macros for reasons why this particular register set is used.
MACRO
INIT_RAM $w1,$w2,$w3,$w4,$w5
; VALIDATE_PROCESSOR $w1, $w2, $w3
MEND
MACRO
$label SETUPMMU $tmp1, $size, $tmp2, $tmp3, $tmp4, $tmp5, $offset
MOV $tmp1, #4 ; DEBUG: 100, R--
DO_DEBUG $tmp1, $tmp3
; Scan for MPU and set up if found
CHECK_FOR_MPU $tmp1
BEQ %F79
; ----------------------------------------------------
; Here lies the MPU memory map for this board. Use it
; with the offset between physical & virtual TTBs to
; build a valid page table.
; To use default memory size, pass in RAM size of zero
; ----------------------------------------------------
ldr $tmp5, =uHAL_MappingTable
LDR $offset, =0
SETUP_MPU $tmp1, $size, $tmp2, $tmp3, $tmp4, $tmp5, $offset
79
; Scan for MMU and set up if found
CHECK_FOR_MMU $tmp1
BEQ %F91
; ----------------------------------------------------
; Here lies the MMU memory map for this board. Use it
; with the offset between physical & virtual TTBs to
; build a valid page table.
; To use default memory size, pass in RAM size of zero
; ----------------------------------------------------
ldr $tmp5, =uHAL_AddressTable
LDR $offset, =0
BUILD_PGTABLE $tmp1, $size, $tmp2, $tmp3, $tmp4, $tmp5, $offset
LDR $tmp1, =Level1tab ;TTB address is 2**14 aligned
WRMMU_TTBase $tmp1 ;Initialise Translation Table Base reg.
LDR $tmp1, =1
WRMMU_DAControl $tmp1 ;Initialise Domain Access Control
; ----------------------------------------------------
; Flush everything and get ready to turn on the MMU
; ----------------------------------------------------
WRMMU_FlushTB $tmp1 ; Flush TB
WRCACHE_FlushIDC $tmp1 ; Flush the Caches
NOP ; make sure that the pipe is empty
NOP
NOP
91
MOV $tmp1, #5 ; DEBUG: 101, R-Y
DO_DEBUG $tmp1, $tmp3
MEND
; ---------------------------------------------------------------------
; GET_RAMSIZE
; ---------
; $w1 -> minimum guaranteed memory amount
; <- actual memory fitted to machine
; $w2, $w3, $w4 are scratch
MACRO
GET_RAMSIZE $w1, $w2, $w3, $w4, $w5
; first off, do we have any DRAM?
MOV $w3,#0xBE000000 ; get ourselves a very unlikely number (be so dead!)
ORR $w3,$w3,#0x00500000
ORR $w3,$w3,#0x0000DE00
ORR $w3,$w3,#0x000000AD
LDR $w4,[$w1]
STR $w3,[$w1] ; store at the base of DRAM
LDR $w2,[$w1]
CMP $w2,$w3
BNE %F01 ; 512k is our friend (ie; no DRAM)
; be paranoid about floating addr lines - try with another value
STR $w1,[$w1]
LDR $w2,[$w1]
CMP $w2,$w1
BNE %F01 ; was 512k after all ...
; fairly likely we have RAM there, but how much?
; $w1 will be test base
; $w2 will be counter
; $w3 will be test
; $w4 will be old contents
MOV $w2,$w1
STR $w3,[$w1] ; watch for it going to zero
2
ADD $w2,$w2,#0x400000 ; inc by 4Mb
CMP $w2,#0x01000000 ; broken 16Mb?
MOVCS $w2,#0x01000000
BCS %F03
LDR $w5,[$w2] ; keep old contents of test location
STR $w1,[$w2] ; store some non-besodead value
LDR $w3,[$w1] ; see if besodead has been altered
CMP $w3,$w1
STRNE $w5,[$w2] ; restore old contents
BNE %B02
3
STR $w4,[$w1]
MOV $w1,$w2
MOV PC,PC ; skip next instruction
1
STR $w4,[$w1] ; restore old value (probably program code)
MEND
; ------------------------------------------------------------------
; INITMMU
; ----------
; uHAL macro, calls the core SETUPMMU macro if the MMU is
; enabled and then sets ICache, DCache & WBuffer as required.
; On certain system where the target does not have a MMU, then this
; macro is almost a NOP, since using the ICache & WBuffer on their
; own is still a big gain.
;
MACRO
$label INITMMU $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $tmp6
PIDInitMMU
IF :LNOT: :DEF: ENABLE_MMU
ENABLE_MMU EQU 1 ; Semihosted flags not defined in uHAL
CACHE_SUPPORTED EQU 1
ENDIF
IF ENABLE_MMU = 1
LDR $tmp2, =uHAL_MEMORY_SIZE ; Pass the top of memory
SETUPMMU $tmp1, $tmp2,$tmp3, $tmp4, $tmp5, $tmp6
; Enable MMU, alignment faults and IC/DC/WB as required
;
LDR $tmp2, =EnableMMU ; NOTE: no alignment checks enabled
ELSE
LDR $tmp2, =0 ; No MMU
ENDIF ; ENABLE_MMU
IF CACHE_SUPPORTED = 1
IF ENABLE_MMU = 1
LDR $tmp1, =(IC_ON + DC_ON + WB_ON)
ELSE
; Cannot use Data Cache without MMU
LDR $tmp1, =(IC_ON + WB_ON)
ENDIF
ELSE
; Handy performance boost to be had even if no MMU is available
;LDR $tmp1, =(IC_ON + WB_ON)
LDR $tmp1, =0
ENDIF ; CACHE_SUPPORTED
ORR $tmp1, $tmp1, $tmp2
IF {ENDIAN} = "big"
ORR $tmp1, $tmp1, #EnableBigEndian
ENDIF ; BIG_ENDIAN
WRCP15_Control $tmp1 ; Update control register
NOP
NOP
NOP
NOP
MEND
; ------------------------------------------------------------------
; INITTIMER
; ---------
; Semihosted macro is provided purely as a holder for any code that may
; be required to initialise a hardware timer as part of the reset
; sequence. Semihosted does *NOT* make use of any timer resources, so by
; default this macro should not be required to do anything. However,
; under exceptional circumstances special code may be required to
; ensure that Semihosted starts cleanly and that later application
; specific code can have full control of the timer.
MACRO
$label INITTIMER $w1, $w2
MEND
; ------------------------------------------------------------------
; REVERSE
; -------
; Quick word byte-order reversal macro. Handy for endian stuff.
MACRO
$label REVERSE $w1, $w2 ; w1: D C B A
EOR $w2, $w1, $w1, ROR #16 ; w2: D^B, C^A, B^D, A^C
BIC $w2, $w2, #0xff0000 ; w2: D^B, 0 , B^D, A^C
MOV $w1, $w1, ROR #8 ; w1: A D C B
EOR $w1, $w1, $w2, LSR #8 ; w2>>8: 0 D^B 0 B^D
MEND ; w1: A B C D
; ------------------------------------------------------------------
; GETSOURCE
; ---------
; This Semihosted macro is used to read the current interrupt source
; activity status for the Semihosted device driver interrupts:
MACRO
$label GETSOURCE $w1, $w2
;; Find out what caused the interrupt
MEND
; ------------------------------------------------------------------
; READ_INT
; --------
; uHAL macro to read which interrupt(s) is active (result in $w1)
MACRO
$label READ_INT $w1, $w2, $w3
MOV $w1,#ICBase
LDR $w1,[$w1, #IC_IRQStatus]
MEND
; ------------------------------------------------------------------
; CACHE_IBR
; ---------
; This Semihosted macro implements an instruction barrier for a range of
; addresses (i.e. it makes instruction and data memory coherent for
; this range) .
; w1 contains the start of the range
; w2 the next address after the end
; Note that w1 will be corrupted
MACRO
$label CACHE_IBR $w1, $w2, $temp, $temp2
MEND
; ------------------------------------------------------------------
; Semihosted and uHAL macro to disable interrupts on powerup
MACRO
$label DISABLE_INTS $w1, $w2
MOV $w1, #ICBase
MOV $w2, #255
ORR $w2, $w2, $w2, LSL #8
STR $w2, [$w1, #IC_IRQEnableClear]
MEND
; ------------------------------------------------------------------
; uHAL macro to initialise external interrupts and other essential
; IO on startup when running standalone
MACRO
$label INIT_INTS $w1, $w2, $w3
IF :DEF: STANDALONE
DISABLE_INTS $w1, $w2
ENDIF
MEND
; ------------------------------------------------------------------
; macro to set the LEDs to the value given in $w1
; Variant which writes to numeric display as well as LEDs.
MACRO
$label NSET_LEDS $w1, $w2, $w3
SET_LEDS $w1, $w2, $w3
MEND
; ------------------------------------------------------------------
; macro to set the LEDs to the value given in $w1
; NOTE: this should be the same as SetLEDs in driver.s
MACRO
$label SET_LEDS $w1, $w2, $w3
MEND
; ------------------------------------------------------------------
; Macro for debugging without having target-specific code in uHAL
MACRO
$label DO_DEBUG $w1, $w2, $w3
NSET_LEDS $w1, $w2, $w3 ; Number + LED lighting on Pid
MEND
ENDIF ; pid_s
IF :DEF: OPT
OPT (old_opt) ; restore previous listing options
ENDIF
END ; EOF target.s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -