源碼
-
源碼複製:
.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狀態,並能正確處理和恢復異常和中斷。