[ PLL_ON_START
;Configure MPLL
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=12MHz,Fout=50MHz
str r1,[r0]
]
;Check if the boot is caused by the wake-up from POWER_OFF mode.
ldr r1,=GSTATUS2
ldr r0,[r1]
tst r0,#0x2
;In case of the wake-up from POWER_OFF mode, go to POWER_OFF_WAKEUP handler.
bne WAKEUP_POWER_OFF
; b WAKEUP_POWER_OFF
WAKEUP_POWER_OFF
;Release SCLKn after wake-up from the POWER_OFF mode.
ldr r1,=MISCCR
ldr r0,[r1]
bic r0,r0,#(7<<17) ;SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE->H
str r0,[r1]
;Set memory control registers
ldr r0,=SMRDATA
ldr r1,=BWSCON ;BWSCON Address
add r2, r0, #52 ;End address of SMRDATA
0
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne %B0
mov r1,#256
0 subs r1,r1,#1 ;1) wait until the SelfRefresh is released.
bne %B0
ldr r1,=GSTATUS3 ;GSTATUS3 has the start address just after POWER_OFF wake-up
; mov r1,#0
ldr r0,[r1]
mov pc,r0
我感觉是不是GSTATUS3里面存储的返回时的地址错误,导致没有返回CPUPowerOff()
我的FW.S里面相关代码
LEAF_ENTRY CPUPowerOff
; 1. Save register state and return address on the stack.
;
stmdb sp!, {r4-r12}
stmdb sp!, {lr}
; b .
; 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.
我弄了一个LED来调试,结果显示确实是进入了休眠模式,也能够唤醒,也能够判断GSTATUS2 来决定是否跳到WAKEUP_POWER_OFF处,从程序看进入这个里面后就是设置一些东西,然后从GSTATUS3 取出跳转的地址,最后进入Fw.s原来休眠的地方。但是现在从现象来看WINCE没有起来,只是电流大了,屏幕和休眠时一样胡乱的显示一些东西,代码如下:WAKEUP_POWER_OFF
;Release SCLKn after wake-up from the POWER_OFF mode.