Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
risc-v
上下文切换
RISC-V上下文切换汇编代码注释
发布于 2023-02-07 15:52:37 浏览:134
订阅该版
[tocm] ### 线程与线程间上下文切换 ```c /* * 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 ``` ### 线程与中断间上下文切换 ```c #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 ```
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
牧尘
这家伙很懒,什么也没写!
文章
6
回答
5
被采纳
0
关注TA
发私信
相关文章
1
studio能否支持risc-v的工程,包括调试。
2
移植rt-nano至risc-v时,无法在main函数创建用户线程
3
risc-v移植rtthread,程序莫名跳转到异常Exception
4
GD32VF103出现to free a bad data block:错误
5
rtt os riscv Store address misaligned异常
6
仅实现机器模式的芯片是否可以移植RT-THREAD系统
7
nano版本移植finsh(基于risc-v)
8
C++在多核下cout打印引起崩溃
9
RT-SMART求助
10
RT-Thread在RISC-V架构的芯片上有成熟的市场项目吗?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
五分钟玩转RT-Thread新社区
5
国产MCU移植系列教程汇总,欢迎查看!
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
FinSH
ART-Pi
Bootloader
CAN总线
Hardfault
文件系统
USB
DMA
RT-Thread
线程
SCons
RT-Thread Nano
stm32
MQTT
ota
ESP8266
RTC
UART
rtthread
packages_软件包
rt-smart
freemodbus
I2C
WIZnet_W5500
flash
cubemx
FAL
定时器
AB32VG1
PWM
BSP
ADC
msh
SDIO
socket
keil
Debug
C++_cpp
LVGL
中断
编译报错
SFUD
SMP
MicroPython
本月问答贡献
宇宙码蚁
39
个答案
5
次被采纳
Ryan_CW
6
个答案
4
次被采纳
xiaorui
24
个答案
3
次被采纳
lchnu
11
个答案
2
次被采纳
rcp
9
个答案
2
次被采纳
本月文章贡献
张世争
6
篇文章
10
次点赞
YZRD
5
篇文章
8
次点赞
快乐小鸟
4
篇文章
4
次点赞
RTT_逍遥
3
篇文章
24
次点赞
recan
2
篇文章
17
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部