可以看到,thead-master的异常向量表中,除了个别异常向量以外,其余异常向量都指向了Default_Handler。这里时开发者针对中断做了处理,无论时什么异常中断进来,都先进入Default_Handler中,在Default_Handler中会对中断再做分类处理,看是正常的中断还是cpu异常或者是高等级的中断,然后再做分派。整个Default_Handler的处理流程比较长,以下截取关键点进行流程分析。
Default_Handler:
/* Check for nmi /
addi sp, sp, -8
sw t0, 0x0(sp)
sw t1, 0x4(sp)
csrr t0, mcause //mcause中记录了本次异常是否为中断,如果是中断,会包含中断号。非中断会记录异常原因
andi t0, t0, 0x3FF //获取中断号记录在t0中
li t1, 24 //thead中将24号中断规定为nmi中断,为高等级中断。
beq t0, t1, .NMI_Handler //如果是nmi中断,跳入nmi中断处理流程。
lw t0, 0x0(sp)
lw t1, 0x4(sp)
addi sp, sp, 8
j trap //跳入trap流程
trap:
/ Check for interrupt */
j .
addi sp, sp, -4
sw t0, 0x0(sp)
csrr t0, mcause //判断本次异常原因标志,若为中断,则该值是中断号
blt t0, x0, .Lirq //判断异常为中断,则跳入Lirq,否则跳入trap_c,标志cpu异常
addi sp, sp, 4
la t0, g_trap_sp
addi t0, t0, -132
.... .... .... .... .... .....
csrr a0, mepc
sw a0, 124(t0)
csrr a0, mstatus
sw a0, 128(t0)
mv a0, t0
lw t0, -4(sp)
mv sp, a0
sw t0, 16(sp)
jal trap_c
.Lirq:
lw t0, 0x0(sp)
addi sp, sp, 4
j Default_IRQHandler //跳入Default_IRQHandler处理流程
Default_IRQHandler:
ipush
#ifdef __riscv_flen
csrr t1, mstatus
srli t1, t1, 13
andi t1, t1, 0x3
la t3, irq_mstatus_fs_flag
sw t1, (t3)
li t0, 0x3
bne t1, t0, .F_RegNotSave1
.... .... ..... .....
csrr t1, mcause //再次获取中断号
andi t1, t1, 0x3FF
slli t1, t1, 2
la t0, g_irqvector //g_irqvector指向中断向量表。将其地址存放于t0中
add t0, t0, t1 //t1为当前中断相对于中断向量表的偏移,即第几个成员。t0最终为该中断对应的Handler
lw t2, (t0) //将中断对应的Handler地址放于t2中
jalr t2 //跳至Handler中
li t0, MSTATUS_PRV1
csrs mstatus, t0 |