欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

fw_arm.s

WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
S
字号:
; -*-Text-*-
;
;      TITLE("Integrator Firmware Initialization")
;
; $Revision: 1.13 $
;   $Author: kwelton $
;     $Date: 2000/08/11 23:17:33 $
;
; Copyright (c) 1997  Microsoft Corporation
; Copyright (c) 1999 ARM Limited
; All Rights Reserved
;
; Module Name:
;
;    fw_arm.s
;
; Abstract:
;
;    This module implements the code necessary to initialize the HW and
; Kernel interface routines.
;
;--

;
; This one source file is used to provide Startup code both for the
; Ethernet Boot Loader, and for the WinCE kernel. The default is to
; build for the WinCE kernel
;
    IF :LNOT: :DEF: EBOOT
        GBLL    EBOOT
EBOOT   SETL    {FALSE}
    ENDIF

                GBLL    SteveRavetsCode
SteveRavetsCode SETL    {TRUE}

        OPT     2       ; disable listing
        INCLUDE kxarm.h
        INCLUDE oalintra.inc
        OPT     1       ; reenable listing

        INCLUDE sizes.s
        INCLUDE bits.s
        INCLUDE platform.s
        INCLUDE cpumodes.s
        INCLUDE target.s

        IMPORT  ARMInitSerial
        IMPORT  ARMPutHex
        IMPORT  ARMWriteString
        IMPORT  ARMSetLEDs
        IMPORT  ARMSetAlpha

   IF EBOOT
        IMPORT  EbootMain
        IMPORT  EverythingRelocate
    ELSE
        IMPORT  KernelStart
    ENDIF

    IF FORCE_TGTCPU = "ARM720"

CP15ControlInit EQU     0x00000270              ; Little-Endian
                                                ; MMU Disabled
    ENDIF

    IF FORCE_TGTCPU = "ARM920"

CP15ControlInit EQU     0xc0001078              ; Async. Bus mode
                                                ; I-Cache enabled
                                                ; Little-Endian
                                                ; MMU Disabled
    ENDIF

        STARTUPTEXT
        LEAF_ENTRY StartUp


;
; There are two ways into StartUp: from the bootmonitor/reset or from
; wake up. In either case, the processor should be in a privileged mode
; (e.g. SVC) with the MMU disabled. If the MMU might be active, there
; needs to be code to ensure that the executable is still at the next
; address when the MMU is turned off.
;
        ; disable all interrupts, set SVC mode
        mov     r0, #(SVC32Mode :OR: NoINTS)
        msr     cpsr_c, r0

; ****************** FALSE
  [ {FALSE}
;
; XXX TRACE XXX TRACE XXX TRACE XXX
;
; This is ARM10200 AHB code, here temporarily so we can
; try and clock the chip as fast as possible. This will
; almost certainly not work on a '920 board.
;
        ldr     r0, =0x00000070 ; I & D cache off, wb off, mmu off
        mcr     p15, 0, r0, c1, c0, 0

;
; Init Integrator registers
;
        mov     r0, #0x10000000
        ldr     r1, =0xa05f
        str     r1, [r0, #0x14] ; unlock OSC & Init registers

;
; INIT register (bit 2 = HIVECInit, 4,5 HBUSDIV, 8-11 PLLTest, 
;                12-13 = VFPTest)
;
        ldr     r1, [r0, #0x24]

;
; bit 1 tells whether the PLL is in bypass or not - if it isn't then we
; can proceed with the clock setup
;
        tst     r1, #0x02
        beq     pllactive

        bic     r1, r1, #0x3f00
        bic     r1, r1, #0x0034


    IF SteveRavetsCode
;
; make GCLK observable on CLKTSTOUT
;
        orr      r1, r1, #0x0800
    ENDIF

        str     r1, [r0, #0x24]

;
; OSC register contains clock input speed in MHz
;
        ldr     r1, [r0, #0x8]
        bic     r1, r1, #0xff

    IF SteveRavetsCode
        orr     r1, r1, #50
    ELSE
        orr     r1, r1, #80
    ENDIF

        sub     r1, r1, #8
        str     r1, [r0, #0x8]

;
; program ARM10200 PLL
;
    IF SteveRavetsCode
        mov     r0, #2  ; MDIV
        mov     r1, #1  ; F1DIV
        mov     r2, #2  ; F2DIV
    ELSE
        mov     r0, #1  ; MDIV
        mov     r1, #1  ; F1DIV
        mov     r2, #1  ; F2DIV
        mov     r0, r0, lsl #1
    ENDIF

;
; these seemingly strange subtracts are to convert from the
; required values to the values that need to be programmed
; into the PLL to acheive those requirements
;
        sub     r0, r0, #1
        sub     r1, r1, #1
        sub     r2, r2, #1
        orr     r2, r2, r1, lsl #5
        orr     r2, r2, r0, lsl #10
        mcr     p15, 0, r0, c15, c12, 0

; ****************** FALSE
    [ {FALSE}
;
; we need to force a reset before the new settings take effect
;
; set yellow LED before forcing reset
;
        mov     r0, #YELLOW_LED
        bl      ARMSetLEDs

        mov     r0, #0x10000000
        ldr     r1, [r0, #0x0c]
        orr     r1, r1, #1 << 3
        str     r1, [r0, #0x0c]

;
; XXX SHOULD NOT BE REACHED
;
        mov     r0, #RED_LED
        bl      ARMSetLEDs
pllspin b       pllspin
; ********************** End of FALSE
    ]

pllactive
        mov     r0, #GREEN_LED
        bl      ARMSetLEDs
; ********************** End of FALSE
  ]


;
; now reset all CP15 features
;
        ldr                     r0, =CP15ControlInit
        WRMMU_STATE             r0

        mov                     r0, #0x0
        WRMMU_FlushTB           r0              ; flush TLBs
        WRCACHE_FlushIDC        r0              ; flush caches

;
; Make sure we're running from the physical memory address and
; not an address mapped to 0 (the normal reset state).
;
        GOTO_ROM        r0, r1
        DISABLE_INTS    r0, r1                  ; Ints -> IRQ; LEDs


; Now, if the reset was caused by a wake-up from sleep, control isn't
; passed to KernelStart, but some reload-saved-state mechanism instead.

        ; Put StrongARM wake-up test in here...
        ; ..and branch away from power-on start.
        ; NOTE: Most ARM processors don't go to sleep

        INIT_RAM        r0, r1, r2      ; Size returned in r2

;
; only used temporarily, but setup a stack for use by 'C' routines; the
; Integrator always has 256Kb of SSRAM, so we use that
;
; the first use of the stack is to save the memory size returned from
; the INIT_RAM macro
;
        ldr     sp, =(INTEGRATOR_SSRAM_BASE + INTEGRATOR_SSRAM_SIZE)
        str     r2, [sp, #-4]!

    IF EBOOT
;
; Relocate code from Flash to RAM if necessary. This step is required
; because EBOOT code runs from physical, not virtual, addresses
;
; returns with r0 = linked address for Startup, -1 if currently
; executing in the correct place
;

        bl      EverythingRelocate

;
; branch to final execution address if necessary
;

	cmp     r0, #-1
	addne   r0, r0, #(RealStartup - StartUp)
	movne   pc, r0

    ENDIF

RealStartup

        SETUP_PCI       r0, r1, r2, r3

;
; XXX
;
; After setting up PCI, there is some necessary settle time before the
; interface can be used. It >was< hoped that this would prove to be
; not necessary, but sadly not.
;
        mov             r0, #1000
        mov             r1, #0
        bl              msecswait

;
; init the debug serial port and say "hello".
;
        bl      ARMInitSerial
        adr     r0, HelloMsg
        bl      ARMWriteString

        adr     r0, MemMsg
        bl      ARMWriteString

        ldr     r0, [sp], #4
        bl      ARMPutHex

        adr     r0, StackMsg
        bl      ARMWriteString
        mov     r0, sp
        bl      ARMPutHex

        adr     r0, EndMsg
        bl      ARMWriteString

        mov     r0, #0                  ; Turn off the discrete LEDs
        bl      ARMSetLEDs

        mov     r0, #0
        bl      ARMSetAlpha             ; Turn off the Alphanumeric LEDs

    IF EBOOT
        bl      EbootMain
    ELSE
        ; (r0) = physical address of OEMMemoryMap
        adr     r0, OEMAddressTable

        bl      KernelStart
    ENDIF

;
; control should never return to this routine; if it does, output
; some debug & spin
;

;
; Display a pattern of two stars on the Alphanumeric LEDs, and turn on
; the red LED
;
        ldr     r0, =0x1fe07f80         ; bit pattern for two stars
        bl      ARMSetAlpha

        mov     r0, #RED_LED
        bl      ARMSetLEDs

        adr     r0, ByeMsg
        bl      ARMWriteString

spin    b       spin

    IF EBOOT
HelloMsg        DCB     13, 10, "ARM Ethernet Boot Loader", 13, 10, 0
ByeMsg          DCB     13, 10, "ARMInt_Eboot returned!", 13, 10, 0
    ELSE
HelloMsg        DCB     13, 10, "WindowsCE on ARM", 13, 10, 0
ByeMsg          DCB     13, 10, "KernelStart returned!", 13, 10, 0
    ENDIF

MemMsg          DCB     "  Memory size: ", 0
StackMsg        DCB     13, 10, "  Stack Pointer: ", 0
EndMsg          DCB     13, 10, 0

        ALIGN   4

    IF :LNOT: EBOOT
        INCLUDE maparm.h
    ENDIF

; End of initialization code & data
        TEXTAREA

; **********************************************************************

;
; msecswait - uses timer2 to wait for a given number of milliseconds
;
; NOTE: this routine can only be used very early on in the system bootstrap
;       process (i.e. only before OEMInit() has been called) because it
;       takes no care to preserve current timer state
;
        LEAF_ENTRY      msecswait

;
; check that we are being asked to wait
;
        cmp     r0, #0

    IF Thumbing
        bxeq    lr
    ELSE
        moveq   pc, lr
    ENDIF

        str     r4, [sp, #-4]!

;
; point r1 at timer2 control registers
;
        ldr     r2, =INTEGRATOR_TIMER2_BASE
        add     r1, r1, r2

;
; We use Timer2 which is clocked at 24MHz. Dividing the clock by 16 gives
; 1500 ticks per millisecond
;
        mov     r2, #0x44               ; clock/16, periodic, disabled
        strb    r2, [r1, #8]

        ldr     r3, =1500
        strh    r3, [r1, #0]

        orr     r2, r2, #0x80           ; set enabled bit
        strb    r2, [r1, #8]

;
; read the current timer register value, and check whether it reached zero
;
        mov     r4, r3
msloop
        ldrh    r2, [r1, #4]
        cmp     r2, #0
        beq     decmscount

;
; it's not zero - check whether it has gone through zero
; and reloaded already
;
        cmp     r2, r3
        movls   r3, r2
        bls     msloop

;
; counter has reached/gone through zero - that's another millisecond
; gone; reset underflow comparator
;
decmscount
        subs    r0, r0, #1
        mov     r3, r4
        bhi     msloop

;
; OK - turn counter off and return
;
        mov     r2, #0
        strb    r2, [r1, #8]

        ldr     r4, [sp], #4

    IF Thumbing
        bx      lr
    ELSE
        mov     pc, lr
    ENDIF

; **********************************************************************

    IF EBOOT
        LEAF_ENTRY GetPC
        mov     r0, pc
        mov     pc, lr
    ELSE
        LEAF_ENTRY OEMPowerOff
; OEMPowerOff - OFF button handler
;
; This routine is invoked when the OFF button is pressed. It is responsible
; for any final power off state and putting the cpu into standby.
;
;       Entry   none
;       Exit    none
;       Uses    r0-r3

        mov     pc, lr

CLOCK_LEDS      EQU     1

        LEAF_ENTRY OEMIdle
; OEMIdle - system idle
;
; This routine is called by the kernel when there are no threads ready to
; run. The CPU should be put into a reduced power mode and halted. It is
; important to be able to resume execution quickly upon receiving an interrupt.
;
; NOTE: Exceptions are blocked when this routine called and must not be
; reenabled unless the functions is going to return immediately.
;
;       Entry   Interrupts disabled
;       Exit    none
;       Uses    r0-r1

      IF :DEF: CLOCK_LEDS :LAND: CLOCK_LEDS = 1
        IMPORT  CurMSec
        IMPORT  OEMWriteDebugLED

; Simple debug, just show no of seconds (approx)
	stmfd   sp!, {r0-r1, lr}

;ldr     r1, =CurMSec
;ldr     r1, [r1]
;mov     r1, r1, LSR #10         ; mSec / 1024 ~= Sec
;mov     r0, #0
;bl      OEMWriteDebugLED
	
	ldmfd   sp!, {r0-r1, pc}
      ENDIF

    ENDIF ; EBOOT

        END

; EOF fw_arm.s

⌨️ 快捷键说明

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