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

📄 k51a12.asm

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