Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
risc-v_RISCV
线程上下文调度切换_context
RISC-V上下文切换汇编代码注释
发布于 2023-02-07 15:52:37 浏览:753
订阅该版
[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
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
rv666
用GDB调试人生
文章
20
回答
62
被采纳
9
关注TA
发私信
相关文章
1
modbusRTU如何避免因为被高优先级任务切走而导致本次通讯失败
2
RT-Thread 4.0.2初次上下文切换失败
3
pendSV中bx lr指令,lr指向哪里?psp中剩余的寄存器啥时候弹出的?
4
Cortex-M0在bootloader环境下的上下文切换问题?
5
arc内核移植线程切换
6
rt_thread_yield 无法在同级别中释放cpu
7
线程执行完后退出 是如何通知cpu切换任务的
8
RTT-NANO 3.1.3 线程切换问题
9
线程切换,打印出来的时间不对
10
软件定时器的回调函数里可以挂起或解挂另一个线程吗?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
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
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
I2C_IIC
UART
ESP8266
cubemx
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
ulog
SFUD
msh
C++_cpp
MicroPython
本月问答贡献
RTT_逍遥
10
个答案
2
次被采纳
xiaorui
3
个答案
2
次被采纳
winfeng
2
个答案
2
次被采纳
三世执戟
8
个答案
1
次被采纳
KunYi
8
个答案
1
次被采纳
本月文章贡献
lizimu
2
篇文章
7
次点赞
catcatbing
2
篇文章
5
次点赞
swet123
1
篇文章
4
次点赞
Days
1
篇文章
4
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部