📄 os_cpu_a.s43
字号:
;********************************************************************************************************
; uC/OS-II
; The Real-Time Kernel
;
; (c) Copyright 2002, Micrium, Inc., Weston, FL
; All Rights Reserved
;
; TI MSP430
;
;
; File : OS_CPU_A.S43
; By : Jian Chen (yenger@hotmail.com)
; Jean J. Labrosse
;********************************************************************************************************
#include <msp430x54x.h>
;********************************************************************************************************
; MACRO DEFINITIONS
;********************************************************************************************************
PUSHALL MACRO
push.w r4 ;push r4
push.w r5 ;push r5
push.w r6 ;push r6
push.w r7 ;push r7
push.w r8 ;push r8
push.w r9 ;push r9
push.w r10 ;push r10
push.w r11 ;push r11
push.w r12 ;push r12
push.w r13 ;push r13
push.w r14 ;push r14
push.w r15 ;push r15
ENDM
POPALL MACRO
pop.w r15 ;pop r15
pop.w r14 ;pop r14
pop.w r13 ;pop r13
pop.w r12 ;pop r12
pop.w r11 ;pop r11
pop.w r10 ;pop r10
pop.w r9 ;pop r9
pop.w r8 ;pop r8
pop.w r7 ;pop r7
pop.w r6 ;pop r6
pop.w r5 ;pop r5
pop.w r4 ;pop r4
ENDM
;********************************************************************************************************
; PUBLIC AND EXTERNAL DECLARATIONS
;********************************************************************************************************
EXTERN OSIntExit
EXTERN OSIntNesting
EXTERN OSISRStkPtr
EXTERN OSPrioCur
EXTERN OSPrioHighRdy
EXTERN OSRunning
EXTERN OSTCBCur
EXTERN OSTCBHighRdy
EXTERN OSTaskSwHook
EXTERN OSTimeTick
PUBLIC OSCtxSw
PUBLIC OSCPURestoreSR
PUBLIC OSCPUSaveSR
PUBLIC OSIntCtxSw
PUBLIC OSStartHighRdy
PUBLIC WDT_ISR
;********************************************************************************************************
; 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.
;********************************************************************************************************
RSEG CODE ; Program code
OSStartHighRdy
calla #OSTaskSwHook
mov.b #1, &OSRunning ; kernel running
mov.w SP, &OSISRStkPtr ; save interrupt stack
mov.w &OSTCBHighRdy, R13 ; load highest ready task stack
mov.w @R13, SP
POPALL ; pop all registers
reti ; 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.w sr,R4 ;
mov.w SP,R13 ;
mov.w 26(R13),R5 ;
mov.w 24(R13),26(R13) ;
RLA R5
RLA R5
RLA R5
RLA R5
RLA R5
RLA R5
RLA R5
RLA R5
RLA R5
RLA R5
RLA R5
RLA R5
BIS R5,R4
mov.w R4,24(R13)
mov.w &OSTCBCur, R13 ; OSTCBCur->OSTCBStkPtr = SP
mov.w SP, 0(R13)
calla #OSTaskSwHook
mov.b &OSPrioHighRdy, R13 ; OSPrioCur = OSPrioHighRdy
mov.b R13, &OSPrioCur ;
mov.w &OSTCBHighRdy, R13 ; OSTCBCur = OSTCBHighRdy
mov.w R13, &OSTCBCur ;
mov.w @R13, SP ; SP = OSTCBHighRdy->OSTCBStkPtr
POPALL ; pop all registers
reti ; 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
calla #OSTaskSwHook
mov.b &OSPrioHighRdy, R13 ; OSPrioCur = OSPrioHighRdy
mov.b R13, &OSPrioCur ;
mov.w &OSTCBHighRdy, R13 ; OSTCBCur = OSTCBHighRdy
mov.w R13, &OSTCBCur ;
mov.w @R13, SP ; SP = OSTCBHighRdy->OSTCBStkPtr
POPALL ; pop all registers
reti ; return from interrup
;********************************************************************************************************
; TICK ISR
;
; Description: This ISR handles tick interrupts. This ISR uses the Watchdog 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.
;********************************************************************************************************
WDT_ISR ; wd timer ISR
PUSHALL ; push all registers
bic.b #0x01, SFRIE1_L ; bic.b #0x01, SFRIE1 ; disable wd timer interrupt
cmp.b #0, &OSIntNesting ; if (OSIntNesting == 0)
jne WDT_ISR_1
mov.w &OSTCBCur, R13 ; save task stack
mov.w SP, 0(R13)
mov.w &OSISRStkPtr, SP ; load interrupt stack
WDT_ISR_1
inc.b &OSIntNesting ; increase OSIntNesting
bis.b #0x01, SFRIE1_L ;bis.b #0x01, SFRIE1 ; enable wd timer interrupt
EINT ; enable general interrupt to allow for interrupt nesting
calla #OSTimeTick ; call ticks routine
DINT ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit()
calla #OSIntExit ; call ticks routine
//没发生任务切换的,执行以下代码
cmp.b #0, &OSIntNesting ; if (OSIntNesting == 0)
jne WDT_ISR_2
mov.w &OSTCBHighRdy, R13 ; restore task stack SP
mov.w @R13, SP
WDT_ISR_2
POPALL ; pop all registers
reti ; return from interrupt
;********************************************************************************************************
; SAVE AND RESTORE THE CPU'S STATUS REGISTER
;
; Description: These functions are used to implement OS_CRITICAL_METHOD #3 by saving the status register
; in a local variable of the calling function and then, disables interrupts.
;
; Notes : R12 is assumed to hold the argument passed to OSCPUSaveSR() and also, the value returned
; by OSCPURestoreSR().
;********************************************************************************************************
OSCPUSaveSR
MOV.W SR,R12
DINT
RETA
OSCPURestoreSR
MOV.W R12,SR
RETA
;********************************************************************************************************
; WD TIMER INTERRUPT VECTOR ENTRY
;
; Interrupt vectors
;********************************************************************************************************
COMMON INTVEC
ORG WDT_VECTOR
WDT_VEC DW WDT_ISR ; interrupt vector. Watchdog/Timer, Timer mode
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -