📄 os_cpu_a.asm
字号:
.def _OSCtxSw, _OSIntCtxSw;
.def _OSStartHighRdy;
.def _OSTaskStkInit;
.mmregs
;**************** Context save and restore macros ************
;
; order must be the same as the compiler generated
; ISR context save/restores
;
;**************************************************************
CONTEXT_SAVE .macro
PSHM AL;
PSHM AH;
PSHM AG;
PSHM BL;
PSHM BH;
PSHM BG;
PSHM AR0;
PSHM AR1;
PSHM AR2;
PSHM AR3;
PSHM AR4;
PSHM AR5;
PSHM AR6;
PSHM AR7;
PSHM AR7; a bug in C compiler, ended up as AR7
PSHM BK;
PSHM T;
PSHM ST0;
PSHM ST1;
PSHM BRC;
PSHM PMST;
PSHM RSA;
PSHM REA;
; PSHM IMR; C compiler dosn't generate this, need to add if the context save is done by C compiler
.endm
CONTEXT_RESTORE .macro
; POPM IMR; C compiler doesn't generate this.
POPM REA;
POPM RSA;
POPM PMST;
POPM BRC;
POPM ST1;
POPM ST0;
POPM T;
POPM BK;
POPM AR7; A bug in C compiler, no FP for C54x. ended up as AR7
POPM AR7;
POPM AR6;
POPM AR5;
POPM AR4;
POPM AR3;
POPM AR2;
POPM AR1;
POPM AR0;
POPM BG;
POPM BH;
POPM BL;
POPM AG;
POPM AH;
POPM AL;
.endm
; NON MODULO MEMORY
.ref _OSTCBHighRdy, _OSTaskSwHook, _OSRunning, _OSTCBCur;
.ref _OSPrioCur, _OSPrioHighRdy
.text
;*********************************************************************************************************
; START MULTITASKING
; void OSStartHighRdy(void)
;
; The stack frame is assumed to look as follows:
;
; OSTCBHighRdy->OSTCBStkPtr --> IMR
; REA
; RSA
; PMST
; BRC
; ST0
; ST1
; T
; BK
; AR7
; AR7
; AR6
; AR5
; AR4
; AR3
; AR2
; AR1
; AR0
; BG
; BH
; BL
; AG
; AH
; AL (*pdata, passed in register A)
; *task (serve as the return address)
;
;
; Note : OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;*********************************************************************************************************
_OSStartHighRdy:
CALL #_OSTaskSwHook ; call _OSTaskSwHook
ST #1, *(_OSRunning) ; set OSRunning try
LD *(_OSTCBHighRdy), A ; OSTCBHighRdy points to the TCB ready to run
NOP ;
NOP ;
STLM A, AR0 ; AR0 has the TCB address
NOP ;
NOP ;
LD *AR0(0), A ; *AR0 has the sp
NOP ;
NOP ;
STLM A, SP ; load the sp for new task
NOP; need some nops for SP to truely changed
NOP;
CONTEXT_RESTORE; new task context is restored here, no A has *pdata, sp point to *task
NOP;
NOP;
RETE; run task
; initialize the task stack
; inputs:
; A = *task
; SP(0) = *pdata
; SP(1) = *ptos
; SP(2) = opt (ignored)
; outputs:
; A = new stack_top ->need to save in TCB
;
; After calling this function, the task stack will look like this:
;
; A(new stack_top) ----> IMR
; REA
; RSA
; PMST
; BRC
; ST0
; ST1
; T
; BK
; AR7
; AR7
; AR6
; AR5
; AR4
; AR3
; AR2
; AR1
; AR0
; BG
; BH
; BL
; AG
; AH
; AL (*pdata, passed in register A)
; *task (serve as the return address)
;
_OSTaskStkInit:
LDM SP, B ; temp save SP to BL
STLM A, T ; temp save *task to T
LD *SP(1), A; A has *pdata now
NOP ;
NOP ;
SFTL A, 8, A; temp save *pdata to BH
ADD A, 8, B ;
LD *SP(2), A; A has *task_stack_top
NOP ;
NOP ;
STLM A, SP ; change SP to the task stack
LDM T, A ;
NOP;
NOP;
PSHM AL ; task start address
SFTL B, -16, A; A has the *pdata
NOP;
NOP;
CONTEXT_SAVE;
LDM SP, A ; the top of the stack
STLM B, SP ; restore the SP
NOP ;
NOP ;
NOP ; need some no ops so SP is truly restored before RET
RET;
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From task level)
; void OSCtxSw(void)
;
; Note(s): 1) Upon entry,
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; 2) The stack frame of the task to suspend looks as follows:
;
; SP -> PC of task to suspend
;
; 3) The stack frame of the task to resume looks as follows:
;
; OSTCBHighRdy->OSTCBStkPtr --> IMR
; REA
; RSA
; PMST
; BRC
; ST0
; ST1
; T
; BK
; AR7
; AR7
; AR6
; AR5
; AR4
; AR3
; AR2
; AR1
; AR0
; BG
; BH
; BL
; AG
; AH
; AL
; PC of task to resume
;*********************************************************************************************************
_OSCtxSw:
CONTEXT_SAVE ; save all registers on the current stack
NOP ;
NOP ;
LDM SP, B ;
LD *(_OSTCBCur), A;
NOP ;
NOP ;
STLM A, AR0 ; store the curr sp to its tcb
NOP ;
NOP ;
STL B, *AR0(0);
NOP ;
NOP ;
CALL #_OSTaskSwHook;
; OSTCBCur = OSTCBHighRdy
; OSPrioCur = OSPrioHighRdy
LD *(_OSTCBHighRdy), A;
LD *(_OSPrioHighRdy), B;
NOP;
STL A, *(_OSTCBCur);
STL B, *(_OSPrioCur);
; restoring the new task
STLM A, AR0 ;
NOP ;
NOP ;
LD *AR0(0), A ;
NOP ;
NOP ;
STLM A, SP ; load the sp for new task
NOP; need some nops for SP to truely changed
NOP;
CONTEXT_RESTORE; new task context is restored here
NOP;
NOP;
RETE;
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From an ISR)
; void OSIntCtxSw(void)
;
; Note(s): 1) Upon entry,
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; 2) The stack frame of the task to suspend looks as follows:
;
; SP --> FRAME -1 from OSIntExit
; return address to OSIntExit()
; return address to ISR
; dummy to make even SP after push old SP
; old SP, -- SP before old even adjustment
; if old SP is odd, this is a dummy, otherwise non-exist
; MMRs - but no IMR
; ..
; ..
; ..
; return address of the task code
; 3) The stack frame of the task to resume looks as follows:
;
; OSTCBHighRdy->OSTCBStkPtr --> MMRs
; address of the task to resume
;*********************************************************************************************************
_OSIntCtxSw:
; When gets here, the SP top looks like this
;
; XXXX <- SP ;FRAME -1 from OSIntExit
; XXXX ;return address to OSIntExit
; XXXX ;return address to ISR
; XXXX ;dummy to make even SP after push old SP
; XXXX ;old SP, -- SP before old even adjustment
; XXXX ;if old SP is odd, this is a dummy, otherwise non-exist
; XXXX ;MMRs - but no IMR
; XXXX
;
FRAME 4 ; adjust the sp, pop up the return address of OSIntExit's caller and OSIntCtxSw's caller and the even word
POPM SP ; restore the old SP(before even/odd adjust)
NOP ;
; PSHM IMR ; IMR is not saved by C compiler, add it to the stack
NOP ;
LDM SP, B ; save sp to B
LD *(_OSTCBCur), A;
STLM A, AR0 ; store the curr sp to its tcb
NOP ;
NOP ;
STL B, *AR0(0) ;
NOP ;
NOP ;
; call user-defined OSTaskSwHook();
CALL #_OSTaskSwHook;
LD *(_OSTCBHighRdy), A;
LD *(_OSPrioHighRdy), B;
NOP;
STL A, *(_OSTCBCur);
STL B, *(_OSPrioCur);
; restoring the new task
NOP ;
NOP ;
STLM A, AR0 ;
NOP ;
NOP ;
LD *AR0(0), A ;
NOP ;
NOP ;
STLM A, SP ; load the sp for new task
NOP; need some nops for SP to truely changed
NOP;
CONTEXT_RESTORE; new task context is restored here
NOP;
NOP;
RETE;
;*********************************************************************************************************
; HANDLE TICK ISR
;
; Description: This function is called 199.99 times per second or, 11 times faster than the normal DOS
; tick rate of 18.20648 Hz. Thus every 11th time, the normal DOS tick handler is called.
; This is called chaining. 10 times out of 11, however, the interrupt controller on the PC
; must be cleared to allow for the next interrupt.
;
; Arguments : none
;
; Returns : none
;
; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below.
;
; Save all registers on the current task's stack;
; OSIntNesting++;
; OSTickDOSCtr--;
; if (OSTickDOSCtr == 0) {
; INT 81H; Chain into DOS every 54.925 mS
; (Interrupt will be cleared by DOS)
; } else {
; Send EOI to PIC; Clear tick interrupt by sending an End-Of-Interrupt to the 8259
; PIC (Priority Interrupt Controller)
; }
; OSTimeTick(); Notify uC/OS-II that a tick has occured
; OSIntExit(); Notify uC/OS-II about end of ISR
; Restore all registers that were save on the current task's stack;
; Return from Interrupt;
;*********************************************************************************************************
;
.end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -