📄 k51a1234.asm
字号:
mov sp, sp_task4
sjmp k51_int_return_to_task
;-----------------------------------------------------
;---- all tasks are idle, "go_idle"
; simply make sp point to bottom of stack,
; save address of idle task, then "reti".
;-----------------------------------------------------
; the k51 idle task is very simple and is not
; initialized, and no registers of this task
; need save, a force branch can make.
;-----------------------------------------------------
k51_int_go_idle:
mov sp, sp_task1
mov a, #low k51_idle_task
push acc
mov a, #high k51_idle_task
push acc ; address of idle task...
setb ea
reti ; go...all interrupts works
;-----------------------------------------------------
; running task do not change,
; simply return, as a normal isr
;-----------------------------------------------------
k51_int_no_sw:
setb ea
ret
;-----------------------------------------------------
k51_int_active_task1:
jb task1_running, k51_int_no_sw ; if task1 is running, switch not needed
setb task1_running
dec sp ; address to caller of
dec sp ; k51_int_exit(), discard
jbc task2_running, k51_int_sw_21
jbc task3_running, k51_int_sw_31
jbc task4_running, k51_int_sw_41
;-----------------------------------------------------
; no task previously running,
; simply copy sp_task1 and "reti"
;-----------------------------------------------------
mov sp, sp_task1
k51_int_return_to_task:
pop dph
pop dpl
pop b
pop acc
pop psw
setb ea
reti
;-----------------------------------------------------
; k51_int_sw_xy
; stack frame (low memory)
; return address of task been interrupted (lsb)
; return address of task been interrupted (msb)
; psw
; acc
; b
; dpl
; intr'd task's sp, copy to sp_tasky ----> dph
; discard ---------------> return address from k51_int_exit() to isr (lsb)
; discard ---------------> return address from k51_int_exit() to isr (msb)
; (high memory)
;-----------------------------------------------------
k51_int_sw_21:
mov sp_task2, sp
mov sp, sp_task1
ljmp k51_int_return_to_task
k51_int_sw_31:
mov sp_task3, sp
mov sp, sp_task1
ljmp k51_int_return_to_task
k51_int_sw_41:
mov sp_task4, sp
mov sp, sp_task1
ljmp k51_int_return_to_task
;-----------------------------------------------------
k51_int_active_task2:
jb task2_running, k51_int_no_sw ; if task2 is running, switch not needed
setb task2_running
dec sp ; address to caller of
dec sp ; k51_int_exit(), discard
jbc task3_running, k51_int_sw_32
jbc task4_running, k51_int_sw_42
;-----------------------------------------------------
; no task previously running,
; simply copy sp_task2 and "reti"
;-----------------------------------------------------
mov sp, sp_task2
ljmp k51_int_return_to_task
;-----------------------------------------------------
k51_int_sw_32:
mov sp_task3, sp
mov sp, sp_task2
ljmp k51_int_return_to_task
;-----------------------------------------------------
k51_int_sw_42:
mov sp_task4, sp
mov sp, sp_task2
ljmp k51_int_return_to_task
;-----------------------------------------------------
k51_int_active_task3:
jb task3_running, k51_int_no_sw ; if task3 is running, switch not needed
setb task3_running
dec sp ; address to caller of
dec sp ; k51_int_exit(), discard
jbc task4_running, k51_int_sw_43
; no task previously running, simply copy sp_task3 and "reti"
mov sp, sp_task3
ljmp k51_int_return_to_task
;-----------------------------------------------------
k51_int_sw_43:
mov sp_task4, sp
mov sp, sp_task3
ljmp k51_int_return_to_task
;-------------------------------------------------------------------------------
; void k51_sleep(unsigned char ticks_count)
; sleep ticks_count ticks
;-------------------------------------------------------------------------------
_k51_sleep:
clr ea
push psw ; save context of tasks...
push acc
push b
push dpl
push dph ; ...save context of tasks
mov a, r7
jnz k51_sleep_100
inc r7 ; 0 for sleep timer is not allowed
k51_sleep_100:
jbc task1_running, task1_sleep
jbc task2_running, task2_sleep
jbc task3_running, task3_sleep
;-----------------------------------------------------
; task4_sleep: no task will later active, "go_idle"
task4_sleep:
clr task4_running
clr task4_ready
mov task4_timer, r7
mov sp_task4, sp ; save context of task4
sjmp k51_sleep_go_idle
task1_sleep:
clr task1_ready
mov task1_timer, r7
mov sp_task1, sp ; save context of task1
jb task2_ready, k51_sw_active_task2
jb task3_ready, k51_sw_active_task3
jb task4_ready, k51_sw_active_task4
;-----------------------------------------------------
; no task is ready, "go_idle"
;-----------------------------------------------------
sjmp k51_sleep_go_idle
;-----------------------------------------------------
k51_sw_active_task2:
setb task2_running
mov sp, sp_task2
sjmp k51_return_to_task
;-----------------------------------------------------
k51_sw_active_task3:
setb task3_running
mov sp, sp_task3
sjmp k51_return_to_task
;-----------------------------------------------------
k51_sw_active_task4:
setb task4_running
mov sp, sp_task4
k51_return_to_task:
pop dph
pop dpl
pop b
pop acc
pop psw
setb ea
ret
;-----------------------------------------------------
task2_sleep:
clr task2_ready
mov task2_timer, r7
mov sp_task2, sp ; save context of task2
jb task3_ready, k51_sw_active_task3
jb task4_ready, k51_sw_active_task4
;-----------------------------------------------------
; no task is ready, "go_idle"
;-----------------------------------------------------
; goto idle, waiting an interrupt.
; idle task use task1's stack
;-----------------------------------------------------
k51_sleep_go_idle:
mov sp, sp_task1
setb ea
sjmp k51_idle_task
;-----------------------------------------------------
task3_sleep:
clr task3_ready
mov task3_timer, r7
mov sp_task3, sp ; save context of task3
jb task4_ready, k51_sw_active_task4
;-----------------------------------------------------
; no task is ready, "go_idle"
sjmp k51_sleep_go_idle
;-------------------------------------------------------------------------------
; void k51_idle_task()
;-------------------------------------------------------------------------------
k51_idle_task:
orl pcon, #1 ; 8XC5X: enter idle mode
sjmp k51_idle_task
;-------------------------------------------------------------------------------
; void k51_tick()
; decreases sleep timers for tasks until it's 0.
;-------------------------------------------------------------------------------
k51_tick:
mov a, task1_timer
jz k51_tick_100
dec task1_timer
mov a, task1_timer
jnz k51_tick_100
setb task1_ready
k51_tick_100:
mov a, task2_timer
jz k51_tick_200
dec task2_timer
mov a, task2_timer
jnz k51_tick_200
setb task2_ready
k51_tick_200:
mov a, task3_timer
jz k51_tick_300
dec task3_timer
mov a, task3_timer
jnz k51_tick_300
setb task3_ready
k51_tick_300:
mov a, task4_timer
jz k51_tick_400
dec task4_timer
mov a, task4_timer
jnz k51_tick_400
setb task4_ready
k51_tick_400:
ret
;-------------------------------------------------------------------------------
; void k51_signal_init(unsigned char idata* p_sig)
; { *p_sig = 0; /* not signaled, non waiting */ }
;-------------------------------------------------------------------------------
_k51_signal_init:
mov a, r7
mov r0, a
mov @r0, #0
ret
;-------------------------------------------------------------------------------
; void k51_signal_send(unsigned char idata* p_sig)
;-------------------------------------------------------------------------------
_k51_signal_send:
clr ea
mov a, r7
mov r0, a
mov a, @r0
anl a, #0fh ; check if a task is waiting on
jnz sig_send_100
setb acc.7 ; no task is waiting it,
mov @r0, a ; make it signaled and return.
setb ea
ret
;-----------------------------------------------------
sig_send_100:
mov a, k51_int_nest ; if called in isr, only set
jz sig_send_1000 ; task-ready, do not switch.
;-----------------------------------------------------
; k51_signal_send() is called in isr.
; task is set ready and no switch.
;-----------------------------------------------------
mov a, @r0
mov @r0, #0 ; signal cleared.
jb acc.0, sig_send_isr_t1_rdy
jb acc.1, sig_send_isr_t2_rdy
jb acc.2, sig_send_isr_t3_rdy
sig_send_isr_t4_rdy:
setb task4_ready
setb ea
ret
sig_send_isr_t1_rdy:
setb task1_ready
setb ea
ret
sig_send_isr_t2_rdy:
setb task2_ready
setb ea
ret
sig_send_isr_t3_rdy:
setb task3_ready
setb ea
ret
;-----------------------------------------------------
; k51_signal_send() is called by a task.
; if higher-priority task is made ready, swich to the task.
;-----------------------------------------------------
sig_send_1000:
mov a, @r0
mov @r0, #0 ; clear signal
jb task1_running, task1_send_sig
jb task2_running, task2_send_sig
jb task3_running, task3_send_sig
task4_send_sig:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -