📄 fw_utils.s
字号:
;
; The content of this file or document is CONFIDENTIAL and PROPRIETARY
; to Jade Technologies Co., Ltd. It is subjected to the terms of a
; License Agreement between Licensee and Jade Technologies Co., Ltd.
; restricting among other things, the use, reproduction, distribution
; and transfer. Each of the embodiments, including this information
; and any derivative work shall retain this copyright notice.
;
; Copyright (c) 2004 - 2005 Jade Technologies Co., Ltd.
; All rights reserved.
; ----------------------------------------------------------------
; File: fw_utils.s,v
; Revision: 1.0
; ----------------------------------------------------------------
; $
;
; Module Name:
;
; fw_utils.s
;
; Abstract:
;
; This module implements the code necessary to initialize the HW and
; Kernel interface routines.
;
; oalfuncs.h contains the C function declarations.
;
;
; 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
IF :LNOT: :DEF: EXEFLASH
GBLL EXEFLASH
EXEFLASH SETL {FALSE}
ENDIF
OPT 2 ; disable listing
INCLUDE kxarm.h
INCLUDE ssmc.inc
INCLUDE mpmc.inc
INCLUDE armmacros.inc
INCLUDE platform.inc
INCLUDE sp810.inc ; System Controller
INCLUDE sp804.inc ; Timers
INCLUDE pl011.inc ; UARTs
INCLUDE pl190.inc ; VIC & SIC
OPT 1 ; reenable listing
TEXTAREA
; **********************************************************************
; *
; * uSecsWait - uses timer2 to wait for a given number of microseconds
; *
; * NOTE: This routine takes no care to preserve current timer state
; *
; * void uSecsWait(unsigned int usecs, unsigned int virtoffset);
; *
; ****************************************************************************
LEAF_ENTRY uSecsWait
; check that we are being asked to wait
cmp r0, #0
RETURN_EQ
; point r1 at timer 2 control registers
ldr r2, =PHYS_TIMER2_BASE
add r1, r1, r2
ldr r2, [r1, #TIMER_Control]
and r2, r2, #TIMER_RESERVED_MASK ; may not modify these bits.
; Timer mode: disabled, 32 bit, one-shot, free-running, no int
orr r2, r2, #TIMER_MODE_ONESHOT | TIMER_MODE_32BIT
str r2, [r1, #TIMER_Control]
;
str r0, [r1, #TIMER_Load]
orr r2, r2, #TIMER_ENABLE
str r2, [r1, #TIMER_Control]
; read the current timer register value, and check whether it reached
; zero
msloop
ldr r2, [r1, #TIMER_Value]
cmp r2, #0
bne msloop
; OK - turn counter off and return
ldr r2, [r1, #TIMER_Control]
and r2, r2, #TIMER_RESERVED_MASK ; may not modify these bits.
str r2, [r1, #TIMER_Control]
RETURN
ENTRY_END uSecsWait
; ****************************************************************************
; ****************************************************************************
; * GetPC
; *
; * Used to obtain the current PC value
; *
; ****************************************************************************
IF EBOOT :LOR: :LNOT: EXEFLASH
LEAF_ENTRY GetPC
mov r0, pc
RETURN
ENTRY_END GetPC
ENDIF
; ****************************************************************************
; * WFI
; *
; * Called by OEMIdle when we are idle. Stops core until next interrupt
; * This imlementation includes workarounds for cacheable code.
; * See ARM926EJ-S Rev0.3 Errata List. CP023-PRDC-001555 5.0.
;
; * If the WFI instruction is run from non-cacheable region, and located at an
; * offset of between 0x3E8 and 0x3F4 (inclusive) from the previous 1KB
; * boundary, then the WFI will execute with the prefetch buffer in a non-full
; * state, and low-power state will not be entered correctly.
; * For the workaround to operate correctly, the instruction which disables
; * the cache, must be offset from the previous 1KB boundary by less then 0x3E4.
; *
; ****************************************************************************
LEAF_ENTRY WFI
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 ; Drain write buffer
mrs r2, CPSR ; Grab CPSR contents
orr r3, r2, #3 :SHL: 6 ; Turn off IRQ and FIQ inputs
mrc p15, 0, r0, c1, c0, 0 ; Read control register
bic r1, r0, #1<<12 ; Clear the Enable I Cache bit
msr CPSR_c, r3 ; Disable interrupts
ldr r3, =TestMemoryLocationLabel; If this is >996 bytes or <1020, then
; WFI will not function correctly
and r3, r3, #0x3FC
cmp r3, #0x3E0 ;
; Branch to the second code set if the first one is near the bottom of 1kb
; boundary. This guarantees that WFI instruction will be issued at the proper
; offset and the processor will be fully switched into core stop mode.
bge WaitForInterruptOffset ; Branch if greater than
; Put the system into low-power state by issuing Disable I Cache and WFI instructions.
mov r3, #0 ; This needs to be 0 (SBZ) see ARM926EJ-S TRM
TestMemoryLocationLabel
mcr p15, 0, r1, c1, c0, 0 ; Disable ICache
mcr p15, 0, r3, c7, c0, 4 ; WFI
b EndOfWFI
nop ; Make some space in the code
nop ; to bridge the 1024 byte boundary
nop
nop
WaitForInterruptOffset ; This label is 10 words after the cmp instruction
; which satisfies the requiremnt of a worst-case
; alignment where it is 996>WFI<1020 bytes from.
mov r3, #0 ; This needs to be 0 (SBZ) see ARM926EJ-S TRM
mcr p15, 0, r1, c1, c0, 0 ; Disable I cache
mcr p15, 0, r3, c7, c0, 4 ; Wait for Interrupt
EndOfWFI
mcr p15, 0, r0, c1, c0, 0 ; Re-enable ICache
msr CPSR_c, r2 ; Re-enable previous interrupt state
RETURN
ENTRY_END WFI
; ****************************************************************************
IF :DEF: EXAMPLE_MEMCONFIG
; **** NOTE: ****
; The following is example code for configuring different memory systems it
; has not been fully tested and is for reference only.
; You will need to alter and test the following code on your system.
; The Z228 platform has memory already configured on boot-up so we do not
; perform this.
; ***************
;/*
; * Configure the MPMC if Multi Port Memory Controller (MPMC) is present
; */
LEAF_ENTRY ARMConfigMemory
STR lr, [sp, #-4]!
LDR r0, =PHYS_MPMC_CNTL_BASE
LDR r1, [r0, #MPMCPeriphID0]
AND r1, r1,#MPMCPeriphID0_Mask
CMP r1, #MPMCPeriphID0PartNumber0
LDREQ r1, [r0, #MPMCPeriphID1]
ANDEQ r1, r1,#MPMCPeriphID1_Mask
LDREQ r2, =(MPMCPeriphID1PartNumber1 :OR: MPMCPeriphID1Designer0)
CMPEQ r1, r2
LDREQ r1, [r0, #MPMCPeriphID2]
ANDEQ r1, r1,#MPMCPeriphID2_Mask
LDREQ r2, =(MPMCPeriphID2Revision :OR: MPMCPeriphID2Designer1)
CMPEQ r1, r2
LDREQ r1, [r0, #MPMCPeriphID3]
ANDEQ r1, r1,#MPMCPeriphID3_Mask
LDREQ r2, =(MPMCPeriphID3ConfigAHB:OR:MPMCPeriphID3ConfigTIC:OR:MPMCPeriphID3ConfigDataBuf:OR:MPMCPeriphID3ConfigDataBuf)
CMPEQ r1, r2
BLEQ MPMCConfigMemory
;/*
; * Configure the SSMC if Synchronous Static Memory Controller (SSMC) is present
; * This section can be removed if the SSMC is not present
; */
LDR r0, =PHYS_SSMC_CNTL_BASE
LDR r1, [r0, #SSMCPeriphID0]
CMP r1, #SSMC_PL093_PID0
BLEQ SSMCConfigMemory
;/* Address remapping example */
IF :DEF: EXAMPLE_REMAP
;/* Upon power reset, the bootcode is run from address 0x0, due to address
; * remapping functionality. This aliases the SSMC memory bank 7 to address
; * 0x0 and the bootloader image is run from this address. As the hardware
; * does not support remapping we must manually return the PC back to the base
; * address of bank 7 ie PHYS_FLASH_BASE and execute the boot image from there.
; */
BL RemapSSMC
;/*
; * Switch the remap off in the system controller
; */
LDR r0, =PHYS_SC_BASE ;load the base address of the System Controller
LDR r1, [r0,#0] ;load contents of SCCTRL register
LDR r2, =SSMCRmapClr ;flag to clear the remap functionality
ORR r1, r1,r2
STR r1, [r0,#0] ;store the value back in SCCTRL register
;/* Manually copy the bootloader and kernel image into the address 0x0, which
; * is now the RAM because the remap function has been switched off.
; *
; * Purely for testing purposes, 10 Mb (0x00A00000) chunk is copied
; */
CTR EQU 0x00A00000 ;stores the amount of memory that needs to be copied, 10 Mb for now
SRC EQU PHYS_FLASH_BASE ;starting address of source block
DST EQU 0x0 ;starting address of destination block
LDR r0, =CTR
LDR r1, =SRC
LDR r2, =DST
MOV sp, #0x00C00000 ;temporarily set up stack pointer
STMFD sp!, {r3-r10} ;save the contents of the registers 3-10
LOOPMULT ;this loop copies memory from SRC location to DST location
LDMIA r1!, {r3-r10} ;load 8 words from source
STMIA r2!, {r3-r10} ;put them at the destination
SUB r0, r0, #1 ;decrement the loop counter
CMP r0, #0
BNE LOOPMULT
;memory copying completed
LDMFD sp!, {r3-r10} ;restore the contents of the registers 3-10
;/* Run image from RAM to allow faster execution */
BL RemapRAM
ENDIF ;EXAMPLE_REMAP
LDR lr, [sp], #4
mov pc, lr
ENTRY_END
; ****************************************************************************
; * MPMCConfigMemory
; *
; * Configures the parameters for the Multi-Port Memory Controller, Memory
; * Bank 0
; * This currently initialises a generic 64Mb SDRAM with address mirroring
; * disabled and write-protection disabled.
; *
; ****************************************************************************
LEAF_ENTRY MPMCConfigMemory
STR lr, [sp, #-4]!
;/* Configures the parameters for the MPMC */
LDR r0, =PHYS_MPMC_CNTL_BASE ;/* Load the MPMC physical base address */
;/* Before starting initialisation force basic configuration*/
LDR r1, =( MPMCControl_L_NormalPower :OR: MPMCControl_E_Enable );/* on POR MPMC is enabled */
STR r1, [r0,#MPMCControl] ;/* r1=0x1 */
;/* Ensure that MPMC is idle */
LDR r1,=( MPMCStatus_B_Busy )
wait
LDR r2,[r0,#MPMCStatus] ;/* read MPMC status register */
AND r2,r2,r1 ;/* mask */
CMP r2,r1 ;/* keep polling until MPMC is idle */
BNE wait ;/* branch if result of AND is not zero */
;/*
; * Now the MPMC can be disabled
; * The MPMC is no longer busy which informs us the buffers are flushed,
; * we can now carry on with initialization
; */
LDR r1, =( MPMCControl_L_NormalPower :OR: MPMCControl_E_Disable )
STR r1, [r0,#MPMCControl] ;/* r1=0x0 */
;/* Wait 100ms to ensure clocks have stabilised */
LDR r0, =100000
MOV r1, #0
BL uSecsWait
LDR r0, =PHYS_MPMC_CNTL_BASE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -