源码
源码复制:
.func freertos_risc_v_trap_handler: addi sp, sp, -portCONTEXT_SIZE store_x x1, 1 * portWORD_SIZE( sp ) store_x x5, 2 * portWORD_SIZE( sp ) store_x x6, 3 * portWORD_SIZE( sp ) store_x x7, 4 * portWORD_SIZE( sp ) store_x x8, 5 * portWORD_SIZE( sp ) store_x x9, 6 * portWORD_SIZE( sp ) store_x x10, 7 * portWORD_SIZE( sp ) store_x x11, 8 * portWORD_SIZE( sp ) store_x x12, 9 * portWORD_SIZE( sp ) store_x x13, 10 * portWORD_SIZE( sp ) store_x x14, 11 * portWORD_SIZE( sp ) store_x x15, 12 * portWORD_SIZE( sp ) store_x x16, 13 * portWORD_SIZE( sp ) store_x x17, 14 * portWORD_SIZE( sp ) store_x x18, 15 * portWORD_SIZE( sp ) store_x x19, 16 * portWORD_SIZE( sp ) store_x x20, 17 * portWORD_SIZE( sp ) store_x x21, 18 * portWORD_SIZE( sp ) store_x x22, 19 * portWORD_SIZE( sp ) store_x x23, 20 * portWORD_SIZE( sp ) store_x x24, 21 * portWORD_SIZE( sp ) store_x x25, 22 * portWORD_SIZE( sp ) store_x x26, 23 * portWORD_SIZE( sp ) store_x x27, 24 * portWORD_SIZE( sp ) store_x x28, 25 * portWORD_SIZE( sp ) store_x x29, 26 * portWORD_SIZE( sp ) store_x x30, 27 * portWORD_SIZE( sp ) store_x x31, 28 * portWORD_SIZE( sp ) /* 读取异常(中断)号 */ csrr a1, mcause /* 计算偏移地址: id * 4 */ slli a1, a1, 2 la a0, vector_table add a1, a0, a1 /* 读取异常(中断)处理函数地址 */ lw a1, 0(a1) /* 跳转到异常(中断)处理函数 */ jalr ra, 0(a1) load_x x1, 1 * portWORD_SIZE( sp ) /* ra */ load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */ load_x x6, 3 * portWORD_SIZE( sp ) /* t1 */ load_x x7, 4 * portWORD_SIZE( sp ) /* t2 */ load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */ load_x x9, 6 * portWORD_SIZE( sp ) /* s1 */ load_x x10, 7 * portWORD_SIZE( sp ) /* a0 */ load_x x11, 8 * portWORD_SIZE( sp ) /* a1 */ load_x x12, 9 * portWORD_SIZE( sp ) /* a2 */ load_x x13, 10 * portWORD_SIZE( sp ) /* a3 */ load_x x14, 11 * portWORD_SIZE( sp ) /* a4 */ load_x x15, 12 * portWORD_SIZE( sp ) /* a5 */ load_x x16, 13 * portWORD_SIZE( sp ) /* a6 */ load_x x17, 14 * portWORD_SIZE( sp ) /* a7 */ load_x x18, 15 * portWORD_SIZE( sp ) /* s2 */ load_x x19, 16 * portWORD_SIZE( sp ) /* s3 */ load_x x20, 17 * portWORD_SIZE( sp ) /* s4 */ load_x x21, 18 * portWORD_SIZE( sp ) /* s5 */ load_x x22, 19 * portWORD_SIZE( sp ) /* s6 */ load_x x23, 20 * portWORD_SIZE( sp ) /* s7 */ load_x x24, 21 * portWORD_SIZE( sp ) /* s8 */ load_x x25, 22 * portWORD_SIZE( sp ) /* s9 */ load_x x26, 23 * portWORD_SIZE( sp ) /* s10 */ load_x x27, 24 * portWORD_SIZE( sp ) /* s11 */ load_x x28, 25 * portWORD_SIZE( sp ) /* t3 */ load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */ load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */ load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */ addi sp, sp, portCONTEXT_SIZE mret .endfunc
这段代码是一个用于FreeRTOS操作系统在RISC-V架构上的陷阱(trap)处理程序。它的作用是保存当前的CPU上下文,确定陷阱类型(异常或中断),然后跳转到对应的处理程序。处理完成后,再恢复CPU上下文并返回。
代码分析
保存上下文:
将当前CPU寄存器的内容保存到堆栈中,以便在处理完陷阱后能够恢复原状态。
addi sp, sp, -portCONTEXT_SIZE store_x x1, 1 * portWORD_SIZE( sp ) store_x x5, 2 * portWORD_SIZE( sp ) ... store_x x31, 28 * portWORD_SIZE( sp )
这里的
portCONTEXT_SIZE
定义了要保存的上下文大小,store_x
指令将寄存器内容保存到堆栈中对应的位置。读取异常(中断)号:
从
mcause
寄存器中读取异常或中断号。csrr a1, mcause
计算处理程序地址:
通过移位操作计算偏移地址,并从向量表中读取相应的处理程序地址。
slli a1, a1, 2 la a0, vector_table add a1, a0, a1 lw a1, 0(a1)
- 左移两位得到vector_table的index的原因是:A shift left can remove the interrupt bit and scale the exception codes to index into a trap vector table.
跳转到处理程序:
使用
jalr
指令跳转到计算出的处理程序地址,保存返回地址到ra
寄存器。jalr ra, 0(a1)
恢复上下文:
从堆栈中恢复寄存器内容,以恢复原来的CPU状态。
load_x x1, 1 * portWORD_SIZE( sp ) /* ra */ load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */ ... load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */ addi sp, sp, portCONTEXT_SIZE
返回到异常前的地址:
使用
mret
指令返回到异常发生前的地址。mret
关键点解释
- 保存和恢复上下文:在进入陷阱处理程序时,需要保存当前的寄存器状态,以便处理完成后可以恢复原状态。这通过调整堆栈指针和将寄存器内容存储到堆栈中实现。
- 异常和中断处理:
mcause
寄存器保存了引发陷阱的原因码,通过读取该寄存器并计算相应的向量表偏移,可以跳转到正确的处理程序。 - 向量表:
vector_table
是一个存储异常和中断处理程序地址的表,通过异常或中断号索引到具体的处理程序。 - 返回指令:
mret
指令用于从陷阱处理程序返回到正常的执行流。
总结
这段代码展示了一个典型的陷阱处理程序的结构,包括保存和恢复上下文、读取和处理陷阱原因,以及跳转到特定的处理程序。它通过有序的步骤确保在陷阱处理期间不会丢失任何CPU状态,并能正确处理和恢复异常和中断。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。