|
用的是S3C2440的CPU,查看datasheet,有关于准备挂起,挂起,唤醒的大概描述。
LEAF_ENTRY CPUPowerOff
; 1. Push SVC state onto our stack
stmdb sp!, {r4-r12}
stmdb sp!, {lr}
; VLED_ON 0x0
; 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
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
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, [r0, #oGPFCON]
; ldr r1, =0x00002 ;set gpf0 as wake up eint
; and r1, r1, #0xfffffffc
; orr r1, r1, #2
; and r1, r1, #0x00000c00
; orr r1, r1, #0x00000400
; str r1, [r0, #oGPFCON]
ldr r0, =vGPIOBASE
ldr r1, =0x950a
str r1, [r0, #oGPFCON]
ldr r1, =0x55550100
str r1, [r0, #oGPGCON]
; 7. Go to Power-Off Mode
ldr r0, =vMISCCR ; hit the TLB
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)
ldr r4, =vCLKCON
ldr r5, =0x7fff8 ; Power Off Mode
ldr r8, =0xEA000000
add r8, r8, #0x3f0
add r8, r8, #0xe ; make value to 0xEA0003FE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Sometimes it is not working in cache mode. So I modify to jump to ROM area.
; ldr r6, =0x92000000 ; make address to 0x9200 0020
; 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 .
这时应当进入到睡眠了。
以下为唤醒
; :::::::::::::::::::::::::::::::::::::::::::::
; Add for Power Management
; - - - - - - - - - - - - - - - - - - - - - - -
ldr r1, =GSTATUS2 ; Determine Booting Mode
ldr r10, [r1]
tst r10, #0x2 ; Power-Off reset Check
beq %F2 ; if not wakeup from PowerOffmode
; goto Watchdog reset test.
b %F3 ; if wakeup from PowerOff mode
; goto Power-up code.
; Watchdog reset
2
tst r10, #0x4 ; In case of the wake-up from Watchdog reset,
; go to SDRAM start address(0x3020_0000)
b %F4 ; If not wakeup from Watchdog reset,
beq %F4 ; If not wakeup from Watchdog reset,
; goto Normal Mode.
mov r0, #4
str r0, [r1] ; Clear the GSTATUS2. Because same code is located in memory address.
; Set memory control registers
add r0, pc, #SMRDATA - (. + 8)
ldr r1, = BWSCON ; BWSCON Address
add r2, r0, #52 ; End address of SMRDATA
loop0
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne loop0
mov r1, #256
loop1
subs r1, r1, #1 ; wait until the SelfRefresh is released.
bne loop1
ldr r2, =0x201000 ; offset into the RAM
add r2, r2, #0x30000000 ; add physical base
mov pc, r2 ; & jump to StartUp address
b .
; Case of Power-off reset
3
ldr r1, =MISCCR ; MISCCR's Bit 17, 18, 19 -> 0
ldr r0, [r1]
bic r0, r0, #(3 << 17)
str r0, [r1]
; - - - - - - - - - - - - - - - - - - - - - - -
; Add for Power Management
; :::::::::::::::::::::::::::::::::::::::::::::
4
add r0, pc, #SMRDATA - (. + 8)
ldr r1, = BWSCON ; BWSCON Address
add r2, r0, #52 ; End address of SMRDATA
1
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne %B1
; :::::::::::::::::::::::::::::::::::::::::::::
; Add for Power Management
; - - - - - - - - - - - - - - - - - - - - - - -
tst r10, #0x2 ; Power-Off reset check
beq BringUpWinCE ; Normal Mode Booting
; Recover Process : Starting Point
ldr r1, =GSTATUS2 ; Determine Booting Mode
ldr r10, [r1]
str r10, [r1] ; Clear Booting Mode
; 1. Checksum Calculation saved Data
ldr r5, =SLEEPDATA_BASE_PHYSICAL ; pointer to physical address of reserved Sleep mode info data structure
mov r3, r5 ; pointer for checksum calculation
mov r2, #0
ldr r0, =SLEEPDATA_SIZE ; get size of data structure to do checksum on
40
ldr r1, [r3], #4 ; pointer to SLEEPDATA
and r1, r1, #0x1
mov r1, r1, LSL #31
orr r1, r1, r1, LSR #1
add r2, r2, r1
subs r0, r0, #1 ; dec the count
bne %b40 ; loop till done
ldr r0,=GSTATUS3
ldr r3, [r0] ; get the Sleep data checksum from the Power Manager Scratch pad register
teq r2, r3 ; compare to what we saved before going to sleep
; bne BringUpWinCE ; bad news - do a cold boot - If emergency power off case, normal booting.
bne JumpToRAM ; bad news - do a cold boot - If emergency power off case, normal booting.
b MMUENABLE
JumpToRAM
ldr r2, =0x400000 ; offset into the RAM
ldr r3, =0x30000000 ; add physical base
add r2, r2, r3
mov pc, r2 ; & jump to StartUp address
MMUENABLE
; 2. MMU Enable
ldr r10, [r5, #SleepState_MMUDOMAIN] ; load the MMU domain access info
ldr r9, [r5, #SleepState_MMUTTB] ; load the MMU TTB info
ldr r8, [r5, #SleepState_MMUCTL] ; load the MMU control info
ldr r7, [r5, #SleepState_WakeAddr] ; load the LR address
nop
nop
nop
nop
nop
; if software reset
; b BringUpWinCE
; b CPUPowerReset
; wakeup routine
1
mcr p15, 0, r10, c3, c0, 0 ; setup access to domain 0
mcr p15, 0, r9, c2, c0, 0 ; PT address
mcr p15, 0, r0, c8, c7, 0 ; flush I+D TLBs
mcr p15, 0, r8, c1, c0, 0 ; restore MMU control
; 3. Jump to Kernel Image's fw.s(Awake_address)
mov pc, r7 ; & jump to new virtual address (back up Power management stack)
nop
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 - also FIQ
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 ; 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 ; 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 ; 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 ; Enter SYS mode, no interrupts
msr cpsr, r1
ldr sp, [r2], #4
ldr lr, [r2]
;mov r1, #Mode_SVC:OR:I_Bit ; Enter SVC mode, no interrupts - FIQ is available
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
我是通过按键产生一个EINT0的外部中断来唤醒的。
现象:当按键盘时,CPU的核电压起来了,说明CPU已经被唤醒了,但是并不如我设想的那样,进入到BOOT中
问题:1.在准备挂起的过程当中(即最后一步前),需不需要设置PC指针,指向BOOT的起始地址。
2.我设置了PC指针,发现并没有把CPU给挂起,正如问题1那样,如果不设,唤醒能自动加载BOOT吗?
请各位同仁不吝赐教.
MSN:liyong983@163.com |
|