⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fw_utils.s_sleep

📁 ARM9基于WINDOWSCE的BSP源代码
💻 S_SLEEP
📖 第 1 页 / 共 3 页
字号:
    adds    r0, r0, #0x20                    ; seg++
    tst     r0, #0x100
    beq     NextLoop
    b       DrainWriteBuffers

; It is ARM926

TestCleanInvalidate
    mrc     p15, 0, r15, c7, c14, 3             ; Test, clean & invalidate D cache
    bne     TestCleanInvalidate
                
; Drain the write buffers

DrainWriteBuffers
    mov     r0, #0                              ; Data SBZ  (R0 = 0)
    mcr     p15, 0, r0, c7, c10, 4              ; Drain Write Buffers


; Disable the MMU, disable & invalidate I Cache
DisableICacheMMU
    mcr     p15, 0, r1, c1, c0, 0               ; Disable I cache & MMU
    mcr     p15, 0, r0, c7, c5, 0               ; Invalidate I Cache
        

            
    mov     pc, r3                              ; Branch to the physical address
    nop
    nop

; MMU is off so we are executing from physical memory addressing


; Reenable I Cache

ReenableICache
    orr     r3, r1, #0x1000                     ; Set the Enable I Cache bit
    mcr     p15, 0, r3, c1, c0, 0               ; Enable I Cache

 IF :DEF: EXAMPLE_MEMCONFIG
    ldr r0, =PHYS_MPMC_CNTL_BASE                      ; Load the MPMC physical base address
  
; Ensure that MPMC is idle 

WaitLoop
    ldr    r2, [r0, #MPMCStatus]            ; Read MPMC status register
    and    r2, r2, #(MPMCStatus_B_Idle)     ; Mask 
    cmp    r2, #(MPMCStatus_B_Idle)         ; Check
    bne    WaitLoop                         ; Keep polling until MPMC is idle and write buffers are empty
 
; MPMC can now enter low-power mode cleanly

    ldr    r3, [r0, #MPMCControl]  
    orr    r3, r3,  #MPMCControl_L_LowPower
    str    r3, [r0, #MPMCControl]

; Set to self-refresh mode

    ldr    r3, [r0, #MPMCDynamicControl]
    orr    r3, r3,  #MPMCDynamicControl_SR_SelfRefresh
    str    r3, [r0, #MPMCDynamicControl]

; Poll the status bit in MPMCStatus register

Poll
    ldr    r2, [r0, #MPMCStatus]             ; Read MPMC status register
    cmp    r2, #MPMCStatus_SA_SelfRefreshMode
    bne    Poll


 ENDIF ; EXAMPLE_MEMCONFIG


; Switch off HCLKSDRAM & MPMCCLK peripheral clocks.
; Leave HCLKSMC & PCLKUART2(UARTDEBUG) enabled.

; Load the System Controller physical base address

;    ldr r0, =PHYS_SC_BASE
;    ldr r2, =(:NOT:SCPerClkEnPhase2)
;    str r2, [r0, #ARM_SCPerDis]
	
     ldr r0, =PHYS_SC_BASE
     ldr r2, =SCPerClkHclkSmc
     str r2, [r0, #ARM_CLKGATED1]
     
     ldr r0, =PHYS_SC_BASE
     ldr r2, =SCPerClkPclkUart2
     str r2, [r0, #ARM_CLKGATED2]
     

; Switch to SLEEP mode and put the core into "Wait for Interrupt" mode 

SleepState
    orr r3, r1, #0x1000             ; Set the Enable I Cache bit

; Workarounds for cacheable code. 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.

    ldr r2, =DisableICache
    and r2, r2, #0x3FC
    cmp r2, #0x3E0

; Clear the control bits to request SLEEP state

    ldr r2, [r0, #ARM_SCCtrl]
    bic r2, r2, #SCCtrlSetDoze:OR:SCCtrlSetSlow:OR:SCCtrlSetNormal
    str r2, [r0, #ARM_SCCtrl]     ; Switch to SLEEP state

    mov    r2, #0                   ; Data SBZ

; 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 low-power mode.
 
    bge WorkAround

; Put the system into low-power state by issuing Disable I Cache and WFI instructions.
 
DisableICache
    mcr p15, 0, r1, c1, c0, 0            ; Disable I cache
    mcr p15, 0, r2, c7, c0, 4            ; Wait for Interrupt

; At this point the platform is fully in the low-power state

; Get here after receiving an interrupt

    mcr p15, 0, r3, c1, c0, 0               ; Enable I cache

; Set VIC physical address

    ldr r2, =PHYS_VIC_BASE

; Check BATOK signal

    ldr     r3, [r0, #ARM_SCSysStat]
    tst     r3 , #SCSysStatBatOk      ; Test BATOK
    bne     BatOK                     ; BATOK so Branch to next intialising section

    b   NotBatOK


; Put the system into low-power state by issuing Disable I Cache and WFI instructions.

; This is the second set of code sequence to put ARM926EJ-S into low-power mode,
; which is offset from the first one by 8 words.

    
WorkAround
    mcr     p15, 0, r1, c1, c0, 0    ; Disable I cache
    mcr     p15, 0, r2, c7, c0, 4    ; Wait for Interrupt

; At this point the platform is fully in the low-power state
; Get here after receiving an interrupt

    mcr     p15, 0, r3, c1, c0, 0    ; Enable I cache

; Set VIC physical address

    ldr     r2, =PHYS_VIC_BASE

; Check BATOK signal

    ldr     r3, [r0, #ARM_SCSysStat]
    tst     r3 , #SCSysStatBatOk      ; Test BATOK
        
    bne BatOK

; Clear any wake up interrupt sources here as bettery is not okay

NotBatOK
    ldr r3, [r2, #ARM_VICIRQStatus]

    ; NOTE: Update this bitmask
    tst r3, #0                ; Bitmask wake up sources
    beq SleepState            ; Not interrupt

; Clear interrupt on VIC

    ldr r3, [r2, #ARM_VICVectAddr]
    str r3, [r2, #ARM_VICVectAddr]

; Clear interrupts here

    ; NOTE: Add interrupt clearing code here

; Now return to sleep
    b       SleepState 

BatOK

 ; Check if Power Fail signal is still active
    
    ldr r2, [r2, #ARM_VICRawIntr]
    tst r2, #IRQ_VIC_PWRFAIL
    bne NotBatOK             ; Power Fail interrupt is pending. Check for interrupt and go to SLEEP again */
    
; Switch to the NORMAL state

    bic r3, r3, #SCCtrlSetDoze:OR:SCCtrlSetSlow:OR:SCCtrlSetNormal
    orr    r3, r3, #SCCtrlSetNormal
    str    r3, [r0, #ARM_SCCtrl]    ; Switch to NORMAL state

; Now check if we are in NORMAL state, and BATOK is set

    mov r2, #COUNTER                            ; Set counter

CheckNormal
    ldr     r3, [r0, #ARM_SCCtrl]

    and    r3, r3, #(SCCtrlModeStatusMask)      ; Mask ModeStatus bits 
    cmp    r3, #(SCCtrlStatusNormal)            ; Test ModeNormal Bits
    bne    RetryCheck

    ldr r3, [r0, #ARM_SCSysStat]
    tst    r3, #SCSysStatBatOk                  ; Test BATOK
    bne    StatusOK                             ; BATOK so Branch to next intialising section

RetryCheck

    subs    r2, r2, #1              ; Counter--
    bne     CheckNormal
    b       SleepState              ; Go to SLEEP again

 ; Clocks are stable and chip is in NORMAL state

StatusOK

    ; Reenable the previously enabled peripheral clocks
    str     r4, [r0, #ARM_CLKGATED1] ;
    str     r5, [r0, #ARM_CLKGATED2] 

; Check peripheral clocks have been setup

CheckClocks
    ldr r1, [r0, #ARM_CLKGATED1] ;
    cmp r1, r4
    bne CheckClocks
    
    ldr r1, [r0, #ARM_CLKGATED2] ;
    cmp r1, r5
    bne CheckClocks

; Wait until the peripheral clocks are running

;CheckClocksRunning
;    ldr r1, [r0, #ARM_SCPerStat] ;
 ;   cmp r1, r4
 ;   bne CheckClocksRunning

 IF :DEF: EXAMPLE_MEMCONFIG
; Load the MPMC physical base address

    ldr r0, =PHYS_MPMC_CNTL_BASE

; Re-enable SDRAM, clear the self-refresh bit

    ldr    r1, [r0, #MPMCDynamicControl]
    bic    r1, r1, #MPMCDynamicControl_SR_SelfRefresh
    str    r1, [r0, #MPMCDynamicControl]

; Perform extra-refresh cycles to allow SDRAM to exit self-refresh mode cleanly. 
; Read MPMCRefreshRegister, save the value temporarily in R2

    ldr    r2, [r0, #MPMCDynamicRefresh]

; Reprogram it to 0x1

    mov    r1, #1
    str    r1, [r0, #MPMCDynamicRefresh]

; Wait 66000 HCLK cycles

    ldr r3, =PHYS_CT2_BASE;
    
; Configure Timer 2 i.e. the third timer
; Enable the timer in wrapping mode, 32-bit counter, no prescale, free run mode
    mov r1, #(TIMER_ENABLE :OR: TIMER_MODE_32BIT)

; Store in Timer2Control register

    str     r1, [r3, #Timer0Control] ;
    mov     r1, #HCLK_66000             ; Wait 66000 HCLK cycles
    str     r1, [r3, #Timer0Load]       ; Store the wait time

TimerWait
    ldr     r1, [r3, #Timer0Value]   ; Load the current timer value
    cmp     r1, #0
    bgt     TimerWait

; Clear and disable the timer

    mov r1, #0
    str r1, [r3, #Timer0Control]        ; Clear Timer2Control
    str r1, [r3, #Timer0Load]           ; Clear Timer2Load
    
; Restore MPMCRefreshRegister
    str     r2, [r0, #MPMCDynamicRefresh] ;

 ENDIF ; EXAMPLE_MEMCONFIG

 ; Enable the MMU, disable & invalidate I Cache

    mov     r0, #0                      ; Data SBZ
    mrc     p15, 0, r1, c1, c0, 0       ; Read the current MMU control register status
    orr     r1, r1, #1                  ; Set the MMU Enable bit
    bic     r2, r1, #0x1000             ; Clear the Enable I Cache bit
    mcr     p15, 0, r2, c1, c0, 0       ; Disable I cache, enable MMU
    mcr     p15, 0, r0, c7, c5, 0       ; Invalidate I Cache

; Branch to the virtual address

    mov     pc, lr
    nop
    nop

; Executed from the virtual address

EnableCaches
    orr     r1, r1, #4              ; Set the Enable D Cache bit
    mcr     p15, 0, r1, c1, c0, 0   ; Enable I & D Caches

    ldmfd   sp!, {r0,r1,r4,r5,lr}      ; Load the saved values from the stack

    mcr     p15, 0, r1, c13, c0, 0  ; Write the previous PID value back

; Enable interrupts

    and     r0, r0, #0xc0
    mrs     r1, cpsr
    bic     r1, r1, #0xc0
    orr     r0, r0, r1
    msr     cpsr, r0                ; Restore FIQ & IRQ Enable bits
    mov pc, lr

 ENDIF ; IF EBOOT 

        ENTRY_END

 ENDIF ; EXAMPLE_POWERDOWN
 
        END

; EOF fw_utils.s

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -