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

📄 kernel.asm

📁 PICOS18 V2.10 基于PIC18的实时操作系统
💻 ASM
📖 第 1 页 / 共 2 页
字号:

    setupStackSentinel                  ; Put a signature, 0xadde at
                                        ; the end of the stack
    incf    FSR0L                       ; Step to next task entry
    bsf     FSR0L, 4                    ; Point back to tsk_xx_activ_prio
    bra     _parserInit                 ; Loop back for next task
                                        ; in task descriptor
_parser_organize
    GLOBAL  _parser_organize            ; If so requested externally
    movlb   0                           ; Prioritize the TCTs
    clrf    permut
    incf    permut      

;/* - REARRANGE TASK ORDER IN EACH TCT, BASED ON DESCENDING PRIORITY - */
_parserUpdate
    setupFSR0    tsk_1_activ_prio
    movf    permut, w                   ; Is there a bubble in the last
    btfsc   STATUS, Z                   ; iteration?
    bra     _isHook                     ; If No, means TCTs prioritized
    clrf    permut                      ; If Yes, sort still in progress
                                        ; Clear permutation flag for this
                                        ; iteration (Bubble sort is used)
_parserUpdateLoop 
    movlw   0x0F
    andwf   INDF0, w
    movwf   temp                        ; Extract task's priority
    btfsc   STATUS, Z                   ; 0 signifies the end of TCT
    bra     _parserUpdate               ; If end of task atble, loop back
                                        ; for next bubble sort iteration 
    movff   INDF0, temp2                ; Else backup (activ + prio) byte
    movlw   0x0F
    andwf   PREINC0, w                  ; Extract next task's priority

    cpfseq  temp
    bra     _parserUpdateDiff
    bra     _parserUpdateLoop           ; Equal priority, Loopback for
                                        ; the next control table entry
_parserUpdateDiff
    cpfsgt  temp
    bra     _parserUpdateSwap           ; Go swap on low priority
    bra     _parserUpdateLoop           ; Loopback if priority in place

_parserUpdateSwap
    movf    POSTDEC0, w                 ; Swap entry in tsk_xx_activ_prio
    movwf   POSTINC0                    ; located at 0x0B0
    movff   temp2, INDF0

    bcf     FSR0L, 4                    ; Swap entry in tsk_xx_state_ID
    swapTaskCtrlEntry                   ; located at 0x0A0

    bcf     FSR0L, 5                    ; Swap the task entry in event_xx
    swapTaskCtrlEntry                   ; located at 0x080

    bsf     FSR0L, 4                    ; Swap the task entry in wait_xx
    swapTaskCtrlEntry                   ; located at 0x090

    bsf     FSR0L, 5                    ; Point back to tsk_xx_activ_prio
    incf    permut                      ; Raise the permutation flag to
                                        ; signify a swap has occurred
    bra     _parserUpdateLoop 

_isHook                                 ; Hook kernel service routine
    #IFDEF  STARTUPHOOK
        call    StartupHook
    #ENDIF

;/**********************************************************************
; * --------------------- KERNEL TASK SCHEDULER ------------------------
; *
; * The scheduler manage the task switching during application running.
; *
; **********************************************************************/
_sched
    GLOBAL  _sched
    #IFDEF  POSTTASKHOOK
        call    PostTaskHook
    #ENDIF

    movlb   0
    bcf     kernelState, 0              ; Switch to KERNEL mode
    movf    id_tsk_run, w
    btfsc   STATUS, Z                   ; Is running task 0 or not?
    bra     _schedPickNext2Run          ; Branch if 0, no task RUNNING,
                                        ; Legal taskID: 1~15, 0 -> none
    setupFSR0    tsk_1_state_ID-1       ; Locate tsk_1_state_ID table

_schedFindRunningTaskEntry
    incf    FSR0L
    movlw   0x1F
    andwf   INDF0, w
    cpfseq  id_tsk_run                  ; Locate RUNNING task's entry
    bra     _schedFindRunningTaskEntry  ; Proceed to next task entry
    bcf     INDF0, 6                    ; Mark the task: no more RUNNING
    clrf    id_tsk_run                  ; Set running task ID to "none"

    bsf     FSR0L, 4                    ; Point to tsk_xx_activ_prio TCT
    movlw   0x0F                        ; Original code uses 0x0E, why?
    andwf   INDF0, w
    movwf   temp                        ; Extract & save task priority
                                        ; for later matching use
_testIfSamePriority
    movlw   0x0F                        ; Original code uses 0x0E, why?
    andwf   PREINC0, w
    cpfseq  temp                        ; Is it with the same priority?
    bra     _schedPickNext2Run          ; Branch to schedule if not
    bra     _RoundRobin4SamePriority    ; Else Proceed with Round Robin
                                        ; setup for the task
_RoundRobin4SamePriority
    swapTaskCtrlEntry                   ; Tasks having the same priority,
                                        ; Round Robin method used, and
                                        ; current task will be swapped
                                        ; all the way to the bottom of
                                        ; the tasks with same priority
    bcf     FSR0L, 4                    ; Swap tsk_xx_state_ID task entry
    swapTaskCtrlEntry
    bcf     FSR0L, 5                    ; Swap event_xx task entry
    swapTaskCtrlEntry
    bsf     FSR0L, 4                    ; Swap wait_xx task entry
    swapTaskCtrlEntry
    bsf     FSR0L, 5                    ; Point back to tsk_xx_activ_prio
    bra     _testIfSamePriority
    
_schedPickNext2Run
    setupFSR0    tsk_1_state_ID-1       ; Top down and hence prioritized,
                                        ; fetching next candiadte to run    
_schedTaskReadyOrNot
    incf    FSR0L
    btfss   INDF0, 5                    ; READY ?
    bra     _schedTestEndOfCtrlTable    ; Proceed to next if not READY
    btfsc   INDF0, 7                    ; WAITING?
    bra     _schedTestEndOfCtrlTable    ; It's READY, however WAITING
                                        ; for certain event
    movlb   0                           ; If READY and not WAITING then
    bsf     INDF0, 6                    ; Mark the task in RUNNING state
    movlw   0x1F
    andwf   INDF0, w
    movwf   id_tsk_run                  ; Designate the task in RUNNING

    #IFDEF  PRETASKHOOK                 ; Hook kernel service routine
        call    PreTaskHook
    #ENDIF
    
;/**********************************************************************
; * ------------------------- RESTORE CONTEXT --------------------------
; *
; * Copy the content of the context (task ram area) into Special File 
; * Registers.
; *
; **********************************************************************/
_restore_ctx
    GLOBAL  _restore_ctx
    
    movlb   0
    bsf     kernelState, 0              ; Change the kernel to USER mode
    locateTaskDescEntry
    locateStackAddrField   
    loadNextAddrTo FSR0L, FSR0H         ; Extract task's stack addr
    loadNextAddrTo startAddressL, startAddressH
                                        ; Extract task's code addr
; Go chech whether the stack overflow occurred
    goto    _checkPanic

; If the stack remains intact, restore the task's context
_restore_now
    GLOBAL  _restore_now
    movlb   0
    movff   POSTDEC1, temp
    movff   POSTDEC1, temp              ; Extract # of H/W stack entries
    clrf    STKPTR                      ; backed up previously
    
restoreNextHardwareStack
    push                                ; push to make room for restoring
    movf    POSTDEC1, w                 ; hardware stack entries
    movwf   TOSU
    movf    POSTDEC1, w
    movwf   TOSH
    movf    POSTDEC1, w
    movwf   TOSL                        ; Restore one H/W stack entry
    movf    STKPTR, w
    cpfseq  temp                        ; Is H/W stack restore done? 
    bra     restoreNextHardwareStack    ; Loopback to next restore If not

    setupFSR0    TEMP_SIZE-1            ; Load FSR0, to point to the end
                                        ; of .tmpdata + MATH_DATA section 
restoreNextTmpdataByte
    movff   POSTDEC1, POSTDEC0          ; Restore .tmpdata + MATH_DATA
    movf    FSR0L, w                    ; section
    btfss   STATUS, N
    bra     restoreNextTmpdataByte

    movff   POSTDEC1, PRODL             ; Restore the rest of SFRs saved
    movff   POSTDEC1, PRODH             ; in previously task swapping out
    movff   POSTDEC1, TABLAT
    movff   POSTDEC1, TBLPTRL
    movff   POSTDEC1, TBLPTRH
    movff   POSTDEC1, TBLPTRU
    movff   POSTDEC1, FSR0H
    movff   POSTDEC1, FSR0L
    movff   POSTDEC1, FSR2H
    movff   POSTDEC1, FSR2L
    movff   POSTDEC1, BSR
    movff   POSTDEC1, WREG
    movff   POSTDEC1, STATUS

    bsf     INTCON, 6                   ; Enable OS/low prior. interrupt
    retfie                              ; Exit to where TOS pointed at

immediat_ret
    movff   FSR0L, FSR1L                ; Here FSR0 seems to have task's
    movff   FSR0L, FSR2L                ; stack address + 2
    movff   FSR0H, FSR1H
    movff   FSR0H, FSR2H

    clrf    STKPTR                      ; Faking TOS with a pointer to
    incf    STKPTR                      ; task's start Address as if
    movf    startAddressL, w            ; there was a CALL right before
    movwf   TOSL                        ; task's start Address
    movf    startAddressH, w
    movwf   TOSH
    clrf    TOSU
    bsf     INTCON, 6                   ; Enable OS/low prior. interrupt
    retfie                              ; Branch to Task's code
    
_schedTestEndOfCtrlTable
    movlw   tsk_16_state_ID             ; Check for task ctrl table end
    subwf   FSR0L, w
    bnz     _schedTaskReadyOrNot

    movff   FSR1H_MAIN, FSR1H           ; No more READY to run, swing
    movff   FSR1L_MAIN, FSR1L           ; stack pointer back to point
                                        ; to main AP stack
_whileIdle
    movlb   0                           ; No task running
    bsf     INTCON, 6                   ; Enable OS/low prior. interrupt
    clrf    STKPTR                      ; waiting for any event to occur
    bra     _whileIdle

;/**********************************************************************
; * --------------------- CHECK STACK OVERFLOW -------------------------
; *
; **********************************************************************/
_checkPanic

    movff   FSR0L, stack_low            ; Save a copy of stack pointer
    movff   FSR0H, stack_high           ; for later recovery

; Check 0xadde signature/sentinel before the start of the task's stack
    ifSentinelDestroyGoto   _kernelPanicTrashedByNeighbor

    locateTaskDescEntry
    movff   stack_low, FSR0L
    movff   stack_high, FSR0H
    addStackSizeTo  FSR0L, FSR0H

; Check 0xadde signature/sentinel before the end of the task's stack
    ifSentinelDestroyGoto   _kernelPanicStackOverflow

    movff   stack_low, FSR0L            ; Restore FSR0 to task's 
    movff   stack_high, FSR0H           ; stack address
    movff   POSTINC0, FSR1L             ; Popup from stack top,
    movff   POSTINC0, FSR1H             ; and setup FSR1 to point to
                                        ; where context were saved
    movf    FSR1L, w                    ; Non-null means there is a
    btfss   STATUS, Z                   ; previous saved context to
    bra     _restore_now                ; be restored
    movf    FSR1H, w
    btfsc   STATUS, Z
    bra     immediat_ret                ; Return immediately if FSR1==0
    bra     _restore_now                ; else restore the context

_kernelPanicTrashedByNeighbor
    markRunningTaskSuspended            ; Chances are stack overflow of
    movff   kernelPanic, WREG           ; another task is jeopardizing
    andlw   0xF0                        ; current task
    addwf   id_tsk_run, w
    movff   WREG, kernelPanic           ; Log the task in right nibble
    bra     _sched                      ; of the kernelpanic

_kernelPanicStackOverflow
    markRunningTaskSuspended            ; Stack overflow found
    #IFDEF  RESET_ON_PANIC              ; Reset in case of KERNEL PANIC
        reset                           ; if so requested
    #ENDIF
    movff   kernelPanic, WREG
    swapf   WREG, w
    andlw   0xF0
    addwf   id_tsk_run, w
    swapf   WREG, w
    movff   WREG, kernelPanic           ; Log the task ID in left nibble
    bra     _sched                      ; of the kernelpanic

;/**********************************************************************
; * ----------------------- FOR BASIC TASK ONLY ------------------------
; *
; * After terminating a task, we loose the start address of the task, 
; * first located in the first place of the stack.
; *
; **********************************************************************/
_restore_start_adr
    GLOBAL  _restore_start_adr
    locateTaskDescEntry
    locateStackAddrField   
    loadNextAddrTo FSR0L, FSR0H

    clrf    WREG
    movwf   POSTINC0
    movwf   INDF0                       ; Set the value into STKPTR
    goto    _sched                      ; Determine the next RUNNING task

    END                                 ; Directive 'end of program'

;/* End of File : kernel.asm */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -