線程與線程間上下文切換
/*
Copyright (c) 2006-2018, RT-Thread Development Team
SPDX-License-Identifier: Apache-2.0
Change Logs:
Date Author Notes
2018/10/28 Bernard The unify RISC-V porting implementation
2018/12/27 Jesven Add SMP support
2020/11/20 BalanceTWK Add FPU support
/
#include "cpuport.h"
.globl rt_hw_interrupt_disable / 關全局中斷 /
rt_hw_interrupt_disable:
//將mstatus寄存器與立即數0x1000(8UL)對應位為1的地方置0 將mststus的值保存至a0寄存器
csrrci a0, mstatus, 8
ret / 一般返回 (return)/
.globl rt_hw_interrupt_enable
rt_hw_interrupt_enable:
csrw mstatus, a0 / 將a0的值加載至mstatus寄存器 /
ret
.globl rt_hw_context_switch_to / 調度器啟動后啟動第一個任務 /
rt_hw_context_switch_to:
LOAD sp, (a0) / 將第一個線程的線程棧加載至sp寄存器 /
LOAD a0, 2 * REGBYTES(sp) / 加載初始化時預設的mstatus寄存器值 至a0寄存器 /
csrw mstatus, a0 / 將a0寄存器的值寫入mstatus寄存器 /
j rt_hw_context_switch_exit
/ 跳轉至rt_hw_context_switch_exit函數 執行加載下文(將預設的棧中的內容加載至系統寄存器) /
.globl rt_hw_context_switch / 線程間上下文切換函數 /
rt_hw_context_switch:
/ saved from thread context
x1/ra - > sp(0)
x1/ra -> sp(1)
mstatus.mie - > sp(2)
x(i) -> sp(i-4)
/
#ifdef ARCH_RISCV_FPU / 若支持硬件浮點運算 則執行下述內容 /
addi sp, sp, -32 * FREGBYTES / 從棧中開辟出空間 保存浮點寄存器 /
FSTORE f0, 0 * FREGBYTES(sp) / 浮點寄存器保存開始 .../
FSTORE f1, 1 * FREGBYTES(sp)
FSTORE f2, 2 * FREGBYTES(sp)
FSTORE f3, 3 * FREGBYTES(sp)
FSTORE f4, 4 * FREGBYTES(sp)
FSTORE f5, 5 * FREGBYTES(sp)
FSTORE f6, 6 * FREGBYTES(sp)
FSTORE f7, 7 * FREGBYTES(sp)
FSTORE f8, 8 * FREGBYTES(sp)
FSTORE f9, 9 * FREGBYTES(sp)
FSTORE f10, 10 * FREGBYTES(sp)
FSTORE f11, 11 * FREGBYTES(sp)
FSTORE f12, 12 * FREGBYTES(sp)
FSTORE f13, 13 * FREGBYTES(sp)
FSTORE f14, 14 * FREGBYTES(sp)
FSTORE f15, 15 * FREGBYTES(sp)
FSTORE f16, 16 * FREGBYTES(sp)
FSTORE f17, 17 * FREGBYTES(sp)
FSTORE f18, 18 * FREGBYTES(sp)
FSTORE f19, 19 * FREGBYTES(sp)
FSTORE f20, 20 * FREGBYTES(sp)
FSTORE f21, 21 * FREGBYTES(sp)
FSTORE f22, 22 * FREGBYTES(sp)
FSTORE f23, 23 * FREGBYTES(sp)
FSTORE f24, 24 * FREGBYTES(sp)
FSTORE f25, 25 * FREGBYTES(sp)
FSTORE f26, 26 * FREGBYTES(sp)
FSTORE f27, 27 * FREGBYTES(sp)
FSTORE f28, 28 * FREGBYTES(sp)
FSTORE f29, 29 * FREGBYTES(sp)
FSTORE f30, 30 * FREGBYTES(sp)
FSTORE f31, 31 * FREGBYTES(sp)/ 浮點寄存器保存結束 /
#endif
addi sp, sp, -32 * REGBYTES / 從棧中開辟出空間 保存整數寄存器 /
STORE sp, (a0) / 保存sp寄存器至 from線程棧*/
STORE x1, 0 * REGBYTES(sp) /* 保存x1寄存器至 from線程棧*/
STORE x1, 1 * REGBYTES(sp) /* 保存x1寄存器至 from線程棧*/
csrr a0, mstatus /* 將mstatus寄存器的值保存至a0寄存器 /
andi a0, a0, 8 / 將a0寄存器中的值與0x1000相與 /
beqz a0, save_mpie / 判斷a0寄存器中的值是否等于0 等于0則跳轉至 save_mpie*/
li a0, 0x80 /* 非0則將立即數0x80加載至a0寄存器 /
save_mpie:
STORE a0, 2 * REGBYTES(sp) / 整數寄存器保存開始 .../
STORE x4, 4 * REGBYTES(sp)
STORE x5, 5 * REGBYTES(sp)
STORE x6, 6 * REGBYTES(sp)
STORE x7, 7 * REGBYTES(sp)
STORE x8, 8 * REGBYTES(sp)
STORE x9, 9 * REGBYTES(sp)
STORE x10, 10 * REGBYTES(sp)
STORE x11, 11 * REGBYTES(sp)
STORE x12, 12 * REGBYTES(sp)
STORE x13, 13 * REGBYTES(sp)
STORE x14, 14 * REGBYTES(sp)
STORE x15, 15 * REGBYTES(sp)
STORE x16, 16 * REGBYTES(sp)
STORE x17, 17 * REGBYTES(sp)
STORE x18, 18 * REGBYTES(sp)
STORE x19, 19 * REGBYTES(sp)
STORE x20, 20 * REGBYTES(sp)
STORE x21, 21 * REGBYTES(sp)
STORE x22, 22 * REGBYTES(sp)
STORE x23, 23 * REGBYTES(sp)
STORE x24, 24 * REGBYTES(sp)
STORE x25, 25 * REGBYTES(sp)
STORE x26, 26 * REGBYTES(sp)
STORE x27, 27 * REGBYTES(sp)
STORE x28, 28 * REGBYTES(sp)
STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp) / 整數寄存器保存結束 /
LOAD sp, (a1) / 加載to線程棧至sp /
j rt_hw_context_switch_exit / 跳轉至rt_hw_context_switch_exit函數 執行加載下文 /
.global rt_hw_context_switch_exit/ 加載下文函數 /
rt_hw_context_switch_exit:
/ resw ra to mepc /
LOAD a0, 0 * REGBYTES(sp) / 將to線程的棧加載至a0寄存器 /
csrw mepc, a0 / 將to線程的pc加載至mepc 退出后自動將mepc寄存器的值更新值系統pc寄存器 /
LOAD x1, 1 * REGBYTES(sp)/ 加載ra寄存器的值至x1寄存器 /
li t0, 0x00007800/ 加載立即數0x00007800至t0(臨時寄存器) /
csrw mstatus, t0 / 將t0寄存器中的值寫入mstatus寄存器*/
LOAD a0, 2 * REGBYTES(sp)/* 加載保存的mstatus的值 /
csrs mstatus, a0/ 將mstatus中與a0寄存器對應位為1的地方置0 /
LOAD x4, 4 * REGBYTES(sp) / 恢復整數寄存器 /
LOAD x5, 5 * REGBYTES(sp)
LOAD x6, 6 * REGBYTES(sp)
LOAD x7, 7 * REGBYTES(sp)
LOAD x8, 8 * REGBYTES(sp)
LOAD x9, 9 * REGBYTES(sp)
LOAD x10, 10 * REGBYTES(sp)
LOAD x11, 11 * REGBYTES(sp)
LOAD x12, 12 * REGBYTES(sp)
LOAD x13, 13 * REGBYTES(sp)
LOAD x14, 14 * REGBYTES(sp)
LOAD x15, 15 * REGBYTES(sp)
LOAD x16, 16 * REGBYTES(sp)
LOAD x17, 17 * REGBYTES(sp)
LOAD x18, 18 * REGBYTES(sp)
LOAD x19, 19 * REGBYTES(sp)
LOAD x20, 20 * REGBYTES(sp)
LOAD x21, 21 * REGBYTES(sp)
LOAD x22, 22 * REGBYTES(sp)
LOAD x23, 23 * REGBYTES(sp)
LOAD x24, 24 * REGBYTES(sp)
LOAD x25, 25 * REGBYTES(sp)
LOAD x26, 26 * REGBYTES(sp)
LOAD x27, 27 * REGBYTES(sp)
LOAD x28, 28 * REGBYTES(sp)
LOAD x29, 29 * REGBYTES(sp)
LOAD x30, 30 * REGBYTES(sp)
LOAD x31, 31 * REGBYTES(sp)
addi sp, sp, 32 * REGBYTES
#ifdef ARCH_RISCV_FPU
FLOAD f0, 0 * FREGBYTES(sp) / 恢復浮點寄存器 */
FLOAD f1, 1 * FREGBYTES(sp)
FLOAD f2, 2 * FREGBYTES(sp)
FLOAD f3, 3 * FREGBYTES(sp)
FLOAD f4, 4 * FREGBYTES(sp)
FLOAD f5, 5 * FREGBYTES(sp)
FLOAD f6, 6 * FREGBYTES(sp)
FLOAD f7, 7 * FREGBYTES(sp)
FLOAD f8, 8 * FREGBYTES(sp)
FLOAD f9, 9 * FREGBYTES(sp)
FLOAD f10, 10 * FREGBYTES(sp)
FLOAD f11, 11 * FREGBYTES(sp)
FLOAD f12, 12 * FREGBYTES(sp)
FLOAD f13, 13 * FREGBYTES(sp)
FLOAD f14, 14 * FREGBYTES(sp)
FLOAD f15, 15 * FREGBYTES(sp)
FLOAD f16, 16 * FREGBYTES(sp)
FLOAD f17, 17 * FREGBYTES(sp)
FLOAD f18, 18 * FREGBYTES(sp)
FLOAD f19, 19 * FREGBYTES(sp)
FLOAD f20, 20 * FREGBYTES(sp)
FLOAD f21, 21 * FREGBYTES(sp)
FLOAD f22, 22 * FREGBYTES(sp)
FLOAD f23, 23 * FREGBYTES(sp)
FLOAD f24, 24 * FREGBYTES(sp)
FLOAD f25, 25 * FREGBYTES(sp)
FLOAD f26, 26 * FREGBYTES(sp)
FLOAD f27, 27 * FREGBYTES(sp)
FLOAD f28, 28 * FREGBYTES(sp)
FLOAD f29, 29 * FREGBYTES(sp)
FLOAD f30, 30 * FREGBYTES(sp)
FLOAD f31, 31 * FREGBYTES(sp)
addi sp, sp, 32 * FREGBYTES
#endif
mret
線程與中斷間上下文切換
#include "cpuport.h"
.section .isr_vector, "ax"
.global irq_handler_trap
.align 2
irq_handler_trap: /* 中斷執行過程中的上下文切換 /
#ifdef ARCH_RISCV_FPU
addi sp, sp, -32 * FREGBYTES / 從棧中開辟出空間 保存浮點寄存器 /
FSTORE f0, 0 * FREGBYTES(sp)
FSTORE f1, 1 * FREGBYTES(sp)
FSTORE f2, 2 * FREGBYTES(sp)
FSTORE f3, 3 * FREGBYTES(sp)
FSTORE f4, 4 * FREGBYTES(sp)
FSTORE f5, 5 * FREGBYTES(sp)
FSTORE f6, 6 * FREGBYTES(sp)
FSTORE f7, 7 * FREGBYTES(sp)
FSTORE f8, 8 * FREGBYTES(sp)
FSTORE f9, 9 * FREGBYTES(sp)
FSTORE f10, 10 * FREGBYTES(sp)
FSTORE f11, 11 * FREGBYTES(sp)
FSTORE f12, 12 * FREGBYTES(sp)
FSTORE f13, 13 * FREGBYTES(sp)
FSTORE f14, 14 * FREGBYTES(sp)
FSTORE f15, 15 * FREGBYTES(sp)
FSTORE f16, 16 * FREGBYTES(sp)
FSTORE f17, 17 * FREGBYTES(sp)
FSTORE f18, 18 * FREGBYTES(sp)
FSTORE f19, 19 * FREGBYTES(sp)
FSTORE f20, 20 * FREGBYTES(sp)
FSTORE f21, 21 * FREGBYTES(sp)
FSTORE f22, 22 * FREGBYTES(sp)
FSTORE f23, 23 * FREGBYTES(sp)
FSTORE f24, 24 * FREGBYTES(sp)
FSTORE f25, 25 * FREGBYTES(sp)
FSTORE f26, 26 * FREGBYTES(sp)
FSTORE f27, 27 * FREGBYTES(sp)
FSTORE f28, 28 * FREGBYTES(sp)
FSTORE f29, 29 * FREGBYTES(sp)
FSTORE f30, 30 * FREGBYTES(sp)
FSTORE f31, 31 * FREGBYTES(sp)
#endif
/ save all from thread context /
addi sp, sp, -32 * REGBYTES / 從棧中開辟出空間 保存整數寄存器 /
STORE x1, 1 * REGBYTES(sp) // ra
li t0, 0x80 / 將立即數0x10000000加載至t0寄存器 /
STORE t0, 2 * REGBYTES(sp) / 將t0寄存器的值保存至 from線程棧 /
STORE x4, 4 * REGBYTES(sp) // tp - thread pointer
STORE x5, 5 * REGBYTES(sp) // t0
STORE x6, 6 * REGBYTES(sp) // t1
STORE x7, 7 * REGBYTES(sp) // t2
STORE x8, 8 * REGBYTES(sp) // s0/fp
STORE x9, 9 * REGBYTES(sp) // s1
STORE x10, 10 * REGBYTES(sp) // a0
STORE x11, 11 * REGBYTES(sp) // a1
STORE x12, 12 * REGBYTES(sp) // a2
STORE x13, 13 * REGBYTES(sp) // a3
STORE x14, 14 * REGBYTES(sp) // a4
STORE x15, 15 * REGBYTES(sp) // a5
STORE x16, 16 * REGBYTES(sp) // a6
STORE x17, 17 * REGBYTES(sp) // a7
STORE x18, 18 * REGBYTES(sp) // s2
STORE x19, 19 * REGBYTES(sp) // s3
STORE x20, 20 * REGBYTES(sp) // s4
STORE x21, 21 * REGBYTES(sp) // s5
STORE x22, 22 * REGBYTES(sp) // s6
STORE x23, 23 * REGBYTES(sp) // s7
STORE x24, 24 * REGBYTES(sp) // s8
STORE x25, 25 * REGBYTES(sp) // s9
STORE x26, 26 * REGBYTES(sp) // s10
STORE x27, 27 * REGBYTES(sp) // s11
STORE x28, 28 * REGBYTES(sp) // t3
STORE x29, 29 * REGBYTES(sp) // t4
STORE x30, 30 * REGBYTES(sp) // t5
STORE x31, 31 * REGBYTES(sp) // t6
/ 將sp寄存器的值保存值mscratch mscratch在機器模式下可快速交換數據 /
csrw mscratch, sp
/ 切換至中斷棧 /
la sp, _stack
/ 進入中斷 /
call rt_interrupt_enter
/ 將線程棧加載為入口參數 0*/
csrr a0, mscratch
call trap_entry /* 調用中斷處理函數 /
call rt_interrupt_leave / 退出中斷 /
/ 切換至線程棧 /
csrr sp, mscratch
/ 判斷是否在中斷處理過程中觸發了調度 /
la s0, rt_thread_switch_interrupt_flag / 將rt_thread_switch_interrupt_flag的地址加載至s0 /
lw s2, 0(s0) / 將s0地址處的值加載至s2寄存器 /
beqz s2, spurious_interrupt / 判斷s2寄存器中的值是否為0 等于0則不進行線程棧的切換 /
/ clear switch interrupt flag /
sw zero, 0(s0) / 將s0寄存器的值清零 /
csrr a0, mepc / 將mepc的值保存至a0寄存器 /
STORE a0, 0 * REGBYTES(sp)/ 將a0寄存器的值寫入線程棧中 /
la s0, rt_interrupt_from_thread/ 將rt_interrupt_from_thread的地址加載至s0寄存器 /
LOAD s1, 0(s0)/ 將from線程的線程棧加載至s1寄存器 /
STORE sp, 0(s1)/ 將sp寄存器的值存儲至from線程棧 /
la s0, rt_interrupt_to_thread / 將rt_interrupt_to_thread的地址加載至s0寄存器 /
LOAD s1, 0(s0)/ 將to線程的線程棧加載至s1寄存器 /
LOAD sp, 0(s1)/ 將s1寄存器中的值加載至sp寄存器 /
LOAD a0, 0 * REGBYTES(sp) / 將to線程棧的pc加載至a0寄存器 /
csrw mepc, a0/ 將a0寄存器的值寫入mepc寄存器 /
spurious_interrupt:
LOAD x1, 1 * REGBYTES(sp) // ra / 加載ra寄存器值至x1 /
/ Remain in M-mode after mret /
li t0, 0x00001800 / 加載立即數0x00001800至t0寄存器 /
csrs mstatus, t0 / 將t0寄存器中為1的位置與mstatus寄存器中對應的位置置1*/
LOAD t0, 2 * REGBYTES(sp) /* 加載保存的mstatus寄存器的值至t0*/
csrs mstatus, t0 /* 將t0寄存器中為1的位置與mstatus寄存器中對應的位置置1*/
LOAD x4, 4 * REGBYTES(sp) // tp /* 恢復整數寄存器值 /
LOAD x5, 5 * REGBYTES(sp) // t0
LOAD x6, 6 * REGBYTES(sp) // t1
LOAD x7, 7 * REGBYTES(sp) // t2
LOAD x8, 8 * REGBYTES(sp) // s0/fp
LOAD x9, 9 * REGBYTES(sp) // s1
LOAD x10, 10 * REGBYTES(sp) // a0
LOAD x11, 11 * REGBYTES(sp) // a1
LOAD x12, 12 * REGBYTES(sp) // a2
LOAD x13, 13 * REGBYTES(sp) // a3
LOAD x14, 14 * REGBYTES(sp) // a4
LOAD x15, 15 * REGBYTES(sp) // a5
LOAD x16, 16 * REGBYTES(sp) // a6
LOAD x17, 17 * REGBYTES(sp) // a7
LOAD x18, 18 * REGBYTES(sp) // s2
LOAD x19, 19 * REGBYTES(sp) // s3
LOAD x20, 20 * REGBYTES(sp) // s4
LOAD x21, 21 * REGBYTES(sp) // s5
LOAD x22, 22 * REGBYTES(sp) // s6
LOAD x23, 23 * REGBYTES(sp) // s7
LOAD x24, 24 * REGBYTES(sp) // s8
LOAD x25, 25 * REGBYTES(sp) // s9
LOAD x26, 26 * REGBYTES(sp) // s10
LOAD x27, 27 * REGBYTES(sp) // s11
LOAD x28, 28 * REGBYTES(sp) // t3
LOAD x29, 29 * REGBYTES(sp) // t4
LOAD x30, 30 * REGBYTES(sp) // t5
LOAD x31, 31 * REGBYTES(sp) // t6 / 恢復整數寄存器值結束 /
addi sp, sp, 32 * REGBYTES / 移動棧指針 /
#ifdef ARCH_RISCV_FPU
FLOAD f0, 0 * FREGBYTES(sp) / 恢復浮點寄存器值 /
FLOAD f1, 1 * FREGBYTES(sp)
FLOAD f2, 2 * FREGBYTES(sp)
FLOAD f3, 3 * FREGBYTES(sp)
FLOAD f4, 4 * FREGBYTES(sp)
FLOAD f5, 5 * FREGBYTES(sp)
FLOAD f6, 6 * FREGBYTES(sp)
FLOAD f7, 7 * FREGBYTES(sp)
FLOAD f8, 8 * FREGBYTES(sp)
FLOAD f9, 9 * FREGBYTES(sp)
FLOAD f10, 10 * FREGBYTES(sp)
FLOAD f11, 11 * FREGBYTES(sp)
FLOAD f12, 12 * FREGBYTES(sp)
FLOAD f13, 13 * FREGBYTES(sp)
FLOAD f14, 14 * FREGBYTES(sp)
FLOAD f15, 15 * FREGBYTES(sp)
FLOAD f16, 16 * FREGBYTES(sp)
FLOAD f17, 17 * FREGBYTES(sp)
FLOAD f18, 18 * FREGBYTES(sp)
FLOAD f19, 19 * FREGBYTES(sp)
FLOAD f20, 20 * FREGBYTES(sp)
FLOAD f21, 21 * FREGBYTES(sp)
FLOAD f22, 22 * FREGBYTES(sp)
FLOAD f23, 23 * FREGBYTES(sp)
FLOAD f24, 24 * FREGBYTES(sp)
FLOAD f25, 25 * FREGBYTES(sp)
FLOAD f26, 26 * FREGBYTES(sp)
FLOAD f27, 27 * FREGBYTES(sp)
FLOAD f28, 28 * FREGBYTES(sp)
FLOAD f29, 29 * FREGBYTES(sp)
FLOAD f30, 30 * FREGBYTES(sp)
FLOAD f31, 31 * FREGBYTES(sp) / 恢復浮點寄存器值結束 /
addi sp, sp, 32 * FREGBYTES / 移動棧指針 */
#endif
mret
-
寄存器
+關注
關注
31文章
5355瀏覽量
120513 -
中斷處理
+關注
關注
0文章
94瀏覽量
10977 -
RT-Thread
+關注
關注
31文章
1293瀏覽量
40192 -
RISC-V
+關注
關注
45文章
2292瀏覽量
46198
發布評論請先 登錄
相關推薦
評論