📄 cxskv5m.asm
字号:
MOV R5,[R10+ #tcbstate] ;get the task's state
AND R5,#RESUME OR READY ;see if capable of running
JMPR cc_NZ,task_resume ;yes, go let task run
findready:
MOV R10,[R10+#nxttcb_pof] ;get next task in linked list
CMP R10,#POF (_cmx_tcb) ;are we at bottom of list?
; this will now loop thru ALL tcb's, before testing do_int_pipe
; and do_K_I_Timer_Task
JMPR cc_NE,midpaus2
@IF( @LOW_POWER_ACTIVE )
jnb _cmx_flag1.6,no_power_down
power_down:
PUSH DPP0
PUSH R10 ;save pointer
CALLA cc_UC,_K_OS_Low_Power_Func ;call USER'S written power down mode
POP R10 ;restore pointer
POP DPP0
no_power_down:
@ENDI
MOV R10,[R10 + #nxttcb_pof] ;set r10 to highest priority user task
JMPR cc_UC,rescan1 ;test flags again
task_resume:
BFLDL _cmx_flag1,#(idle_flag or do_time_slice),#00h
@IF( @INT_ENABLE )
BFLDH PSW,#0F0H,#(INT_LEVEL << 4)
@ELSE
BCLR IEN ;turn interrupts off
@ENDI
@IF( @ADD_NOP )
NOP ;These 2 NOP's fix the 80C16x silicon
NOP
@ENDI
MOVB RL4,_cmx_flag1 ;get CMX flag byte
ANDB RL4,#(do_int_pipe or do_timer_tsk) ;see if either flag set
JMPA cc_NZ,sched_again ;if so, go do it
resume_good:
MOVB _locked_out,ZEROS ;set locked out to zero
;move the tcb address into current active tcb
MOV _activetcb,R10
MOV _activetcb+2,DPP0
MOVB RL4,[R10+#tsk_priority] ;get task's priority
MOVB _active_priority,RL4
@IF( @SLICE_ENABLE )
MOVB RL4,_SLICE_ON
JMPR cc_Z,no_slice ;no, bypass following
jb _cmx_flag1.3,no_slice ;if flag set, then still dec. slice count
bset _cmx_flag1.3
MOVB RL4,_TSLICE_SCALE
MOVB _tslice_count,RL4
no_slice:
@ENDI
@IF( @CMXTRACKER_ENABLE )
CMP R10,_previoustcb ;see if same task as before
JMPR cc_NE,diff1
CMP DPP0,_previoustcb+2 ;see if same task as before
JMPR cc_EQ,same1
diff1:
MOV _previoustcb,R10
MOV _previoustcb+2,DPP0
PUSH DPP0
PUSH R10 ;save pointer
CALLA cc_UC,_cmxtracker_in_task
POP R10 ;restore pointer
POP DPP0
same1:
@ENDI
MOV R4,[R10+#tcbstate] ;get task's states again
@IF( @CMXTRACKER_ENABLE )
MOV R5,R4
@ENDI
BFLDH R4,#0EH,#08H ;set to RUNNING STATE
MOV [R10+ #tcbstate],R4 ;save it
jb r5.9,task_ready ;see if READY, then task start
;at beginning brace
;if not, then task is RESUMING
mov R0,[R10+#stk_save_pof] ;get the task's stack address
MOV R2,[R0+] ;GET COUNT
restore_loop:
MOV R1,[R0+] ;GET WORD FROM USER STACK
PUSH R1 ;PUT ON SYSTEM STACK
SUB R2,#2
JMPR cc_NZ,restore_loop
@IF( @FLOAT_ENABLE )
CALLA cc_UC,__fppopus
@ENDI
MOV R15,[R0+] ;restore all regs
MOV R14,[R0+]
MOV R13,[R0+]
MOV R12,[R0+]
MOV R11,[R0+]
MOV R10,[R0+]
MOV R9,[R0+]
MOV R8,[R0+]
MOV R7,[R0+]
MOV R6,[R0+]
MOV R5,[R0+]
MOV R4,[R0+]
MOV R3,[R0+]
; new as of 9/29/93
pop psw ;restore psw, for MULIP bit
JB PSW.6,restore_from_interrupt ;see if interrupt caused task
;switch, if so jump
MOV R2,[R0+]
MOV R1,[R0+]
pop psw ;restore TRUE PSW
RETN ;return to correct address
restore_from_interrupt:
MOV R1,[R0+] ;restore additional regs
MOV DPP2,R1
MOV R1,[R0+]
MOV DPP0,R1
MOV R1,[R0+]
mov mdl,r1
MOV R1,[R0+]
mov mdh,r1
MOV R1,[R0+]
mov mdc,r1
done_scheduler:
MOV R2,[R0+]
MOV R1,[R0+]
done1_scheduler:
@IF( @FIX166 )
BFLDH PSW,#0F0H,#0F0H ;This fixes the 8016x silicon
NOP
NOP
@ENDI
FAKE_RETI ;return to correct address, use literal,
;so assembler will be happy
RET ;DUMMY Return instruction, to keep assembler happy
; the following is for a task that is beginning it's code
task_ready:
mov R0,[R10+#stk_start_pof] ;get the task's stack address
BFLDH R0,#0C0H,#40H ;HAVE R0 POINT TO DPP1 (stack page)
mov R1,#0800h ;load in value to enable interrupts
;for psw (set bit IEN)
push R1 ;place on stack
mov r4,#SEG _K_I_Scheduler ;place CSP on stack
push R4
mov r4,[R10+#task_addr_sof] ;place task's IP address on stack
push R4
@IF( @FIX166 )
BFLDH PSW,#0F0H,#0F0H ;This fixes the 8016x silicon
NOP
NOP
@ENDI
FAKE_RETI ;return to correct address, use literal,
;so assembler will be happy
RET ;DUMMY Return instruction, to keep assembler happy
_K_I_Sched ENDP
_K_OS_Disable_Interrupts PROC NEAR
@IF( @INT_ENABLE )
BFLDH PSW,#0F0H,#(INT_LEVEL << 4)
@ELSE
BCLR IEN ;turn interrupts off
@ENDI
@IF( @ADD_NOP )
NOP ;These 2 NOP's fix the 80C16x silicon
NOP
@ENDI
RETN
_K_OS_Disable_Interrupts ENDP
_K_OS_Enable_Interrupts PROC NEAR
@IF( @INT_ENABLE )
BFLDH PSW,#0F0H,#00h
@ELSE
BSET IEN ;turn interrupts ON
@ENDI
RETN
_K_OS_Enable_Interrupts ENDP
_K_OS_Save_Interrupts PROC NEAR
PUSH R2 ;save R2
PUSH PSW
@IF( @INT_ENABLE )
BFLDH PSW,#0F0H,#(INT_LEVEL << 4)
@ELSE
BCLR IEN ;turn interrupts off
@ENDI
@IF( @ADD_NOP )
NOP ;These 2 NOP's fix the 80C16x silicon
NOP
@ENDI
POP R2
MOV _ie_holder,R2
POP R2
RETN
_K_OS_Save_Interrupts ENDP
_K_OS_Restore_Interrupts PROC NEAR
MOV PSW,_ie_holder
RETN
_K_OS_Restore_Interrupts ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Interrupt routine
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; NOTE: for ALL memory models, except tiny. Must be CALLS instruction
; the following is for "C" coded interrupts using #pragma noframe
_K_OS_Intrp_Exit_No_Frame PROC FAR
add SP,#4 ;adjust stack pointer for calls to K_OS_Intrp_Exit
jmpa cc_UC,K_OS_Intrp_Exit1
RET ;NOTE: This will NOT be executed, here only to suppress
;a warning from the assembler
_K_OS_Intrp_Exit_No_Frame ENDP
; the following is for "C" coded interrupts NOT using #pragma noframe
_K_OS_Intrp_Exit PROC FAR
add SP,#4 ;adjust stack pointer for calls to K_OS_Intrp_Exit
NOP ;has to be here for silicon
@IF( @Ff_ENABLE )
CALLA cc_UC,__fppopus
@ENDI
@IF ( @MDH_PUSHED_FIRST )
POP MDL ;restore registers that compiler generated code pushed
POP MDH
@ELSE
POP MDH ;restore registers that compiler generated code pushed
POP MDL
@ENDI
POP DPP2
POP DPP0
POP MDC
@IF( @PSW_INT_PUSH )
POP PSW
@ENDI
POP CP
K_OS_Intrp_Exit1:
@IF( @INT_ENABLE )
BFLDH PSW,#0F0H,#(INT_LEVEL << 4)
@ELSE
BCLR IEN ;turn interrupts off
@ENDI
@IF( @ADD_NOP )
NOP ;These 2 NOP's fix the 80C16x silicon
NOP
@ENDI
jnb _cmx_flag1.7,done1_scheduler ;have we entered CMX RTOS
MOV [-R0],R1 ;save reg
MOV [-R0],R2 ;save reg
mov r1,SP
; test ILVL level of psw. If non zero, means other interrupts were interrupted
mov r2,[r1 + #4] ;get psw
AND R2,#0F000H ;see if other interrupts preempted
jmpr cc_NZ,done_scheduler ;yes, go finish their code
no_pending:
PUSH DPP2
MOV DPP2, #PAG C166_DGROUP
NOP
MOVB RL1,_locked_out ;see if we were in critical region
JMPR cc_NZ,new_exit ;yes, return to it
MOVB RL1,_cmx_flag1 ;get CMX flag byte
ANDB RL1,#(do_int_pipe or preempted or do_timer_tsk or do_time_slice or do_coop_sched)
JMPR cc_Z,new_exit ;yes, return to it
jmp_sched_int:
movb rl1,#01h ;yes, set critical region count to 1
addb _locked_out,rl1
POP DPP2
AND PSW,#0FFFH ;clear ilvl level
BSET PSW.6 ;set user flag, identifying that interrupt cause preemption
; the following pushes PSW on stack, saving MULIP bit and USER flag then
; enables interrupts.
SCXT PSW,#0800H
MOV R1,MDC
MOV [-R0],R1
MOV MDC,#00h
MOV R1,MDH
MOV [-R0],R1
MOV R1,MDL
MOV [-R0],R1
MOV R1,DPP0
MOV [-R0],R1
MOV R1,DPP2
MOV [-R0],R1
MOV DPP0, #PAG ?BASE_DPP0 ; Set data page pointers.
MOV DPP2, #PAG C166_DGROUP
jmpa cc_UC,sched_int ;go save task's context
RET ;NOTE: This will NOT be executed, here only to suppress
;a warning from the assembler
new_exit:
POP DPP2
JMPA cc_UC,done_scheduler
_K_OS_Intrp_Exit ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CXSKV5M_PR ENDS
C166_DGROUP DGROUP __DUMMY
__DUMMY SECTION DATA WORD PUBLIC 'CNEAR'
__DUMMY ENDS
REGDEF R0-R15
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -