📄 k51a12.asm
字号:
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
;-----------------------------------------------------
; task2_sleep: no task will later active, "go_idle"
task2_sleep:
clr task2_running
clr task2_ready
mov task2_timer, r7
mov sp_task2, 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
;-----------------------------------------------------
; 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_return_to_task:
pop dph
pop dpl
pop b
pop acc
pop psw
setb ea
ret
;-----------------------------------------------------
; 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
;-------------------------------------------------------------------------------
; 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:
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
sig_send_isr_t2_rdy:
setb task2_ready
setb ea
ret
sig_send_isr_t1_rdy:
setb task1_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
task2_send_sig:
clr task2_running
push psw
push acc
push b
push dpl
push dph
mov sp_task2, sp
;-----------------------------------------------------
; task2 can not send signal to itself, then the signal
; is send to task1.
;-----------------------------------------------------
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:
setb task2_ready
setb ea
ret
;-------------------------------------------------------------------------------
; 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
;-----------------------------------------------------
; task2 will goto idle state, no task actives
;-----------------------------------------------------
sig_wait_task2:
clr task2_running
clr task2_ready
orl a, #2 ; waiting: task2
mov @r0, a
mov sp_task2, 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
jnb task2_ready, k51_wait_go_idle ; no task actives
sigw_active_task2:
setb task2_running
mov sp, sp_task2
sjmp k51_wait_ret_task
;-----------------------------------------------------
k51_wait_ret_task:
pop dph
pop dpl
pop b
pop acc
pop psw
setb ea
ret
;-----------------------------------------------------
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
;-----------------------------------------------------
; A task wait on the mutex will active, instead of task4.
;-----------------------------------------------------
mut_rls_task2:
push psw
push acc
push b
push dpl
push dph
mov sp_task2, sp
clr task2_running
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:
anl a, #0fdh ; bit1 clear, task2 removed.
mov @r0, a
setb task2_ready
setb ea
ret
;-------------------------------------------------------------------------------
ENDIF ; MUTEX_ENABEL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -