📄 fw.s
字号:
;**
; * CPUPowerReset - Software reset routine. Just jump to StartUp in this file.
; *
; * Entry none
; * Exit none
; * Uses r0-r3
; *
LEAF_ENTRY CPUPowerReset
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; base of Sleep mode storage
mov r2, #0x38000000 ; store Virtual return address
str r2, [r3], #4
; Disable MMU
ldr r2, = PhysicalStart
ldr r3, = (0x8C000000 - 0x30000000)
sub r2, r2, r3
mov r1, #0x0070 ; Disable MMU
mcr p15, 0, r1, c1, c0, 0
nop
mov pc, r2 ; Jump to PStart
nop
; MMU & caches now disabled.
PhysicalStart
bl ARMClearUTLB
bl ARMFlushICache
ldr r0, = (DCACHE_LINES_PER_SET - 1)
ldr r1, = (DCACHE_NUM_SETS - 1)
ldr r2, = DCACHE_SET_INDEX_BIT
ldr r3, = DCACHE_LINE_SIZE
bl ARMFlushDCache
[ {FALSE}
ldr r2, =0x201000 ; offset into the RAM
add r2, r2, #0x30000000 ; add physical base
add r2, r2, r3
mov pc, r2 ; & jump to StartUp address
]
ldr r2, =0x201000 ; offset into the RAM
ldr r3, =0x30000000 ; add physical base
add r2, r2, r3
mov pc, r2 ; & jump to StartUp address
;**
; * EmergencyCPUPowerOff - Emergency condition ( fast poweroff ).
; *
; * Entry none
; * Exit none
; * Uses r0-r3
; *
LEAF_ENTRY EmergencyCPUPowerOff
; 1. Push SVC state onto our stack
stmdb sp!, {r4-r12}
stmdb sp!, {lr}
; 2. Save MMU & CPU Register to RAM
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; base of Sleep mode storage
ldr r2, =Awake_address ; store Virtual return address
str r2, [r3], #4
mrc p15, 0, r2, c1, c0, 0 ; load r2 with MMU Control
ldr r0, =MMU_CTL_MASK ; mask off the undefined bits
bic r2, r2, r0
str r2, [r3], #4 ; store MMU Control data
mrc p15, 0, r2, c2, c0, 0 ; load r2 with TTB address.
ldr r0, =MMU_TTB_MASK ; mask off the undefined bits
bic r2, r2, r0
str r2, [r3], #4 ; store TTB address
mrc p15, 0, r2, c3, c0, 0 ; load r2 with domain access control.
str r2, [r3], #4 ; store domain access control
str sp, [r3], #4 ; store SVC stack pointer
mrs r2, spsr
str r2, [r3], #4 ; store SVC status register
mov r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; Enter FIQ mode, no interrupts
msr cpsr, r1
mrs r2, spsr
stmia r3!, {r2, r8-r12, sp, lr} ; store the FIQ mode registers
mov r1, #Mode_ABT:OR:I_Bit:OR:F_Bit ; Enter ABT mode, no interrupts
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr} ; store the ABT mode Registers
mov r1, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; Enter IRQ mode, no interrupts
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr} ; store the IRQ Mode Registers
mov r1, #Mode_UND:OR:I_Bit:OR:F_Bit ; Enter UND mode, no interrupts
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr} ; store the UND mode Registers
mov r1, #Mode_SYS:OR:I_Bit:OR:F_Bit ; Enter SYS mode, no interrupts
msr cpsr, r1
stmia r3!, {sp, lr} ; store the SYS mode Registers
mov r1, #Mode_SVC:OR:I_Bit:OR:F_Bit ; Back to SVC mode, no interrupts
msr cpsr, r1
; 3. do Checksum on the Sleepdata
[ {FALSE}
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; get pointer to SLEEPDATA
mov r2, #0
ldr r0, =SLEEPDATA_SIZE ; get size of data structure (in words)
30
ldr r1, [r3], #4
and r1, r1, #0x1
mov r1, r1, LSL #31
orr r1, r1, r1, LSR #1
add r2, r2, r1
subs r0, r0, #1
bne %b30
]
ldr r0, =vGPIOBASE
str r2, [r0, #oGSTATUS3] ; Store in Power Manager Scratch pad register
; 4. Interrupt Disable
ldr r0, =vINTBASE
mvn r2, #0
str r2, [r0, #oINTMSK]
str r2, [r0, #oSRCPND]
str r2, [r0, #oINTPND]
; 5. Cache Flush
[ {FALSE}
bl ARMClearUTLB
bl ARMFlushICache
ldr r0, = (DCACHE_LINES_PER_SET - 1)
ldr r1, = (DCACHE_NUM_SETS - 1)
ldr r2, = DCACHE_SET_INDEX_BIT
ldr r3, = DCACHE_LINE_SIZE
bl ARMFlushDCache
]
; 6. Setting Wakeup External Interrupt(EINT0,1,2) Mode
ldr r0, =vGPIOBASE
ldr r1, =0x550a
str r1, [r0, #oGPFCON]
ldr r1, =0x55550100
str r1, [r0, #oGPGCON]
; 7. Go to Power-Off Mode
ldr r0, =vMISCCR
ldr r0, [r0]
ldr r0, =vCLKCON
ldr r0, [r0]
ldr r0, =vREFRESH
ldr r1, [r0] ; r1=rREFRESH
orr r1, r1, #(1 << 22)
ldr r2, =vMISCCR
ldr r3, [r2]
orr r3, r3, #(7<<17) ; Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up
ldr r4, =vCLKCON
ldr r5, =0x7fff8 ; Power Off Mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WinCE 3.00 assembler has some problem about ALIGN instruction.
; Sometimes it is not working in cache mode. So I modify to jump to ROM area.
; If the rom is EBOOT, the target address is 0x92001004.
; Else if the rom is NAND, the target address is 0x92000004.
ldr r8, =0xEA000000
add r8, r8, #0x3f0
add r8, r8, #0xe ; make value to 0xEA0003FE
ldr r6, =0x92000000 ; make address to 0x9200 1004 or 0x9200 0004
ldr r7, [r6] ; Check ROM Address data, if 0xEA0003FE, it is EBOOT
cmp r7, r8
bne %f50
add r6, r6, #0x1000 ; Because eboot startup code is located at 0x1000.
50
add r6, r6, #0x4 ;
mov pc, r6 ; jump to Power off code in ROM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
b SelfRefreshAndPowerOff2
ALIGN 32 ; for I-Cache Line(32Byte, 8 Word)
SelfRefreshAndPowerOff2 ; run with Instruction Cache's code
str r1, [r0] ; Enable SDRAM self-refresh
str r3, [r2] ; MISCCR Setting
str r5, [r4] ; Power Off !!
b .
;**
; * CPUPowerOff - OFF button handler(Called from OEMPowerOff() in cfw.c)
; * 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
; *
LEAF_ENTRY CPUPowerOff
; 1. Save register state and return address on the stack.
;
stmdb sp!, {r4-r12}
stmdb sp!, {lr}
; 2. Save MMU & CPU Registers to RAM.
;
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; base of Sleep mode storage
ldr r2, =Awake_address
str r2, [r3], #4 ; save resume function address (virtual).
mrc p15, 0, r2, c1, c0, 0
ldr r0, =MMU_CTL_MASK
bic r2, r2, r0
str r2, [r3], #4 ; save MMU control data.
mrc p15, 0, r2, c2, c0, 0
ldr r0, =MMU_TTB_MASK
bic r2, r2, r0
str r2, [r3], #4 ; save TTB address.
mrc p15, 0, r2, c3, c0, 0
str r2, [r3], #4 ; save domain access control.
str sp, [r3], #4 ; save SVC mode stack pointer.
mrs r2, spsr
str r2, [r3], #4 ; save SVC status register.
mov r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; enter FIQ mode, no interrupts.
msr cpsr, r1
mrs r2, spsr
stmia r3!, {r2, r8-r12, sp, lr} ; save the FIQ mode registers.
mov r1, #Mode_ABT:OR:I_Bit:OR:F_Bit ; enter ABT mode, no interrupts.
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr} ; save the ABT mode Registers.
mov r1, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; enter IRQ mode, no interrupts.
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr} ; save the IRQ Mode Registers.
mov r1, #Mode_UND:OR:I_Bit:OR:F_Bit ; enter UND mode, no interrupts.
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr} ; save the UND mode Registers.
mov r1, #Mode_SYS:OR:I_Bit:OR:F_Bit ; enter SYS mode, no interrupts.
msr cpsr, r1
stmia r3!, {sp, lr} ; save the SYS mode Registers.
mov r1, #Mode_SVC:OR:I_Bit:OR:F_Bit ; back to SVC mode, no interrupts.
msr cpsr, r1
; 3. Compute the checksum on SleepData (verify integrity of data after resume).
;
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; get pointer to SLEEPDATA.
mov r2, #0
ldr r0, =SLEEPDATA_SIZE ; get size of data structure (in words).
30
ldr r1, [r3], #4 ; compute the checksum.
and r1, r1, #0x1
mov r1, r1, LSL #31
orr r1, r1, r1, LSR #1
add r2, r2, r1
subs r0, r0, #1
bne %b30
ldr r0, =vGPIOBASE
str r2, [r0, #oGSTATUS3] ; save the checksum in the Power Manager Scratch pad register.
; 4. Mask and clear all interrupts.
;
ldr r0, =vINTBASE
mvn r2, #0
str r2, [r0, #oINTMSK]
str r2, [r0, #oSRCPND]
str r2, [r0, #oINTPND]
; 5. Flush caches and TLBs.
;
bl ARMClearUTLB
bl ARMFlushICache
ldr r0, = (DCACHE_LINES_PER_SET - 1)
ldr r1, = (DCACHE_NUM_SETS - 1)
ldr r2, = DCACHE_SET_INDEX_BIT
ldr r3, = DCACHE_LINE_SIZE
bl ARMFlushDCache
; 6. Set external wake-up interrupts (EINT0-2: power-button and keyboard).
;
ldr r0, =vGPIOBASE
ldr r1, =0x550a
str r1, [r0, #oGPFCON]
ldr r1, =0x55550100
str r1, [r0, #oGPGCON]
; 7. Switch to power-off mode.
;
ldr r0, =vMISCCR ; hit the TLB
ldr r0, [r0]
ldr r0, =vCLKCON
ldr r0, [r0]
; **These registers are used later during power-off.
;
ldr r0, =vREFRESH
ldr r1, [r0] ; r1 = rREFRESH.
orr r1, r1, #(1 << 22)
; **These registers are used later during power-off.
;
ldr r2, =vMISCCR
ldr r3, [r2]
orr r3, r3, #(7 << 17) ; make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up.
; **These registers are used later during power-off.
;
ldr r4, =vCLKCON
ldr r5, =0x7fff8 ; power-off mode.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WinCE 3.00 assembler has some problem about ALIGN instruction.
; Sometimes it is not working in cache mode. So I modify to jump to ROM area.
; If the rom is EBOOT, the target address is 0x92001004.
; Else if the rom is NAND, the target address is 0x92000004.
ldr r8, =0xEA000000
add r8, r8, #0x3f0
add r8, r8, #0xe ; make value to 0xEA0003FE
ldr r6, =0x92000000 ; make address to 0x9200 1004 or 0x9200 0004
ldr r7, [r6] ; Check ROM Address data, if 0xEA0003FE, it is EBOOT
cmp r7, r8
bne %f50
add r6, r6, #0x1000 ; Because eboot startup code is located at 0x1000.
50
add r6, r6, #0x4 ;
mov pc, r6 ; jump to Power off code in ROM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
b SelfRefreshAndPowerOff
ALIGN 32 ; for I-Cache Line(32Byte, 8 Word)
SelfRefreshAndPowerOff ; run with Instruction Cache's code
str r1, [r0] ; Enable SDRAM self-refresh
str r3, [r2] ; MISCCR Setting
str r5, [r4] ; Power Off !!
b .
; This point is called from EBOOT's startup code(MMU is enabled)
; in this routine, left information(REGs, INTMSK, INTSUBMSK ...)
Awake_address
; 1. Recover CPU Registers
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; Sleep mode information data structure
add r2, r3, #SleepState_FIQ_SPSR
mov r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; Enter FIQ mode, no interrupts
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr r8, [r2], #4
ldr r9, [r2], #4
ldr r10, [r2], #4
ldr r11, [r2], #4
ldr r12, [r2], #4
ldr sp, [r2], #4
ldr lr, [r2], #4
; mov r1, #Mode_ABT:OR:I_Bit:OR:F_Bit ; Enter ABT mode, no interrupts
mov r1, #Mode_ABT:OR:I_Bit ; Enter ABT mode, no interrupts
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
ldr lr, [r2], #4
; mov r1, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; Enter IRQ mode, no interrupts
mov r1, #Mode_IRQ:OR:I_Bit ; Enter IRQ mode, no interrupts
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
ldr lr, [r2], #4
; mov r1, #Mode_UND:OR:I_Bit:OR:F_Bit ; Enter UND mode, no interrupts
mov r1, #Mode_UND:OR:I_Bit ; Enter UND mode, no interrupts
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
ldr lr, [r2], #4
; mov r1, #Mode_SYS:OR:I_Bit:OR:F_Bit ; Enter SYS mode, no interrupts
mov r1, #Mode_SYS:OR:I_Bit ; Enter SYS mode, no interrupts
msr cpsr, r1
ldr sp, [r2], #4
ldr lr, [r2]
; mov r1, #Mode_SVC:OR:I_Bit:OR:F_Bit ; Enter SVC mode, no interrupts
mov r1, #Mode_SVC:OR:I_Bit ; Enter SVC mode, no interrupts
msr cpsr, r1
ldr r0, [r3, #SleepState_SVC_SPSR]
msr spsr, r0
; 2. Recover Last mode's REG's, & go back to caller of CPUPowerOff()
ldr sp, [r3, #SleepState_SVC_SP]
ldr lr, [sp], #4
ldmia sp!, {r4-r12}
mov pc, lr ; and now back to our sponsors
;
; MMU_WaitForInterrupt() from 2410slib.s (in bsp/others/test2410_r11 dirs)
;
;void MMU_WaitForInterrupt(void)
EXPORT MMU_WaitForInterrupt
MMU_WaitForInterrupt
mcr p15,0,r0,c7,c0,4
mov pc, lr ;MOV_PC_LR
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -