📄 kernel.asm
字号:
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 + -