Cortex-M与RISC-V区别
环境
Cortex-M以STM32H750为代表,RISC-V以芯来为代表
RTOS版本为RT-Thread 4.1.1
寄存器

RISC-V

常用汇编
RISC-V
关于STORE x4, 4(sp)这种寄存器前面带数字的写法,其意思为将x4的值存入sp+4这个地址,即前面的数字表示偏移的意思
反之LOAD表示从内存里面取值
la
地址加载 (Load Address). 伪指令(Pseudoinstruction), RV32I and RV64I.
la rd, symbol x[rd] = &symbol
例如将函数irq_entry()的地址放入t0中
la t0, irq_entry
mv
移动(Move). 伪指令(Pseudoinstruction), RV32I and RV64I.
mv rd, rs1 x[rd] = x[rs1]
把寄存器 x[rs1]复制到 x[rd]中。实际被扩展为 addi rd, rs1, 0
addi
加立即数(Add Immediate). I-type, RV32I and RV64I.
把符号位扩展的立即数加到寄存器 x[rs1]上,结果写入 x[rd]。忽略算术溢出。
addi rd, rs1, immediate x[rd] = x[rs1] + sext(immediate)
add
加 (Add). R-type, RV32I and RV64I.
把寄存器 x[rs2]加到寄存器 x[rs1]上,结果写入 x[rd]。忽略算术溢出。
add rd, rs1, rs2 x[rd] = x[rs1] + x[rs2]
压缩形式:c.add rd, rs2; c.mv rd, rs2
Cortex-M
中断与异常处理
中断与异常入口
Cortex-M
Cortex-M在启动文件中会初始化一个中断向量表,所有的异常和中断根据这个表的地址跳转
; Vector Table Mapped to Address 0 at ResetAREA RESET, DATA, READONLYEXPORT __VectorsEXPORT __Vectors_EndEXPORT __Vectors_Size__Vectors DCD __initial_sp ; Top of StackDCD Reset_Handler ; Reset HandlerDCD NMI_Handler ; NMI HandlerDCD HardFault_Handler ; Hard Fault HandlerDCD MemManage_Handler ; MPU Fault HandlerDCD BusFault_Handler ; Bus Fault HandlerDCD UsageFault_Handler ; Usage Fault HandlerDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD SVC_Handler ; SVCall HandlerDCD DebugMon_Handler ; Debug Monitor HandlerDCD 0 ; ReservedDCD PendSV_Handler ; PendSV HandlerDCD SysTick_Handler ; SysTick Handler; External InterruptsDCD WWDG_IRQHandler ; Window WatchDog interrupt ( wwdg1_it) DCD PVD_AVD_IRQHandler ; PVD/AVD through EXTI Line detection
RISC-V
RISC-V的异常会跳入所有异常共享的异常处理程序入口mtvec,在启动文件中的初始化如下:
exc_entry由汇编编写,其中又会调用core_exception_handler()
/** Set Exception Entry MTVEC to exc_entry* Due to settings above, Exception and NMI* will share common entry.*/la t0, exc_entrycsrw CSR_MTVEC, t0
ECLIC 的每个中断源均可以设置成向量或者非向量处理(通过寄存器 clicintattr[i]的 shv 域),其要点如下:
当 mtvec.MODE != 6’b000011 时,处理器使用默认中断模式
mtvec.MODE = 6’b000011 时,处理器使用ECLIC 中断模式,推荐使用此模式。
/* Set the interrupt processing mode to ECLIC mode */la t0, 0x3fcsrc CSR_MTVEC, t0csrs CSR_MTVEC, 0x3
-
如果被配置成为向量处理模式,则该中断被处理器内核响应后,处理器直接跳入该中断的向量入口(Vector Table Entry)存储的目标地址
-
如果被配置成为非向量处理模式,则该中断被处理器内核响应后,处理器直接跳入所有中断共享的入口地址
默认情况下异常和所有非向量中断共享入口地址(不推荐),推荐将 CSR 寄存器 mtvt2 的最低位设置为 1,则所有非向量中断共享的入口地址由 CSR 寄
存器 mtvt2 的值(忽略最低 2 位的值)指定/** Set ECLIC non-vector entry to be controlled* by mtvt2 CSR register.* Intialize ECLIC non-vector interrupt* base address mtvt2 to irq_entry.*/la t0, irq_entrycsrw CSR_MTVT2, t0csrs CSR_MTVT2, 0x1
进入irq_entry后会自动关闭中断MIE
保存完上下文之后会调用对应中断服务程序,在跳入中断服务程序的同时,硬件也会同时打开中断的全局使能
中断服务程序执行完成之后需要将中断全局使能再次关闭,保证恢复上下文的原子性
MPIE会记录异常发生前得MIE值,以便异常结束时恢复到原来的值
csrrw ra, CSR_JALMNXTI, ra
在跳入中断服务程序的同时,“csrrw ra, CSR_JALMNXTI, ra”指令还会达到 JAL(Jump and Link)的效果,硬件同时更新 Link 寄存器的值为该指令的 PC 自身作为函数调用的返回地址。因此,从中断服务程序函数返回后会回到该“csrrw ra,CSR_JALMNXTI, ra”指令重新执行,重新判断是否还有中断在等待(Pending),从而达到中断咬尾的效果。如果没有中断在等待(Pending),则该指令相当于是个 Nop 指令不做任何操作。
对于中断嵌套,会重新从irq_entry进入
保存上下文
Cortex-M
当Cortex-M开始响应一个中断时,会自动完成如下操作:
-
入栈: 自动把8个寄存器的值压入栈
-
取向量:从向量表中找出对应的服务程序入口地址
-
选择堆栈指针MSP/PSP,更新堆栈指针SP,更新连接寄存器LR,更新程序计数器PC
响应异常的第一个行动,就是自动保存现场的必要部分:依次把xPSR, PC, LR, R12以及R3‐R0由硬件自动压入适当的堆栈中:如果当响应异常时,当前的代码正在使用PSP,则压入PSP,即使用线程堆栈;否则压入MSP,使用主堆栈。一旦进入了服务例程,就将一直使用主堆栈。
压栈顺序如下:
| 地址(设原SP为 N-0) | 寄存器 | 被保存的顺序 |
|---|---|---|
| N-4 | xPSR | 2 |
| N-8 | PC | 1 |
| N-12 | LR | 8 |
| N-16 | R12 | 7 |
| N-20 | R3 | 6 |
| N-24 | R2 | 5 |
| N-28 | R1 | 4 |
| N-32 (新SP也指向这里) | R0 | 3 |
RISC-V
RISC-V 架构的处理器在进入和退出中断处理模式时没有硬件自动保存和恢复上下文(通用寄存器)的操作,因此需要软件明确地使用(汇编语言编写的)指令进行上下文的保存和恢复。根据中断是向量处理模式还是非向量处理模式,上下文的保存和恢复涉及到的内容会有所差异
在上述异常exc_entry和中断irq_entry中,都有SAVE_CONTEXT和RESTORE_CONTEXT来保存上下文和恢复上下文
.macro SAVE_CONTEXTcsrrw sp, CSR_MSCRATCHCSWL, sp/* Allocate stack space for context saving */addi sp, sp, -20*REGBYTESSTORE x1, 0*REGBYTES(sp)STORE x4, 1*REGBYTES(sp)STORE x5, 2*REGBYTES(sp)STORE x6, 3*REGBYTES(sp)STORE x7, 4*REGBYTES(sp)STORE x10, 5*REGBYTES(sp)STORE x11, 6*REGBYTES(sp)STORE x12, 7*REGBYTES(sp)STORE x13, 8*REGBYTES(sp)STORE x14, 9*REGBYTES(sp)STORE x15, 10*REGBYTES(sp)STORE x16, 14*REGBYTES(sp)STORE x17, 15*REGBYTES(sp)STORE x28, 16*REGBYTES(sp)STORE x29, 17*REGBYTES(sp)STORE x30, 18*REGBYTES(sp)STORE x31, 19*REGBYTES(sp)
.endm.macro RESTORE_CONTEXTLOAD x1, 0*REGBYTES(sp)LOAD x4, 1*REGBYTES(sp)LOAD x5, 2*REGBYTES(sp)LOAD x6, 3*REGBYTES(sp)LOAD x7, 4*REGBYTES(sp)LOAD x10, 5*REGBYTES(sp)LOAD x11, 6*REGBYTES(sp)LOAD x12, 7*REGBYTES(sp)LOAD x13, 8*REGBYTES(sp)LOAD x14, 9*REGBYTES(sp)LOAD x15, 10*REGBYTES(sp)LOAD x16, 14*REGBYTES(sp)LOAD x17, 15*REGBYTES(sp)LOAD x28, 16*REGBYTES(sp)LOAD x29, 17*REGBYTES(sp)LOAD x30, 18*REGBYTES(sp)LOAD x31, 19*REGBYTES(sp)addi sp, sp, 20*REGBYTEScsrrw sp, CSR_MSCRATCHCSWL, sp
.endm
还有SAVE_CSR_CONTEXT和RESTORE_CSR_CONTEXT来保存和恢复这三个MCAUSE MEPC MSUBMCSR寄存器
例如下面的第一条命令表示把MCAUSE存到SP+11*4的位置,正好上面留了三个位置给CSR寄存器
/*** \brief Macro for save necessary CSRs to stack* \details* This macro store MCAUSE, MEPC, MSUBM to stack.*/
.macro SAVE_CSR_CONTEXT/* Store CSR mcause to stack using pushmcause */csrrwi x5, CSR_PUSHMCAUSE, 11/* Store CSR mepc to stack using pushmepc */csrrwi x5, CSR_PUSHMEPC, 12/* Store CSR msub to stack using pushmsub */csrrwi x5, CSR_PUSHMSUBM, 13
.endm.macro RESTORE_CSR_CONTEXTLOAD x5, 13*REGBYTES(sp)csrw CSR_MSUBM, x5LOAD x5, 12*REGBYTES(sp)csrw CSR_MEPC, x5LOAD x5, 11*REGBYTES(sp)csrw CSR_MCAUSE, x5
.endm
栈指针的切换
Cortex-M
Cortex-M有主栈MSP和线程栈PSP自动切换,默认是使用的MSP,那么疑问来了,怎么使用线程栈呢?
PendSV_Handler PROC
switch_to_threadLDR r1, =rt_interrupt_to_threadLDR r1, [r1]LDR r1, [r1] ; load thread stack pointerLDMFD r1!, {r4 - r11} ; pop r4 - r11 registerMSR psp, r1 ; update stack pointerpendsv_exit; restore interruptMSR PRIMASK, r2ORR lr, lr, #0x04BX lrENDP
在线程切换的时候,会把线程的sp——rt_interrupt_to_thread赋给psp
在进入异常服务程序后,LR的值被自动更新为特殊的EXC_RETURN,所以只需要在异常中将LR的bit2置1就可以切换PSP了
EXC_RETURN会根据进入异常前的模式和SP使用情况生成(保持进入异常前的值),理论上只用第一次线程切换时手动把MSP改成PSP
| EXC_RETURN位段 | 含义 |
|---|---|
| [31:4] | EXC_RETURN的标识:必须全为1 |
| 3 | 0=返回后进入Handler模式 1=返回后进入线程模式 |
| 2 | 0=从主堆栈中做出栈操作,返回后使用MSP, 1=从进程堆栈中做出栈操作,返回后使用PSP |
| 1 | 保留,必须为0 |
| 0 | 0=返回ARM状态。 1=返回Thumb状态。在CM3中必须为1 |
LR在函数调用时会自动更新,对于函数的返回,将LR出栈给PC即可
在异常退出时,也会将LR赋给PC,但是很显然这不是代码空间的地址,系统会根据标识检测到这是一条EXC_RETURN命令,进一步根据进入中断时入栈的PC进行返回

RISC-V
在保存上下文和恢复上下文中都有如下语句:
csrrw sp, CSR_MSCRATCHCSWL, sp
mscratchcswl 寄存器用于在多个中断 level 间切换时,交换目的寄存器与 mscratch 的值来加速中断处理
使用带读操作的 CSR 指令访问 mscratchcsw,当特权模式不变,在出现中断程序和应用程序的切换时,有以下伪指令所示的寄存器操作:
mcause.mpil表示前一个中断级别
mintstatus.mil表示Machine Mode 的有效中断级别
csrrw rd, mscratchcswl, rs1// Pseudocode operation.
// 栈指针的切换只在中断中操作,mintstatus.mil肯定不为0
// 如果mcause.mpil==0表示从线程中进入的中断(待验证),即判断成立,使用mscratch和SP交换来加载主栈
// RESTORE_CONTEXT中再次调用即再次交互,把主栈存入mscratch并把线程栈交换到SP中
if ( (mcause.mpil==0) != (mintstatus.mil == 0) )
{t = rs1; rd = mscratch; mscratch = t;
}
else
{ // 中断嵌套使用同一个栈,不需要改变rd = rs1; // mscratch unchanged.
}
// Usual use: csrrw sp, mscratchcswl, sp
看到这里,就会有一个疑问,第一次进中断时,mscratch中的内容从哪里来呢?
rt_hw_context_switch_to表示没有来源即第一次切换线程(在开始OS调度时调用,不是在中断切换)
所以第一次切换线程时会将主栈存入mscratch,之后就不需要再管了
之后便线程栈赋值给sp
rt_hw_context_switch_to:/* Setup Interrupt Stack usingThe stack that was used by main()before the scheduler is started isno longer required after the scheduler is started.Interrupt stack pointer is stored in CSR_MSCRATCH */la t0, _spcsrw CSR_MSCRATCH, t0LOAD sp, 0x0(a0) /* Read sp from first TCB member(a0) */
在进入中断时,mepc 寄存器被同时更新,以反映当时遇到中断时的 PC 值。软件必须使用 mret指令退出中断,执行 mret 指令后处理器将从 mepc 定义的 pc 地址重新开始执行。通过这个机制,意味着 mret 指令执行后处理器回到了当时遇到中断时的 PC 地址,从而可以继续执行之前被中止的程序流。


相关文章:
Cortex-M与RISC-V区别
环境 Cortex-M以STM32H750为代表,RISC-V以芯来为代表 RTOS版本为RT-Thread 4.1.1 寄存器 RISC-V 常用汇编 RISC-V 关于STORE x4, 4(sp)这种寄存器前面带数字的写法,其意思为将x4的值存入sp4这个地址,即前面的数字表示偏移的意思 反之LOA…...
YashanDB入选2023年世界互联网大会领先科技奖成果集《科技之魅》
近日,由深圳计算科学研究院自主研发的“崖山数据库系统YashanDB”入编2023年世界互联网大会领先科技奖成果集《科技之魅》。此次入选,充分彰显了YashanDB在数据库技术领域的突破性创新成果。 《科技之魅》是世界互联网大会领先科技奖的重要成果ÿ…...
C语言基础程序设计题
1.个人所得税计算 应纳税款的计算公式如下:收入<=1000元部分税率为0%,2000元>=收入>1000元的部分税率为5%,3000元>=收入>2000元的部分税率为10%…...
Spring Boot实现图片上传和展示
Spring Boot实现图片上传和展示 本文将介绍如何使用Spring Boot框架搭建后端服务,实现接收前端上传的图片并保存到resources/images目录下。同时,我们还将展示如何在前端编写一个HTML页面,实现上传图片和从resources/images目录下获取图片并…...
大数据-之LibrA数据库系统告警处理(ALM-37015 Gaussdb进程可用文件句柄资源不足)
告警解释 操作系统环境文件句柄不足时,产生该告警。 告警属性 告警ID 告警级别 可自动清除 37015 严重 是 告警参数 参数名称 参数含义 ServiceName 产生告警的服务名称 RoleName 产生告警的角色名称 HostName 产生告警的主机名 Instance 产生告警…...
大一学编程怎么学?刚接触编程怎么学习,有没有中文编程开发语言工具?
大一学编程怎么学?刚接触编程怎么学习,有没有中文编程开发语言工具? 1、大一刚开始学编程,面对复杂的代码学习非常吃力,很难入门。建议刚接触编程可以先学习中文编程,了解其中的编程逻辑,学编程…...
GoWeb学习-第二天
文章目录 从零开始学Go web——第二天一、安装Go语言二、建立web目录2.1 创建GO语言包目录2.2 创建Go web文件 三、编译并运行Go web应用3.1 编译并运行3.2 查看结果 从零开始学Go web——第二天 第一天我们了解了与web息息相关的HTTP协议,聊了聊Go与web的关系等…...
04-鸿蒙4.0学习之样式装饰器相关
04-鸿蒙4.0学习之样式装饰器 styles装饰器:定义组件重用样式 /*** styles装饰器:定义组件重用样式*/ Entry Component struct StyleUI {State message: string stylesStyles commonStyle(){.width(200).height(100).backgroundColor(Color.Gray).marg…...
C# 线程(1)
目录 1 线程与进程2 创建线程3 线程等待4 线程优先级5 前台线程与后台线程6 Lock与线程安全7 Monitor8 死锁9 线程中异常处理 1 线程与进程 进程是计算机概念,一个程序运用时占用的的所有计算机资源(CPU、内存、硬盘、网络)统称为进程。 线程…...
冒泡排序以及改进方案
冒泡排序以及改进方案 介绍: 冒泡排序属于一种典型的交换排序(两两比较)。冒泡排序就像是把一杯子里的气泡一个个往上冒一样。它不断比较相邻的元素,如果顺序不对就像水泡一样交换它们的位置,直到整个序列像水泡一样…...
QTextEdit 是 Qt 框架中的一个类,用于显示和编辑多行文本内容的可编辑部件
QTextEdit 是 Qt 框架中的一个类,用于显示和编辑多行文本内容的可编辑部件。 QTextEdit 提供了一个用于显示和编辑富文本(包括格式化文本、图像和链接等)和纯文本的文本编辑器。它支持基本的文本操作(如复制、粘贴、撤销、重做等…...
vue+jsonp编写可导出html的模版,可通过外部改json动态更新页面内容
效果 导出后文件结果如图所示,点击Index.html即可查看页面,页面所有数据由report.json控制,修改report.json内容即可改变index.html展示内容 具体实现 1. 编写数据存储的json文件 在index.html所在的public页面新建report.json文件ÿ…...
查看各ip下的连接数
netstat -n | awk /^tcp/ {print $5} | awk -F: {print $1} | sort | uniq -c| sort -rn netstat -n:显示所有的网络连接,不包括任何服务名的解释。awk /^tcp/ {print $5}:使用awk命令过滤出tcp协议的连接,并打印出每个连接的第五…...
Linux—进程状态
目录 一.前言 1.1.通过系统调用获取进程标示符 1.2.通过系统调用创建进程 二.进程状态 三.Z(zombie)-僵尸进程 四.僵尸进程危害 一.前言 学习进程的状态,我们首先了解一下进程的基本数据 1.1.通过系统调用获取进程标示符 由getpid()…...
万宾科技可燃气体监测仪科技作用全览
燃气管网在运行过程中经常会遇到燃气管道泄漏的问题,燃气泄漏甚至会引起爆炸,从而威胁人民的生命和财产安全,因此对燃气管网进行定期巡检是十分必要的工作。但是传统的人工巡检已不能满足城市的需要,除了选择增加巡检人员之外&…...
Python与GPU编程快速入门(三)
3、使用Numba加速Python代码 Numba 是一个 Python 库,它使用行业标准 LLVM 编译器库在运行时将 Python 函数转换为优化的机器代码。 您可能想尝试用它来加速 CPU 上的代码。 然而,Numba还可以将Python 语言的子集转换为CUDA,这就是我们将在这里使用的。 所以我们的想法是,…...
praseInt 和 逻辑或连用
这是做项目时遇到json文件转换 的一个小坑 将json 对象中的值 由字符串(数字字符串) 转换为 数值类型,如果是 转换失败 ,就返回 -1 这里的 parseInt 看起来非常简洁,但是存在一个小坑 transformedData[fieldsToCheck[i]] parseInt(origina…...
对属于国家秘密的地理信息的获取、持有、提供、利用情况进行登记并长期保存,实行可追溯管理
对属于国家秘密的地理信息的获取、持有、提供、利用情况进行登记并长期保存,实行可追溯管理 数据记录(包括获取、持有、提供、利用、销毁等全闭环)...
XAER_RMERR: Fatal error occurred in the transaction branch异常解决
XAER_RMERR: Fatal error occurred in the transaction branch异常解决 数据库权限问题!!!不是mysql驱动问题,执行下面命令解决 GRANT XA_RECOVER_ADMIN ON *.* TO root% ;...
Redis面试常见问题
Redis中的Lua脚本到底能不能保证原子性? Redis中Lua脚本的执行,可以保证并发编程中不可再拆分的这个原子性,但是没有保证数据库ACID中要么都执行要么都回滚的这个原子性。Lua脚本执行过程中命令产生错误,是不会回滚的,…...
实时手机检测-通用GPU算力优化:TensorRT加速后吞吐量提升3.2倍
实时手机检测-通用GPU算力优化:TensorRT加速后吞吐量提升3.2倍 1. 引言:当手机检测遇上性能瓶颈 想象一下,在一个大型活动现场,安保系统需要实时分析数百路监控视频,精准识别出每一部正在使用的手机,以防…...
仅限首批200名开发者获取:PHP低代码表单引擎v1.0内测版+商业授权白名单通道(含Figma组件库+Swagger自动文档生成)
第一章:PHP低代码表单引擎v1.0内测版概览与接入指南 PHP低代码表单引擎v1.0内测版是一款面向中小规模Web应用的轻量级表单构建与渲染框架,基于原生PHP 8.1开发,不依赖Composer自动加载,支持零配置快速嵌入现有项目。引擎核心由表单…...
Vulnhub sar
Vulnhub sar 扫描主机 扫描端口 扫描目录 只开了80端口,访问页面,默认的apache2页面 Robots.txt 查询漏洞,版本一致都是远程代码执行漏洞 提供了利用路径 github源码 http://192.168.68.128/sar2HTML/index.php?plot;whoami 反弹shell 直…...
山西太原传媒艺考评价榜第 1 名
在山西太原,艺天影视培训学校凭借其卓越的教学质量和丰富的行业资源,连续多年稳居传媒艺考评价榜榜首。本文将从师资力量、教学体系、硬件设施以及升学成果四个方面,详细解读艺天影视培训学校的成功之道,并为有志于传媒艺术的学子…...
代码之外周刊(第期):当技术让一切趋同,我们还剩什么?克
1. 前言 本文详细介绍如何使用 kylin v10 iso 文件构建出 docker image,docker 版本为 20.10.7。 2. 构建 yum 离线源 2.1. 挂载 ISO 文件 mount Kylin-Server-V10-GFB-Release-030-ARM64.iso /media 2.2. 添加离线 repo 文件 在/etc/yum.repos.d/下创建kylin-local…...
Curl命令行工具:从基础到高级的全面指南
1. Curl 命令行工具概述curl(Client for URLs)是一个功能强大的命令行工具,用于与各种服务器进行数据传输。作为一名长期与服务器打交道的开发者,我可以负责任地说,curl是每个技术人员工具箱中不可或缺的利器。它支持包…...
【MATLAB实例教程:五分钟快速上手教程】
前言MATLAB(Matrix Laboratory)是MathWorks公司开发的高性能数值计算和可视化软件,广泛应用于工程、科学、金融和数据分析领域。本文将通过一个完整的实例,演示MATLAB在数据分析和可视化方面的强大功能。这是一个面向绝对初学者的…...
从原理到选型:WDM波分复用技术全解析与应用指南
1. WDM波分复用技术基础入门 第一次接触WDM这个概念是在2013年参加某运营商骨干网改造项目时。当时客户指着机房密密麻麻的光纤问我:"能不能在不更换现有光缆的情况下,把传输容量提升8倍?"这个问题直接把我问住了。后来在华为专家的…...
【权威实测|2026.03.15 CPython核心团队签发】:Python原生AOT插件下载失败率骤降92%,但90%开发者仍卡在第2步安装验证
第一章:Python原生AOT编译方案2026插件下载与安装概览Python原生AOT(Ahead-of-Time)编译方案2026是CPython官方实验性路线图中的关键演进,旨在为Python代码提供零运行时依赖的二进制输出能力。该方案不依赖PyInstaller或Nuitka等第…...
别再踩坑了!SQL Server数据类型那点事儿,看懂这篇少背三个锅蹬
从0构建WAV文件:读懂计算机文件的本质 虽然接触计算机有一段时间了,但是我的视野一直局限于一个较小的范围之内,往往只能看到于算法竞赛相关的内容,计算机各种文件在我看来十分复杂,认为构建他们并能达到目的是一件困难…...
