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

📄 os_cpu_a.asm

📁 ucos_ii 在Z80系列单片机上的移植
💻 ASM
字号:
;********************************************************************************************************
;                                                uC/OS-II
;                                          The Real-Time Kernel
;
;                          (c) Copyright 1992-2000, Jean J. Labrosse, Weston, FL
;                                          All Rights Reserved
;
;                                           ZiLOG eZ80-Specific code
;
; File   : OS_CPU_A.ASM
; By           : Jean J. Labrosse
; Revised      : Douglas Beattie Jr. (13-JAN-2004)
; Port Version : V2.00 (for uC/OS-II V2.52 or higher)
;********************************************************************************************************

    .ASSUME ADL=1

CPUFREQ EQU 50000000	;50_MHz crystal
OS_TICKS_PER_SEC EQU 20	;this should match OS_TICKS_PER_SEC in OS_CFG.H

MS_TIMER_INT EQU 1 ;Set to '1' to enable millisecond timer ISR
            
            PUBLIC  _OSStartHighRdy
            PUBLIC  _OSCtxSw
            PUBLIC  _OSIntCtxSw
            PUBLIC  _OSTickISR

			PUBLIC _tick_timer_start
			PUBLIC _ms_timer_start
			PUBLIC _init_tick_timer
			PUBLIC _init_ms_timer

            EXTERN  _OSTCBCur
            EXTERN  _OSTCBHighRdy
            EXTERN  _OSTaskSwHook
            EXTERN  _OSPrioHighRdy
            EXTERN  _OSPrioCur
            EXTERN  _OSRunning
            EXTERN  _OSIntNesting
            EXTERN  _OSTimeTick
            EXTERN  _OSIntExit

    .INCLUDE "eZ80F91.inc"

	.ASSUME ADL=1

;*********************************************************************************************************
;                                          START MULTITASKING
;                                      void OSStartHighRdy(void)
;*********************************************************************************************************

_OSStartHighRdy:
            NOP

            ; OSTaskSwHook();
            CALL   _OSTaskSwHook

            ; OSRunning = TRUE;
            LD     A,1
            LD    (_OSRunning),A

            ; SP = OSTCBHighRdy->OSTCBStkPtr;
            LD HL,(_OSTCBHighRdy)
            LD HL,(HL)
            LD     SP,HL   

            ; Pop task's registers
            POP    IY                                 
            POP    IX
            EX     AF,AF' 
            EXX 
            POP    HL 
            POP    DE 
            POP    BC 
            POP    AF
            EX     AF,AF' 
            EXX 
            POP    HL 
            POP    DE 
            POP    BC 
            POP    AF

            ; Run task
			;EI ;;<<<
            RETI

;*********************************************************************************************************
;                                PERFORM A CONTEXT SWITCH (From task level)
;          void OSCtxSw(void)
;*********************************************************************************************************

_OSCtxSw:
            PUSH   AF                                 ; Save current task's context
            PUSH   BC
            PUSH   DE
            PUSH   HL                                 
            EX     AF,AF'                             
            EXX 
            PUSH   AF                                 
            PUSH   BC
            PUSH   DE
            PUSH   HL                                 
            EX     AF,AF'                             
            EXX 
            PUSH   IX
            PUSH   IY

            ;OSTCBCur->OSTCBStkPtr = StackPointer;
            LD     HL,0
            ADD    HL,SP
            EX     DE,HL
            LD     HL,(_OSTCBCur)
            LD     (HL),DE

            ;CONTINUE WITH CONTEXT SWITCH...


;*********************************************************************************************************
;                                PERFORM A CONTEXT SWITCH (From an ISR)
;                                        void OSIntCtxSw(void)
;*********************************************************************************************************

_OSIntCtxSw:
            ; OSTaskSwHook();
            CALL   _OSTaskSwHook

            ; OSPrioCur = OSPrioHighRdy;
            LD     A,(_OSPrioHighRdy)                  
            LD     (_OSPrioCur),A             

            ; OSTCBCur = OSTCBHighRdy;
            LD     HL,(_OSTCBHighRdy)                  
            LD     (_OSTCBCur),HL                       

            ; SP = OSTCBHighRdy->OSTCBStkPtr;
            LD HL,(HL)
            LD     SP,HL                               

            ; Restore task's context
            POP    IY                                 
            POP    IX
            EX     AF,AF' 
            EXX 
            POP    HL 
            POP    DE 
            POP    BC 
            POP    AF
            EX     AF,AF' 
            EXX 
            POP    HL 
            POP    DE 
            POP    BC 
            POP    AF

            ; Return to new task
			;EI ;;<<<
            RETI                                      

;*********************************************************************************************************
;                                              TICK ISR 
;                                        void OSTickISR (void)
;
; Notes: 1) This implementation assumes that the TICK interrupt will be generated by a TIMER
;        2) Don't forget to clear the interrupt source
;*********************************************************************************************************

_OSTickISR:
            PUSH    AF                                ; Save registers
            PUSH    BC
            PUSH    DE
            PUSH    HL                                 
            EX      AF,AF' 
            EXX 
            PUSH    AF
            PUSH    BC
            PUSH    DE
            PUSH    HL                                 
            EX      AF,AF' 
            EXX 
            PUSH    IX                                  
            PUSH    IY
;
            ; Notify uC/OS-II about ISR
            ;OSIntNesting++
            LD  HL,_OSIntNesting                  
            LD  A,(HL)
            INC A
            LD (HL),A

            ; if (OSIntNesting == 1)
            CP 1
            JR NZ,$F
            
            ;   OSTCBCur->OSTCBStkPtr = StackPointer
            LD     HL,0
            ADD    HL,SP
            EX     DE,HL
            LD     HL,(_OSTCBCur)
            LD     (HL),DE

            ;
; Clear Timer Interrupt HERE!
$$
    IN0 A,(TMR2_IIR)   ; Clear timer interrupt flag


;>>>> Optionally re-enable interrupts for higher priority devices
            ;EI

            CALL    _OSTimeTick                        ; Handle TICK interrupt
;
            CALL    _OSIntExit                         ; Tell uC/OS-II about end of ISR

	;??re-enable tick timer
    IN0 A,(TMR2_CTL)    ; read Timer 2 Control Register
    OR  01h             ; just in case, timer activate
    OUT0 (TMR2_CTL),A   ; write Timer 2 Control Register

            POP    IY                                 ; Restore task's context
            POP    IX
            EX     AF,AF' 
            EXX 
            POP    HL 
            POP    DE 
            POP    BC 
            POP    AF
            EX     AF,AF' 
            EXX 
            POP    HL 
            POP    DE 
            POP    BC 
            POP    AF
;
            EI
            RETI                                      ; Return to interrupted task

;*********************************************************************************************************
;                                              YOUR ISR 
;                                         void ???ISR (void)
;
; Notes  : 1) Don't forget to clear the interrupt source
;*********************************************************************************************************

 comment ~

YourISR:
            PUSH    AF                                ; Save registers
            PUSH    BC
            PUSH    DE
            PUSH    HL                                 
            EX      AF,AF' 
            EXX 
            PUSH    AF
            PUSH    BC
            PUSH    DE
            PUSH    HL                                 
            EX      AF,AF' 
            EXX 
            PUSH    IX                                  
            PUSH    IY
;
            ; Notify uC/OS-II about ISR
            ;OSIntNesting++
            LD  HL,_OSIntNesting                  
            LD  A,(HL)
            INC A
            LD (HL),A

            ; if (OSIntNesting == 1)
            CP 1
            JR NZ,$F
            
            ;   OSTCBCur->OSTCBStkPtr = StackPointer
            LD     HL,0
            ADD    HL,SP
            EX     DE,HL
            LD     HL,(_OSTCBCur)
            LD     (HL),DE

            ;
;
;           CALL    YourISRHandler                     
;------------------------------------------------------------
;  clear interrupt source;

;------------------------------------------------------------
            CALL    _OSIntExit                      
;
            POP    IY                                 ; Restore task's context
            POP    IX
            EX     AF,AF' 
            EXX 
            POP    HL 
            POP    DE 
            POP    BC 
            POP    AF
            EX     AF,AF' 
            EXX 
            POP    HL 
            POP    DE 
            POP    BC 
            POP    AF
;
			EI
			RETI                                      ; Return to interrupted task
;
 ~ endcomment

    PUBLIC _prt_1_isr
 IF MS_TIMER_INT
;#################################################################
ms_timer_ISR:
_prt_1_isr:
    PUSH AF
    IN0 A,(TMR1_IIR)   ; Clear timer interrupt flag
	PUSH HL
    LD HL,(_ms_ticks)
    INC HL
    LD (_ms_ticks),HL
	POP HL
    IN0 A,(TMR1_CTL)    ; read Timer 4 Control Register
    OR  01h             ; just in case, timer activate
    OUT0 (TMR1_CTL),A   ; write Timer 4 Control Register
	POP AF
    EI
    RETI

ms_timer_ISR_size EQU $-ms_timer_ISR

;#################################################################
  ELSE
_prt_1_isr:
  ENDIF

NULLINT ;;RET
        NOP
        EI
        RETI

;*********************************************************************************************************
; Six timers...
; Timer 0: 
; Timer 1: RTOS 'tick' heartbeat
; Timer 2: Reserved, not used
; Timer 3: Reserved, not used
; Timer 4: Reserved, not used
; Timer 5: millisecond-resolution timer

_tick_timer_start:
	LD A,01h			;INTs for end-of-count
    OUT0  (TMR2_IER),A  ; set Interrupt-Enable Register
    IN0 A,(TMR2_CTL)    ; read Timer 2 Control Register
    OR  01h             ; INTs on, timer activate
    OUT0 (TMR2_CTL),A    ; write Timer 2 Control Register
    RET

_ms_timer_start:
 IF MS_TIMER_INT
	LD A,01h			;INTs for end-of-count
    OUT0  (TMR1_IER),A  ; set Interrupt-Enable Register
    IN0 A,(TMR1_CTL)    ; read Timer 1 Control Register
    OR  01h             ; INTs on, timer activate
    OUT0 (TMR1_CTL),A    ; write Timer 1 Control Register
  ELSE
    NOP
  ENDIF
    RET


_init_tick_timer:
TICK_DIVISOR EQU ((CPUFREQ/16)/OS_TICKS_PER_SEC)  ;tick divisor
	LD  A,10010100b  ; PHI divide-by-64, continuous.
                      ; INTs off, not yet running
    OUT0 (TMR2_CTL),A    ; write Timer 2 Control Register
    LD  A,HIGH(TICK_DIVISOR)
    OUT0  (TMR2_RR_H),A  ; set Reload Register, MSB
    LD  A,LOW(TICK_DIVISOR)
    OUT0  (TMR2_RR_L),A  ; set Reload Register, LSB

    RET


_init_ms_timer:

 IF MS_TIMER_INT

; ********************************************************
; **   Set up a 10-microsecond-resolution timer on TMR1
; **   with interrupts, this will produce 100,000 INTs/sec.
; **   The corresponding ISR simply increments a 24-bit
; **   variable, for "current milliseconds elapsed" value.
;

; prescale=16
MS_DIVISOR_10u EQU ((CPUFREQ/16)/100000)  ;10-microsecond divisor

    LD  A,10001100b  ; PHI/16, reload, continuous,
                      ; INTs off, not yet running
    OUT0 (TMR1_CTL),A    ; write Timer 4 Control Register
    LD  A,HIGH(MS_DIVISOR_10u)
    OUT0  (TMR1_RR_H),A  ; set Reload Register, MSB
    LD  A,LOW(MS_DIVISOR_10u)
    OUT0  (TMR1_RR_L),A  ; set Reload Register, LSB

 ELSE

MS_DIVISOR EQU ((CPUFREQ/16)/2000)  ;milliseconds divisor

 ENDIF

    RET


  SEGMENT BSS
  PUBLIC _ms_ticks
_ms_ticks:
  DS 3
;*********************************************************************************************************

⌨️ 快捷键说明

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