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-4xPSR2
N-8PC1
N-12LR8
N-16R127
N-20R36
N-24R25
N-28R14
N-32 (新SP也指向这里)R03

RISC-V

RISC-V 架构的处理器在进入和退出中断处理模式时没有硬件自动保存和恢复上下文(通用寄存器)的操作,因此需要软件明确地使用(汇编语言编写的)指令进行上下文的保存和恢复。根据中断是向量处理模式还是非向量处理模式,上下文的保存和恢复涉及到的内容会有所差异

在上述异常exc_entry和中断irq_entry中,都有SAVE_CONTEXTRESTORE_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_CONTEXTRESTORE_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
30=返回后进入Handler模式
1=返回后进入线程模式
20=从主堆栈中做出栈操作,返回后使用MSP,
1=从进程堆栈中做出栈操作,返回后使用PSP
1保留,必须为0
00=返回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 地址,从而可以继续执行之前被中止的程序流。
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/204066.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读:“Model-based teeth reconstruction”

文章目录 AbstractIntroductionTeeth Prior ModelData PreparationParametric Teeth Model Teeth FittingTeeth Boundary Extraction Reference Abstract 近年来,基于图像的人脸重建方法日趋成熟。这些方法可以捕捉整个面部或面部特定区域(如头发、眼睛…

探索H5的神秘世界:测试点解析

Html5 app实际上是Web app的一种,在测试过程中可以延续Web App测试的部分方法,同时兼顾手机端的一些特性即可,下面帮大家总结下Html5 app 相关测试方法! app内部H5测试点总结 1、业务逻辑 除基本功能测试外,需要关注的…

【微服务专题】微服务架构演进

目录 前言阅读对象阅读导航前置知识笔记正文一、系统架构的演变1.1 单体架构1.2 单体水平架构1.3 垂直架构1.4 SOA架构1.5 微服务架构 二、如何实现微服务架构2.1 微服务架构下的技术挑战2.2 微服务技术栈选型2.3 什么是Spring Cloud全家桶2.4 Spring Cloud Alibaba版本选择 学…

智慧化工~工厂设备检修和保全信息化智能化机制流程

化工厂每年需要现场检修很多机器,比如泵、压缩机、管道、塔等等,现场检查人员都是使用照相机,现场拍完很多机器后,回办公室整理乱糟糟的照片,但是经常照了之后无法分辨是哪台设备,而且现场经常漏拍&#xf…

HarmonyOS4.0系列——02、汉化插件、声明式开发范式ArkTS和类web开发范式

编辑器调整 我们在每次退出编辑器后再次打开会直接进入项目文件中,这样在新建项目用起来很是不方便,所以这里跟着设置一下就好 这样下次进入就不会直接跳转到当时的文件项目中!! 关于汉化 settings → plugins → installe…

耗时一个星期整理的APP自动化测试工具大全

在本篇文章中,将给大家推荐14款日常工作中经常用到的测试开发工具神器,涵盖了自动化测试、APP性能测试、稳定性测试、抓包工具等。 一、UI自动化测试工具 1. uiautomator2 openatx开源的ui自动化工具,支持Android和iOS。主要面向的编程语言…

西南科技大学数字电子技术实验二(SSI逻辑器件设计组合逻辑电路及FPGA实现 )预习报告

一、计算/设计过程 说明:本实验是验证性实验,计算预测验证结果。是设计性实验一定要从系统指标计算出元件参数过程,越详细越好。用公式输入法完成相关公式内容,不得贴手写图片。(注意:从抽象公式直接得出结果,不得分,页数可根据内容调整) 1、1位半加器 真值表: 逻…

flask 上传文件

from flask import Flask, request, render_template,redirect, url_for from werkzeug.utils import secure_filename import os from flask import send_from_directory # send_from_directory可以从目录加载文件app Flask(__name__)#UPLOAD_FOLDER media # 注意&#xff…

Me-and-My-Girlfriend-1

Me-and-My-Girlfriend-1 一、主机发现和端口扫描 主机发现,靶机地址192.168.80.147 arp-scan -l端口扫描,开放了22、80端口 nmap -A -p- -sV 192.168.80.147二、信息收集 访问80端口 路径扫描 dirsearch -u "http://192.168.80.147/" -e * …

深入探索Maven:优雅构建Java项目的新方式(一)

Maven高级 1,分模块开发1.1 分模块开发设计1.2 分模块开发实现 2,依赖管理2.1 依赖传递与冲突问题2.2 可选依赖和排除依赖方案一:可选依赖方案二:排除依赖 3,聚合和继承3.1 聚合步骤1:创建一个空的maven项目步骤2:将项目的打包方式改为pom步骤…

在Linux中对Docker中的服务设置自启动

先在Linux中安装docker,然后对docker中的服务设置自启动。 安装docker 第一步,卸载旧版本docker。 若系统中已安装旧版本docker,则需要卸载旧版本docker以及与旧版本docker相关的依赖项。 命令:yum -y remove docker docker-c…

2304. 网格中的最小路径代价 : 从「图论最短路」过渡到「O(1) 空间的原地模拟」

题目描述 这是 LeetCode 上的 「2304. 网格中的最小路径代价」 ,难度为 「中等」。 Tag : 「最短路」、「图」、「模拟」、「序列 DP」、「动态规划」 给你一个下标从 0 开始的整数矩阵 grid,矩阵大小为 m x n,由从 0 到 的不同整数组成。 你…

设计模式之十二:复合模式

模式通常被一起使用,并被组合在同一个解决方案中。 复合模式在一个解决方案中结合两个或多个模式,以解决一般或重复发生的问题。 首先重新构建鸭子模拟器: package headfirst.designpatterns.combining.ducks;public interface Quackable …

Scala如何写一个通用的游戏数据爬虫程序

以前想要获取一些网站数据的时候,都是通过人工手动复制粘贴,这样的效率及其低下。数据少无所谓,如果需要采集大量数据,手动就显得乏力了。半夜睡不着,爬起来写一段有关游戏商品数据的爬虫通用模板,希望能帮…

Servlet实现一个简单的表白墙网站

文章目录 前言效果展示事前准备HTML、CSS、JavaScript分别负责哪些HTML和CSS构架出页面的基本结构和样式JavaScript 实现行为和交互实现服务器端的业务代码整理pom.xmlweb.xmlmessageWall.htmlMessageServlet.java 前言 前面我们学习了 Java 中知名的 HTTP 服务器 tomcat 的安…

linux下的工具---yum

一、什么是yum yum是Linux下的软件包管理器 二、什么是软件包管理器 1、在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 2、但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在…

【密码学引论】Hash密码

第六章 Hash密码 md4、md5、sha系列、SM3 定义:将任意长度的消息映射成固定长度消息的函数功能:确保数据的真实性和完整性,主要用于认证和数字签名Hash函数的安全性:单向性、抗若碰撞性、抗强碰撞性生日攻击:对于生日…

保护您的IP地址:预防IP地址盗用的关键措施

随着互联网的发展,IP地址作为标识互联网设备的重要元素,成为网络通信的基石。然而,IP地址盗用威胁正不断增加,可能导致敏感信息泄露、未经授权的访问和网络攻击。本文将介绍一些有效的方法,以帮助组织和个人预防IP地址…

初学vue3与ts:路由跳转带参数

index-router <!-- 路由跳转 --> <template><div><div class"title-sub flex"><div>1、用router-link跳转带参数id1&#xff1a;</div><router-link to"./link?id1"><button>点我跳转</button>&…

scipy 笔记:scipy.spatial.distance

1 pdist 计算n维空间中观测点之间的成对距离。 scipy.spatial.distance.pdist(X, metriceuclidean, *, outNone, **kwargs) 1.1 主要参数 X一个m行n列的数组&#xff0c;表示n维空间中的m个原始观测点metric使用的距离度量out输出数组。如果非空&#xff0c;压缩的距离矩阵…