timer0.src

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· SRC 代码 · 共 345 行

SRC
345
字号
;-------------------------------------------------------------------------------
;
;   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
;   ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
;   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
;   PARTICULAR PURPOSE.
;   Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.
;   
;-------------------------------------------------------------------------------
        .list OFF
        .include "kxshx.h"
        .list ON

        .aif SH_CPU eq h'40
        .include "sh4.inc"
        .aelse
        .include "sh3.inc"
        .aendi
		.include "aspen.inc"

;
; since SHx assembler doesn't take C style defines, we can't automatically
; determine which version we are by include "bldver.h".
; If you are compiling this file for SHx, make sure you change the following
; line to:
CE_MAJOR_VER: .equ    3
;
; CE_MAJOR_VER:   .equ    4

CLOCK_LEDS: .equ 0

; Note: this needs to match RESCHED_PERIOD in timer.h
RESCHED_PERIOD: .equ  1         ; Reschedule period in ms

SYSINTR_NOP: .equ 0
SYSINTR_RESCHED: .equ 1
SYSINTR_DEVICES: .equ 8
SYSINTR_TIMING: .equ SYSINTR_DEVICES+2

        .aif CLOCK_LEDS eq h'2
LEDState .data.l 1
         .data.l 1
        .aendi

;
;   ODO Platform LED addresses:
;

;HKEEP_FPGA_REGS_BASE:   .equ    h'A4000000  ; housekeeping FPGA reg base
;LED_ALPHA:              .equ    HKEEP_FPGA_REGS_BASE+h'00060000
;LED_DISCRETE:               .equ    HKEEP_FPGA_REGS_BASE+h'00040000

        .import _CurMSec
        .import _CurTicks
        .import _wNumInterrupts
        .import _dwSPC
        .import _dwIsrTime1
        .import _dwIsrTime2
        .import _fIntrTime
        .import _dwReschedIncrement
        .import _OEMClockFreq
        .import _dwIntrTimeCountdownRef
        .import _dwIntrTimeCountdown
        .import _dwPerfCountHigh
    .aif CE_MAJOR_VER == h'0003
        .import _DiffMSec
        .import _ticksleft
        .import _dwSleepMin
        .import _dwPreempt
    .aelse
        .import _dwReschedTime
    .aendi
;-------------------------------------------------------------------------------
; We make this a MACRO because it needs to be called from inside the
; ISR and we don't want to waste a function call to do it.
;
; Value is returned in R0
;-------------------------------------------------------------------------------
        .macro  PERFCOUNT_MACRO 
        
        mov     #TMU_REGBASE, r2           ; (r2) = ptr to timer unit registers
        mov.l   @(TMU_TCOR0_OFFSET,r2), r0      ; (r0) = Timer 0 constant
        mov.l   @(TMU_TCNT0_OFFSET,r2), r2      ; (r2) = Timer 0 count
        sub     r2, r0                  ; (r0) = Constant - count (ticks elapsed)
        
        .endm

;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
        LEAF_ENTRY _Timer0ISR
        
        .aif CLOCK_LEDS eq 1
        mov     #LED_ALPHA, r1         ; (r1) = LED address
        mov.l   @r1, r0
        add     #-1,r0
        and     #h'ff,r0                ; restrict change to lights only
        mov.l   r0, @r1                 ; put it in lights
        .aendi

        .aif CLOCK_LEDS eq 2
        mov.l   #LEDState, r1
        mov.l   @r1, r0
        mov.l   @(4,r1),r3
        cmp/EQ  #1, r0
        bf      LED1
        mov     #0, r1
        shll2   r3
        shll2   r3
        cmp/EQ  r3,r1
        bf      LED2
        mov     #0, r0
        mov     #h'10000000, r3
        bra     LED2
LED1:
        mov     #0, r1
        shlr2   r3
        shlr2   r3
        cmp/EQ  r3,r1
        bf      LED2
        mov     #1, r0
        mov     #h'1, r3
LED2:
        mov.l   #LEDState, r1
        mov.l   r0, @r1
        mov.l   r3, @(4,r1)
        mov     #LED_ALPHA, r1         ; (r1) = LED address
        mov.l   r3, @r1                 ; put it in lights
        .aendi
        
        ;-------------------------------------------------------
        ; Check for IntrTime measurements (COMMON)
        ;
        mov     #_fIntrTime, r1         ; (r1) = ptr to fIntrTime gate
        mov     @r1, r6                 ; (r6) = fIntrTime
        tst     r6, r6
        bt      skip_isrtime1
        
        ;-------------------------------------------------------
        ; Get ISR latency and saved program counter (INTRTIME)
        ;
        PERFCOUNT_MACRO                 ; (r0) = PerfCountSinceTick()
        mov     #_dwIsrTime1, r1
        mov     r0, @r1                 ; dwIsrTime1 = (r0)
                       
        stc     spc, r0
        mov     #_dwSPC, r1
        mov.l   r0, @r1                 ; Save Program Counter
        
        mov     #_wNumInterrupts, r0    ; (r0) = addr of interrupt counter
        mov     @r0, r1                 ; (r1) = interrupt counter
        add     #1, r1                  ; Increment counter
        mov     r1, @r0                 ; Save interrupt counter

skip_isrtime1:                      
        ;-------------------------------------------------------
        ; Clear the timer interrupt (COMMON)
        ;
        mov     #TMU_REGBASE, r1           ; (r1) = ptr to timer unit registers
        mov.w   @(TMU_TCR0_OFFSET,r1), r0
tisr10: and     #h'ff, r0               ; clear timer underflowed flag
        mov.w   r0, @(TMU_TCR0_OFFSET,r1)       ;  & and set new tcr0 value
        mov     #1, r3
        mov.w   @(TMU_TCR0_OFFSET,r1), r0
        shll8   r3                      ; (r3) = 0x100 (underflow bit)
        tst     r3, r0
        bf      tisr10                  ; bit not clear, go clear it again!
        
        ;-------------------------------------------------------
        ; Blink the discrete LED's (COMMON)
        ;
;        mov     #LED_DISCRETE, r1       ; (r1) = LED address
;        mov.l   @r1, r0
;        add     #1,r0
;        and     #h'ff,r0                ; restrict change to lights only
;        mov.l   r0, @r1                 ; put it in lights
        
        ;-------------------------------------------------------
    .aif CE_MAJOR_VER == h'0003
        ; Update CurMSec and DiffMSec (COMMON)
        ;
        mov     #_CurMSec, r2           ; (r2) = ptr to counters
        mov.l   @r2, r3                 ; (r3) = current millisecond count
        mov     #_DiffMSec, r0          ; (r0) = ptr to DiffMSec
        mov.l   @r0, r1                 ; (r1) = millisecond delta
        
        add     #RESCHED_PERIOD, r3
        add     #RESCHED_PERIOD, r1
        
        mov.l   r3, @r2                 ; update current millisecond counter
        mov.l   r1, @r0                 ; update millisecond delta        
    .aelse
        ; Update CurMSec (COMMON)
        ;
        mov     #_CurMSec, r0           ; (r0) = ptr to counters
        mov.l   @r0, r1                 ; (r1) = current millisecond count
        
        add     #RESCHED_PERIOD, r1
        
        mov.l   r1, @r0                 ; update current millisecond counter
    .aendi
        ;-------------------------------------------------------
        ; Update CurTicks (COMMON)
        ;
        mov     #_CurTicks, r0          ; (r0) = ptr to CurTicks
        mov.l   @r0, r2                 ; (r2) = CurTicks lower DWORD
        mov     #_dwReschedIncrement, r3; (r3) = ptr to dwReschedIncrement
        mov.l   @r3, r3                 ; (r3) = number of ticks per resched
        clrt
        addc.l  r3, r2                  ; increment tick count by resched period
        bf/s    nocarry                 ; skip next section if no carry
        mov.l   r2, @r0                 ; update CurTicks lower DWORD
        mov.l   @(4,r0), r2             ; (r2) = CurTicks upper DWORD
        mov     #1, r3                  ; (r3) = 1
        add.l   r3, r2                  ; carry to upper DWORD
        mov.l   r2, @(4,r0)             ; update CurTicks upper DWORD
        
nocarry:        
                
        tst     r6, r6                  ; (r6) = fIntrTime
        bt      normal
        
        ;-------------------------------------------------------
        ; Check the countdown (INTRTIME)
        ;
        mov     #_dwIntrTimeCountdown, r2
        mov     @r2, r0                 ; (r0) = dwIntrTimeCountdown
        add     #-1, r0
        tst     r0, r0
        bf/s    normal
        mov     r0, @r2                 ; dwIntrTimeCountdown--
                
        mov     #_dwIntrTimeCountdownRef, r0
        mov     @r0, r0                 ; (r0) = dwIntrTimeCountdownRef
        mov     r0, @r2                 ; Countdown = Reference
        
        ; Zero wNumInterrupts, which counts interrupts since SYSINTR_TIMING
        mov     #_wNumInterrupts, r0    ; (r0) = addr of interrupt counter
        mov     #0, r1                  ; (r1) = 0
        mov     r1, @r0                 ; Zero interrupt counter
        
        ;-------------------------------------------------------
        ; Get end-of-ISR time. (INTRTIME)
        ;
        PERFCOUNT_MACRO                 ; (r0) = PerfCountSinceTick()
        mov     #_dwIsrTime2, r2
        mov     r0, @r2                 ; dwIsrTime2 = (r0)

        .aif CLOCK_LEDS eq 3
        ;-------------------------------------------------------
        ; Verification of INTRTIMEs with a Logic Analyzer (INTRTIME)
        ;
;Davli
;        mov     #h'A4060014, r2         ; (r1) = Debug LED address
;        mov.l   #h'12340001, r0         ; 
;        mov.l   r0, @r2                 ; Capture on Logic Analyzer
        .aendi
        
        mov     #SYSINTR_TIMING, r0
        rts
        nop
                
        ;-------------------------------------------------------
        ; Normal processing (NORMAL)

    .aif CE_MAJOR_VER == h'0003
        ; (cedar)
        ; (r1) = DiffMSec
        ;
normal: 
        mov     #_ticksleft, r0
        mov     @r0, r0
        cmp/EQ  #0, r0
        bf      doresched

        mov     #_dwSleepMin, r0
        mov     @r0, r0
        cmp/EQ  #0,r0
        bt      part2
        cmp/ge  r0, r1
        bt      doresched
part2:
        mov     #_dwPreempt, r0
        mov     @r0, r0
        cmp/EQ  #0, r0
        bt      noresched
        cmp/ge  r0, r1
        bt      doresched

    .aelse
        ; (dougfir or later)
        ; (r1) = CurMSec
        ;
normal: 
        mov     #_dwReschedTime, r0 ; r0 = &dwReschedTime
        mov     @r0, r0         ; r0 == dwReschedTime
        sub     r1, r0          ; r0 == dwReschedTime - CurMSec
        mov     #0, r2          ; r2 == 0
        cmp/ge  r0, r2          ; (int) (dwReschedTime - CurMSec) <= 0?
        bt      doresched       ;   reschedule if true
    .aendi
noresched:
        rts
        mov     #SYSINTR_NOP, r0

doresched:
        rts
        mov     #SYSINTR_RESCHED, r0    ; must set reschedule flag
        .endf



;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
        LEAF_ENTRY _Timer2ISR
        
        ;-------------------------------------------------------
        ; Clear the timer interrupt
        ;
        mov     #(TMU_REGBASE + TMU_TCR2_OFFSET), r1  ; (r1) = ptr to timer unit registers
        mov.w   @r1, r0
tisr1:  and     #h'ff, r0               ; clear timer underflowed flag
        mov.w   r0, @r1                 ;  & and set new tcr0 value
        mov     #1, r3
        mov.w   @r1, r0
        shll8   r3                      ; (r3) = 0x100 (underflow bit)
        tst     r3, r0
        bf      tisr1                  ; bit not clear, go clear it again!
        
        ;-------------------------------------------------------
        ; Update dwPerfCountHigh
        ;
        mov     #_dwPerfCountHigh, r2   ; (r2) = &dwPerfCountHigh
        mov.l   @r2, r3                 ; (r3) = dwPerfCountHigh
        add     #1, r3
        mov.l   r3, @r2                 ; dwPerfCountHigh++
        
        rts
        mov     #SYSINTR_NOP, r0

        .endf


        .end

⌨️ 快捷键说明

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