📄 k51a12.asm
字号:
; k51a12.asm
; by geweidong, 2005-11-27
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; iiiiiiiiiiiiiii imports iiiiiiiiiiiiiiiiiii
;-------------------------------------------------------------------------------
extrn code (task1, task2)
;-------------------------------------------------------------------------------
; eeeeeeeeeeeeeee exports eeeeeeeeeeeeeeeeeee
;-------------------------------------------------------------------------------
;--------------- functions -------------
public k51_init
public task1_init
public task2_init
public k51_int_exit
public _k51_sleep
public k51_tick
public k51_idle_task
public _k51_signal_init
public _k51_signal_send
public _k51_signal_wait
IF MUTEX_ENABLE <> 0
public _k51_mutex_init
public _k51_mutex_release
public _k51_mutex_wait
ENDIF
;--------------- variables -------------
public k51_int_nest
public sp_task1, sp_task2
;-------------------------------------------------------------------------------
; stack frame for task switch (low mem) --> return address (lsb)
; return address (msb)
; psw
; acc
; b
; dpl
; Top of stack (high mem) ------------> dph
;-------------------------------------------------------------------------------
seg_k51_data segment data
seg_k51_bits segment bit
seg_k51_core segment code
;-------------------------------------------------------------------------------
rseg seg_k51_data
task1_timer: ds 1
task2_timer: ds 1
sp_task1: ds 1
sp_task2: ds 1
k51_int_nest: ds 1
;-------------------------------------------------------------------------------
rseg seg_k51_bits
slot1_available: dbit 1
slot2_available: dbit 1
task1_ready: dbit 1
task2_ready: dbit 1
task1_running: dbit 1
task2_running: dbit 1
;-------------------------------------------------------------------------------
; ccccccccccccccccccccc constants cccccccccccccccccccccccc
;-------------------------------------------------------------------------------
no_error equ 0
error_prio_used equ 0x1
;-------------------------------------------------------------------------------
rseg seg_k51_core
;-------------------------------------------------------------------------------
; void k51_init()
;-------------------------------------------------------------------------------
k51_init:
clr a
mov task1_timer, a ; timers set to 0
mov task2_timer, a
mov k51_int_nest, a ; init to 0
setb slot1_available ; all available
setb slot2_available
clr task1_ready ; none ready
clr task2_ready
clr task1_running ; none running
clr task2_running
IF PRIO_MAIN = 1
clr slot1_available ; slot1 used
setb task1_ready ; task1 ready
setb task1_running ; task1 running
mov psw, #0 ; register bank 0
ENDIF
IF PRIO_MAIN = 2
clr slot2_available ; slot2 used
setb task2_ready ; task2 ready
setb task2_running ; task2 running
mov psw, #8 ; register bank 1
ENDIF
ret
;-------------------------------------------------------------------------------
; unsigned char task1_init();
; globals:
; slot1_available - if slot1_available == 0 this function fail, otherwise
; this function succeed and slot1_available clear.
; task1_ready - if succeeded, task1_ready will set.
; psw - select register bank 0
;-------------------------------------------------------------------------------
task1_init:
jbc slot1_available, task1_init_100
task1_init_prio_used:
mov r7, #error_prio_used ; error code return
ret
task1_init_100:
mov r1, sp_task1 ; begin...init stack of task1
inc r1 ; full stack, inc then write
mov a, #low task1
mov @r1, a
inc r1
mov a, #high task1
mov @r1, a ; pc = start address of task1
inc r1
mov @r1, #0 ; psw = 0...register bank 0
inc r1
clr a
mov @r1, a ; acc = 0
inc r1
mov @r1, a ; b = 0
inc r1
mov @r1, a ; dpl = 0
inc r1
mov @r1, a ; dph = 0
mov sp_task1, r1 ; set stack-pointer of task1
setb task1_ready ; task1 ready
mov r7, #no_error ; error code return -- no error
ret
;-------------------------------------------------------------------------------
; unsigned char task2_init();
; globals:
; slot2_available - if slot2_available == 0 this function fail, otherwise
; this function succeed and slot2_available clear.
; task2_ready - if succeeded, task2_ready will set.
; psw - select register bank 1
;-------------------------------------------------------------------------------
task2_init:
jbc slot2_available, task2_init_100
task2_init_prio_used:
mov r7, #error_prio_used ; error code return
ret
task2_init_100:
mov r1, sp_task2 ; begin...init stack of task2
inc r1
mov a, #low task2
mov @r1, a
inc r1
mov a, #high task2
mov @r1, a ; pc = start address of task2
inc r1
mov @r1, #8 ; psw = 8...register bank 1
inc r1
clr a
mov @r1, a ; acc = 0
inc r1
mov @r1, a ; b = 0
inc r1
mov @r1, a ; dpl = 0
inc r1
mov @r1, a ; dph = 0
mov sp_task2, r1 ; set stack-pointer of task2
setb task2_ready ; task2 ready
mov r7, #no_error ; error code return -- no error
ret
;-------------------------------------------------------------------------------
; void k51_int_exit()
; Called by user defined interrupt service routines
; This function can make a task to running state, and make another from running
; state to ready state (a running task is alwayls a ready task).
; This function never make a task from idle to ready.
; If no task is ready at this point, no task is running.
;-------------------------------------------------------------------------------
k51_int_exit:
clr ea
dec k51_int_nest
mov a, k51_int_nest
jnz k51_int_no_sw
jnb task1_ready, k51_int_chk_task2
ljmp k51_int_active_task1
k51_int_chk_task2:
jnb task2_ready, k51_int_go_idle
k51_int_active_task2:
jb task2_running, k51_int_no_sw
setb task2_running
mov sp, sp_task2
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
;-----------------------------------------------------
; 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
;-------------------------------------------------------------------------------
; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -