# interrupts and exceptions while in machine mode come here.
# the trap vector base address must always be aligned on a 4-byte boundary
.globl trap_vector
.balign 4
trap_vector:
# save context(registers).
csrrw t6, mscratch, t6 # swap t6 and mscratch
reg_save t6
# Save the actual t6 register, which we swapped into
# mscratch
mv t5, t6 # t5 points to the context of current task
csrr t6, mscratch # read t6 back from mscratch
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
# save the return address to context of current task
# save mepc to context of current task
csrr a0, mepc
STORE a0, 31*SIZE_REG(t5)
# Restore the context pointer into mscratch
csrw mscratch, t5
# call the C trap handler in trap.c
csrr a0, mepc
csrr a1, mcause
call trap_handler
# trap_handler will return the return address via a0.
csrw mepc, a0
# restore context(registers).
csrr t6, mscratch
reg_restore t6
# return to whatever we were doing before trap.
mret
.globl switch_to
.balign 4
switch_to:
csrrw t6, mscratch, t6 # swap t6 and mscratch
beqz t6, 1f # Note: the first time switch_to() is
# called, mscratch is initialized as zero
# (in sched_init()), which makes t6 zero,
# and that's the special case we have to
# handle with t6
reg_save t6 # save context of prev task
# Save the actual t6 register, which we swapped into mscratch
mv t5, t6 # t5 points to the context of current task
csrr t6, mscratch # read t6 back from mscratch
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
1:
# switch mscratch to point to the context of the next task
csrw mscratch, a0
# Restore all GP registers
# Use t6 to point to the context of the new task
mv t6, a0
reg_restore t6
# Do actual context switching.
ret
抢占式:
assembly复制代码
.globl switch_to
.balign 4
switch_to:
# switch mscratch to point to the context of the next task
csrw mscratch, a0
# set mepc to the pc of the next task
LOAD a1, 31*SIZE_REG(a0)
csrw mepc, a1
# Restore all GP registers
# Use t6 to point to the context of the new task
mv t6, a0
reg_restore t6
# Do actual context switching.
# Notice this will enable global interrupt
mret
8.2 兼容协作式多任务---- 软中断(software interrupt)
主要目的是考虑兼容协作式多任务中,出现任务完成但定时还没到,主动放弃任务的功能。
c复制代码
/*
* DESCRIPTION
* task_yield() causes the calling task to relinquish the CPU and a new
* task gets to run.
*/
void task_yield()