⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 k51a1234.asm

📁 同事写的一个内核
💻 ASM
📖 第 1 页 / 共 3 页
字号:
    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 + -