📄 os_cpu_a.asm
字号:
;********************************************************************************************************
; uC/OS-II
; The Real-Time Kernel
;
; (c) Copyright 2002, Micrium, Inc., Weston, FL
; All Rights Reserved
;
; TI TMS320F2812
;
;
; File : OS_CPU_A.S43
; By : Jian Chen (yenger@hotmail.com)
; Jean J. Labrosse
;********************************************************************************************************
;********************************************************************************************************
; MACRO DEFINITIONS
;********************************************************************************************************
PUSHALL .MACRO
PUSH AR1H:AR0H ; 32-bit
PUSH XAR2 ; 32-bit
PUSH XAR3 ; 32-bit
PUSH XAR4 ; 32-bit
PUSH XAR5 ; 32-bit
PUSH XAR6 ; 32-bit
PUSH XAR7 ; 32-bit
PUSH XT ; 32-bit
PUSH RPC
.ENDM
POPALL .MACRO
POP RPC
POP XT
POP XAR7
POP XAR6
POP XAR5
POP XAR4
POP XAR3
POP XAR2
POP AR1H:AR0H
.ENDM
;********************************************************************************************************
; PUBLIC AND EXTERNAL DECLARATIONS
;********************************************************************************************************
.REF _OSIntExit
.REF _OSIntNesting
.REF _OSISRStkPtr
.REF _OSPrioCur
.REF _OSPrioHighRdy
.REF _OSRunning
.REF _OSTCBCur
.REF _OSTCBHighRdy
.REF _OSTaskSwHook
.REF _OSTimeTick
.DEF _OSCtxSw
.DEF _OSIntCtxSw
.DEF _OSStartHighRdy
.DEF _Timer2_Isr
.DEF _OSTaskStkInit
;********************************************************************************************************
; START HIGHEST PRIORITY READY TASK
;
; Description: This function is called by OSStart() to start the highest priority task that is ready to run.
;
; Note : OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;********************************************************************************************************
.TEXT ; Program code
_OSStartHighRdy
LCR #_OSTaskSwHook
MOV DP,#_OSRunning ;OSRunning = 1
MOV @_OSRunning,#01H
MOV *(0:_OSISRStkPtr),@SP ;OSISRStkPTR = SP
MOV DP,#_OSTCBHighRdy
MOVZ AR4,@_OSTCBHighRdy ;SP = OSTCBHighRdy
MOV AL,*XAR4
MOV @SP,AL
POPALL ;pop all registers
IRET ;emulate return from interrupt
;********************************************************************************************************
; TASK LEVEL CONTEXT SWITCH
;
; Description: This function is called by OS_Sched() to perform a task level context switch.
;
; Note : OSCtxSw() MUST:
; a) Save the current task's registers onto the current task stack
; b) Save the SP into the current task's OS_TCB
; c) Call OSTaskSwHook()
; d) Copy OSPrioHighRdy to OSPrioCur
; e) Copy OSTCBHighRdy to OSTCBCur
; f) Load the SP with OSTCBHighRdy->OSTCBStkPtr
; g) Restore all the registers from the high priority task stack
; h) Perform a return from interrupt
;********************************************************************************************************
_OSCtxSw
PUSHALL ; push all registers
MOV DP,#_OSTCBCur
MOVZ AR4,@_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP
MOV AL,@SP
MOV *XAR4,AL
LCR #_OSTaskSwHook
MOV AL,*(0:_OSPrioHighRdy) ; OSPrioCur = OSPrioHighRdy
MOV *(0:_OSPrioCur),AL
MOV DP,#_OSTCBHighRdy
MOVZ AR4,@_OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy
MOV *(0:_OSTCBCur),AR4
MOV AL,*XAR4
MOV @SP,AL ; SP = OSTCBHighRdy->OSTCBStkPtr
POPALL ; pop all registers
IRET ; return from interrup
;********************************************************************************************************
; ISR LEVEL CONTEXT SWITCH
;
; Description: This function is called by OSIntExit() to perform an ISR level context switch.
;
; Note : OSIntCtxSw() MUST:
; a) Call OSTaskSwHook()
; b) Copy OSPrioHighRdy to OSPrioCur
; c) Copy OSTCBHighRdy to OSTCBCur
; d) Load the SP with OSTCBHighRdy->OSTCBStkPtr
; e) Restore all the registers from the high priority task stack
; f) Perform a return from interrupt
;********************************************************************************************************
_OSIntCtxSw
LCR #_OSTaskSwHook
MOV AL,*(0:_OSPrioHighRdy) ; OSPrioCur = OSPrioHighRdy
MOV *(0:_OSPrioCur),AL
MOV DP,#_OSTCBHighRdy
MOVZ AR4,@_OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy
MOV *(0:_OSTCBCur),AR4
MOV AL,*XAR4
MOV @SP,AL ; SP = OSTCBHighRdy->OSTCBStkPtr
POPALL ; pop all registers
IRET ; return from interrup
;********************************************************************************************************
; TICK ISR
;
; Description: This ISR handles tick interrupts. This ISR uses the Timera timer as the tick source.
;
; Notes : 1) The following C pseudo-code describes the operations being performed in the code below.
;
; Save all the CPU registers
; if (OSIntNesting == 0) {
; OSTCBCur->OSTCBStkPtr = SP;
; SP = OSISRStkPtr; /* Use the ISR stack from now on */
; }
; OSIntNesting++;
; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */
; Clear the interrupt source;
; OSTimeTick(); /* Call uC/OS-II's tick handler */
; DISABLE general interrupts; /* Must DI before calling OSIntExit() */
; OSIntExit();
; if (OSIntNesting == 0) {
; SP = OSTCBHighRdy->OSTCBStkPtr; /* Restore the current task's stack */
; }
; Restore the CPU registers
; Return from interrupt.
;
; 2) ALL ISRs should be written like this!
;
; 3) You MUST disable general interrupts BEFORE you call OSIntExit() because an interrupt
; COULD occur just as OSIntExit() returns and thus, the new ISR would save the SP of
; the ISR stack and NOT the SP of the task stack. This of course will most likely cause
; the code to crash. By disabling interrupts BEFORE OSIntExit(), interrupts would be
; disabled when OSIntExit() would return. This assumes that you are using OS_CRITICAL_METHOD
; #3 (which is the prefered method).
;
; 4) If you DON'T use a separate ISR stack then you don't need to disable general interrupts
; just before calling OSIntExit(). The pseudo-code for an ISR would thus look like this:
;
; Save all the CPU registers
; if (OSIntNesting == 0) {
; OSTCBCur->OSTCBStkPtr = SP;
; }
; OSIntNesting++;
; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */
; Clear the interrupt source;
; OSTimeTick(); /* Call uC/OS-II's tick handler */
; OSIntExit();
; Restore the CPU registers
; Return from interrupt.
;********************************************************************************************************
_Timer2_Isr
AND IER,#7FFFH ;diable RTOSINT
PUSHALL
MOV AH,#0
MOV AL,*(0:_OSIntNesting)
BF TM_ISR_1,NEQ
MOV DP,#_OSTCBCur
MOVZ AR4,@_OSTCBCur ; save task stack
MOV AH,@SP
MOV *XAR4,AH
MOV @SP,*(0:_OSISRStkPtr) ; load interrupt stack TM_ISR_1
ADD AL,#01
MOV *(0:_OSIntNesting),AL
EINT
LCR #_OSTimeTick
LCR #_OSIntExit
MOV AH,#0
MOV AL,*(0:_OSIntNesting)
BF TM_ISR_2,NEQ
MOV DP,#_OSTCBCur
MOVZ AR4,@_OSTCBCur
MOV AL,*XAR4
MOV @SP,AL
TM_ISR_2
POPALL
IRET
.REF _OSExtIntExit
.DEF _OSExtIntIsr
_OSExtIntIsr
PUSHALL
MOV DP,#_OSTCBCur
MOVZ AR4,@_OSTCBCur ; save task stack
MOV AH,@SP
MOV *XAR4,AH
LCR #_OSExtIntExit
POPALL
IRET
;*********************************************************************************************************
;* INITIALIZE A TASK'S STACK
;*
;* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
;* stack frame of the task being created. This function is highly processor specific.
;*
;* Arguments : task is a pointer to the task code
;*
;* pdata is a pointer to a user supplied data area that will be passed to the task
;* when the task first executes.
;*
;* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to
;* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then
;* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if
;* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
;* of the stack.
;*
;* opt specifies options that can be used to alter the behavior of OSTaskStkInit().
;* (see uCOS_II.H for OS_TASK_OPT_???).
;*
;* Returns : Always returns the location of the new top-of-stack' once the processor registers have
;* been placed on the stack in the proper order.
;*
;* Note(s) : The register passing convention for the IAR compiler is that the LEFTMOST two parameters
;* are passed in registers:
;* 1st parameter: R12 for a 16-bit value or, R13:R12 for a 32-bit value
;* 2nd parameter: R14 for a 16-bit value or, R15:R14 for a 32-bit value
;*
;* OSTaskStkInit() thus needs to place 'p_arg' in R12 since when the task is started, 'p_arg'
;* is the FIRST argument of the task declaration:
;*
;* void Task (void *p_arg)
;* {
;* }
;*********************************************************************************************************
;OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)
; XAR4, XAR5 , -SP[4], AL
_OSTaskStkInit
ADDB SP,#04
MOVL *-SP[2],XAR4
MOV *-SP[4],AL
MOVL XAR4,*-SP[8] ;XAR4 = ptos
ADDB XAR4,#01
AND AR4,#0FFFEH
ASP
NASP
PUSH T:ST0
POP ACC
MOVL *XAR4++,ACC ;ST0,T
MOVL *XAR4++,ACC ;ACC
MOVL *XAR4++,P
MOV *XAR4++,AR0 ;AR0
MOV *XAR4++,AR1 ;AR1
PUSH DP:ST1
POP ACC
MOVL *XAR4++,ACC ;ST1,DP
PUSH IER
POP *XAR4++ ;IER
PUSH DBGIER
POP *XAR4++ ;DBGIER
MOVL ACC,*-SP[2]
MOVL *XAR4++,ACC ;ADDR
ADDB XAR4,#01
MOVL ACC,XAR0
MOV *XAR4++,AH ;AR0H
MOVL ACC,XAR1
MOV *XAR4++,AH ;AR1H
MOVL *XAR4++,XAR2 ;XAR2
MOVL *XAR4++,XAR3 ;XAR3
MOVL ACC,*-SP[2]
MOVL *XAR4++,ACC ;XAR4
MOVL *XAR4++,XAR5 ;XAR5
MOVL *XAR4++,XAR6 ;XAR6
MOVL *XAR4++,XAR7 ;XAR7
MOVL *XAR4++,XT ;XT
MOVL ACC,*-SP[2]
MOVL *XAR4++,ACC ;ADDR
SUBB SP,#04
LRETR
.ref _c_int00
.sect "codestart"
LB _c_int00
.end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -