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

📄 k51a12.asm

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