📄 k51a123.asm
字号:
clr task3_ready
mov task3_timer, r7
mov sp_task3, 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
;-----------------------------------------------------
; 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
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
;-----------------------------------------------------
; idle task use task1's stack
;-----------------------------------------------------
k51_sleep_go_idle:
mov sp, sp_task1
setb ea
sjmp k51_idle_task
;-------------------------------------------------------------------------------
; 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:
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
sig_send_isr_t3_rdy:
setb task3_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
;-----------------------------------------------------
; 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
task3_send_sig:
clr task3_running
push psw
push acc
push b
push dpl
push dph
mov sp_task3, sp
jb acc.0, sig_send_active1
;-----------------------------------------------------
; task3 can not send signal to itself, then the signal
; must be send to task2.
;-----------------------------------------------------
sig_send_active2:
mov sp, sp_task2
setb task2_ready
setb task2_running
ljmp k51_wait_ret_task
;-----------------------------------------------------
sig_send_active1:
mov sp, sp_task1
setb task1_ready
setb task1_running
ljmp k51_wait_ret_task
;-----------------------------------------------------
; task1 has highest priority, signaled task is set to
; ready, but do not switch to it.
;-----------------------------------------------------
task1_send_sig:
jb acc.1, sig_send_rdy2
sig_send_rdy3:
setb task3_ready
setb ea
ret
sig_send_rdy2:
setb task2_ready
setb ea
ret
;-----------------------------------------------------
task2_send_sig:
jb acc.2, sig_send_rdy3
sig_send_sw21:
push psw
push acc
push b
push dpl
push dph
mov sp_task2, sp
clr task2_running
sjmp sig_send_active1
;-------------------------------------------------------------------------------
; void k51_signal_wait(unsigned char idata* p_obj)
; void k51_mutex_wait (unsigned char idata* p_obj)
; these 2 functions do the same thing.
; bit7 of obj indicates the object is signaled or available,
; bit0-3 indicates waiting tasks(task1-4). If it's a signal, only 1 task could
; be included in the list, if it's a mutex, every task is allowed.
;-------------------------------------------------------------------------------
_k51_mutex_wait:
_k51_signal_wait:
clr ea
mov a, r7
mov r0, a
mov a, @r0
jnb acc.7, k51_sig_wait_100
mov @r0, #0 ; signaled, do not need wait
; the signal is cleared
setb ea
ret
k51_sig_wait_100:
push psw
push acc
push b
push dpl
push dph
jbc task1_running, sig_wait_task1
jbc task2_running, sig_wait_task2
;-----------------------------------------------------
; task3 will goto idle state, no task actives
;-----------------------------------------------------
sig_wait_task3:
clr task3_running
clr task3_ready
orl a, #4 ; waiting: task3
mov @r0, a
mov sp_task3, sp
sjmp k51_wait_go_idle ; no task actives
;-----------------------------------------------------
sig_wait_task1:
clr task1_running
clr task1_ready
orl a, #1 ; waiting: task1
mov @r0, a
mov sp_task1, sp
jb task2_ready, sigw_active_task2
jb task3_ready, sigw_active_task3
sjmp k51_wait_go_idle ; no task actives
sigw_active_task2:
setb task2_running
mov sp, sp_task2
sjmp k51_wait_ret_task
;-----------------------------------------------------
sigw_active_task3:
setb task3_running
mov sp, sp_task3
k51_wait_ret_task:
pop dph
pop dpl
pop b
pop acc
pop psw
setb ea
ret
;-----------------------------------------------------
sig_wait_task2:
clr task2_running
clr task2_ready
orl a, #2 ; waiting: task2
mov @r0, a
mov sp_task2, sp
jb task3_ready, sigw_active_task3
k51_wait_go_idle:
mov sp, sp_task1 ; idle task use task1's stack
setb ea
ljmp k51_idle_task
IF MUTEX_ENABLE <> 0
;-------------------------------------------------------------------------------
; void k51_mutex_init(unsigned char idata* p_mut)
; { *p_mut = 0x80; /* available */ }
;-----------------------------------------------------
; The bit7 of a mutex indicates it's available.
; bit0-bit3 indicates tasks(1-4) are waiting for this mutex.
;-------------------------------------------------------------------------------
_k51_mutex_init:
mov a, r7
mov r0, a
mov @r0, #80h
ret
;-------------------------------------------------------------------------------
; void k51_mutex_release(unsigned char idata* p_mut)
; If any task is waiting for the mutex, the task with highest priority will
; be set to ready and remove to the wait list.
; If no task is waiting for it, the mutex is set to available state.
;-------------------------------------------------------------------------------
_k51_mutex_release:
clr ea
mov a, r7
mov r0, a
mov a, @r0
anl a, #0fh ; check task list
jnz mut_release_100
setb acc.7 ; no task is waiting, make it
mov @r0, a ; available and return.
setb ea
ret
mut_release_100:
jb task1_running, mut_rls_task1
jb task2_running, mut_rls_task2
;-----------------------------------------------------
; A task wait on the mutex will active, instead of task3.
;-----------------------------------------------------
mut_rls_task3:
push psw
push acc
push b
push dpl
push dph
mov sp_task3, sp
clr task3_running
jb acc.0, mut_rls_active1
;-----------------------------------------------------
; A task can not release a mutex to itself,
; so the waiting task must be task3.
;-----------------------------------------------------
mut_rls_active2:
anl a, #0fdh ; bit1 clear, task2 removed.
mov @r0, a
setb task2_ready
setb task2_running
mov sp, sp_task2
ljmp k51_wait_ret_task
;-----------------------------------------------------
mut_rls_active1:
anl a, #0feh ; bit0 clear, task1 removed.
mov @r0, a
setb task1_ready
setb task1_running
mov sp, sp_task1
sjmp k51_wait_ret_task
;-----------------------------------------------------
; task1 has highest priority, it release a mutex do
; not need to switch to another task.
;-----------------------------------------------------
mut_rls_task1:
jb acc.1, mut_rls_rdy2
mut_rls_rdy3:
anl a, #0fbh ; bit2 clear, task3 removed.
mov @r0, a
setb task3_ready
setb ea
ret
mut_rls_rdy2:
anl a, #0fdh ; bit1 clear, task2 removed.
mov @r0, a
setb task2_ready
setb ea
ret
;-----------------------------------------------------
mut_rls_task2:
jb acc.0, mut_rls_sw21
sjmp mut_rls_rdy3
mut_rls_sw21:
push psw
push acc
push b
push dpl
push dph
mov sp_task2, sp
clr task2_running
sjmp mut_rls_active1
;-------------------------------------------------------------------------------
ENDIF ; MUTEX_ENABEL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -