线程与线程间上下文切换
/*
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
mre
原作者:牧尘