📄 arm1136-dormantmode-example_c.s
字号:
;*******************************************************************************
;*
;* The confidential and proprietary information contained in this file may
;* only be used by a person authorised under and to the extent permitted
;* by a subsisting licensing agreement from ARM Limited.
;*
;* (C) COPYRIGHT 2007 ARM Limited.
;* ALL RIGHTS RESERVED
;*
;* This entire notice must be reproduced on all copies of this file
;* and copies of this file may only be made by a person if such person is
;* permitted to do so under the terms of a subsisting license agreement
;* from ARM Limited.
;*
;* Config to simulate the dormant mode
;* ===================================
;*
;* Origin: CPU Validation
;* $Revision: 1.14 $
;* $Date: Fri Nov 2 10:39:21 2007 $
;*
;*******************************************************************************
AREA dormantMode, CODE
;*******************************************************************************
;* Configuration and constants
;*******************************************************************************
; Change the following definition to the address at the start of your dormant
; mode state saving address space. This memory region should be defined as
; write back for best performance. This address should be flat mapped, so that
; the physical and virtual addresses are the same.
DORMANTSTORE EQU dormantstore_area
; Specify whether the Main TLB RAM remains powered up in Dormant mode
GBLL TLB_POWERED
TLB_POWERED SETL {TRUE} ; {TRUE} or {FALSE}
; Specify whether Dormant mode entry/exit code uses its own static memory setup
; i.e. after saving memory setup state it changes to a memory setup which can
; be statically restored from constants after reset, in which case the original
; memory setup state can be saved into cache
GBLL DM_STATICMEM
DM_STATICMEM SETL {FALSE} ; {TRUE} or {FALSE}
; Aliases for mode encodings - do not change
MODE_USR EQU 0x10
MODE_FIQ EQU 0x11
MODE_IRQ EQU 0x12
MODE_SVC EQU 0x13
MODE_ABT EQU 0x17
MODE_UND EQU 0x1B
MODE_SYS EQU 0x1F
;*******************************************************************************
;* Dormant mode entry
;*******************************************************************************
; This code assumes that the operating system will make the decision to
; enter dormant mode. The operating system must call this dormant mode
; entry code in System mode using an instruction of the form:
; BL dormant_entry
; as the dormant mode exit code returns using a MOV pc,r14 instruction. The
; entry code assumes that it is in System mode and does not check for this.
; The dormant mode entry code saves all required state in the correct order.
; You must make some modifications to this code as explained by the comments
; within it. The most important change is to add your system-dependent method
; of setting up your system's power controller so that it will enter dormant
; mode when it sees the macrocell output STANDBYWFI go high. Full details
; are given in the comments.
; Information about the dormant mode exit code is given at the start of that
; code.
EXPORT dormant_entry
dormant_entry
; Assume we are in System mode.
; Save general purpose registers (SYS) and CPSR
STR r0,r0_store ; Temporary store
LDR r0,=DORMANTSTORE ; Get state save addr
STR r1,[r0,#4] ; Save r1
MOV r1,r0 ; Get state save addr
LDR r0,r0_store ; Restore r0
STR r0,[r1],#8 ; Save r0
STMIA r1!,{r2-r14} ; Save r2-r14 (SYS/USR)
MRS r0,CPSR ; Get CPSR
STR r0,[r1],#4 ; Save CPSR
; Disable interrupts until mode regs & SPSRs are saved
; Also change to FIQ mode for next section
CPSID if,#MODE_FIQ
; Save FIQ mode registers and SPSR
STMIA r1!,{r8-r14} ; Save r8-r14 (FIQ)
MRS r0,SPSR ; Get SPSR
STR r0,[r1],#4 ; Save SPSR
; Save IRQ mode registers and SPSR
CPS #MODE_IRQ
STMIA r1!,{r13-r14} ; Save r13-r14 (IRQ)
MRS r0,SPSR ; Get SPSR
STR r0,[r1],#4 ; Save SPSR
; Save Abort mode registers and SPSR
CPS #MODE_ABT
STMIA r1!,{r13-r14} ; Save r13-r14 (Abort)
MRS r0,SPSR ; Get SPSR
STR r0,[r1],#4 ; Save SPSR
; Save Supervisor mode registers and SPSR
CPS #MODE_SVC
STMIA r1!,{r13-r14} ; Save r13-r14 (SVC)
MRS r0,SPSR ; Get SPSR
STR r0,[r1],#4 ; Save SPSR
; Save Undefined mode registers and SPSR
CPS #MODE_UND
STMIA r1!,{r13-r14} ; Save r13-r14 (Undef)
MRS r0,SPSR ; Get SPSR
STR r0,[r1],#4 ; Save SPSR
; Return to System mode and enable interrupts
CPSIE aif,#MODE_SYS
; Save TLB lockdown register, then force page table walks to
; write into the associative region of the TLB, to avoid
; changing the lockdown region
MRC p15,0,r2,c10,c0,0 ; TLB Lockdown
STR r2,[r1],#4 ; Save
BIC r2,r2,#1 ; Clear P bit
MCR p15,0,r2,c10,c0,0 ; Write TLB Lockdown
; If Dormant mode has its own static memory setup, save memory system control
; registers then change to the static memory setup.
; This is only worth doing if both the original memory setup and the static
; setup enable write-back into the data cache.
[ DM_STATICMEM
MRC p15,0,r2,c1,c0,0 ; Control
MRC p15,0,r3,c2,c0,0 ; TTBR0
MRC p15,0,r4,c2,c0,1 ; TTBR1
MRC p15,0,r5,c2,c0,2 ; TTBCR
MRC p15,0,r6,c3,c0,0 ; DAC
MRC p15,0,r7,c13,c0,0 ; FCSE PID
MRC p15,0,r8,c13,c0,1 ; Context ID
STMIA r1!,{r2-r8} ; Save
MRC p15,0,r2,c15,c2,0 ; Data Mem Remap
MRC p15,0,r3,c15,c2,1 ; Instr Mem Remap
MRC p15,0,r4,c15,c2,2 ; DMA Mem Remap
MRC p15,0,r5,c15,c2,4 ; PP Mem Remap
MRC p15,7,r6,c15,c0,0 ; Cache Debug Control
MRC p15,7,r7,c15,c1,0 ; TLB Debug Control
MRC p15,0,r8,c9,c0,0 ; D Cache Lockdown
MRC p15,0,r9,c9,c0,1 ; I Cache Lockdown
STMIA r1!,{r2-r9} ; Save
; ARM1136 rev1 has two extra memory system registers
MRC p15,0,r0,c0,c0,0 ; Read ID code
ANDS r0,r0,#0xF << 20 ; Is this a rev0 device?
BEQ rev0_skip1 ; Yes: skip
MRC p15,0,r2,c10,c2,0 ; Primary Region Remap
MRC p15,0,r3,c10,c2,1 ; Normal Memory Remap
STMIA r1!,{r2-r3} ; Save
rev0_skip1
; Now set up the static memory configuration for Dormant mode.
; This may involve changing TTBR regs to use new page tables, or disabling
; the MMU and remapping memory to write-back. If you disable the MMU here,
; write 0x00000000 to the FCSE PID register first.
]
; Note: if you do not have a separate static memory setup for dormant mode,
; the above state will be saved later after disabling the caches & MMU.
; Save CP15 control & fault registers
MRC p15,0,r2,c5,c0,0 ; DFSR
MRC p15,0,r3,c5,c0,1 ; IFSR
MRC p15,0,r4,c6,c0,0 ; FAR
MRC p15,0,r5,c6,c0,1 ; IFAR
MRC p15,0,r6,c1,c0,1 ; Auxiliary Control
MRC p15,0,r7,c1,c0,2 ; Coproc Access Control
STMIA r1!,{r2-r7} ; Save
; ARM1136 rev1 has three extra thread/process ID registers
MRC p15,0,r0,c0,c0,0 ; Read ID code
ANDS r0,r0,#0xF << 20 ; Is this a rev0 device?
BEQ rev0_skip2 ; Yes: skip
MRC p15,0,r2,c13,c0,2 ; User R/W Thread/PID
MRC p15,0,r3,c13,c0,3 ; User RO Thread/PID
MRC p15,0,r4,c13,c0,4 ; Priv Only Thread/PID
STMIA r1!,{r2-r4} ; Save
rev0_skip2
; If we have a DMA, save DMA state (both channels) and
; stop running and queued DMA channels.
; If either channel has stopped with an error, we cannot
; restore this error status. This code will abandon entry to
; dormant mode and return. Alternatively you can change this code
; to process the DMA error(s) and continue.
; This code checks if the DMA is present by reading the DMA ID
; & Status reg. If your code runs on a system that never has
; an internal DMA engine you can remove this code section.
MRC p15,0,r0,c11,c0,0 ; Read DMA ID & Status
CMP r0,#3 ; Do we have a DMA?
BNE no_DMA ; No - skip DMA save
MRC p15,0,r2,c11,c1,0 ; User Accessibility Reg
MRC p15,0,r3,c11,c2,0 ; Channel Number
MOV r0,#0
MCR p15,0,r0,c11,c2,0 ; Select Channel 0
MRC p15,0,r4,c11,c8,0 ; DMA channel status
CMP r4,#3 ; Is there an error?
BHI quit_dormant_entry ; Yes: quit
MCR p15,0,r0,c11,c3,0 ; No: stop the channel
MOV r0,#1
MCR p15,0,r0,c11,c2,0 ; Select Channel 1
MRC p15,0,r10,c11,c8,0 ; DMA channel status
CMP r10,#3 ; Is there an error?
BHI quit_dormant_entry ; Yes: quit
MCR p15,0,r0,c11,c3,0 ; No: stop the channel
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -