当前位置: 首页 > news >正文

【ARMv8M Cortex-M33 系列 7.3 -- EXC_RETURN 与 LR 及 PC 的关系详细介绍】


请阅读【嵌入式开发学习必备专栏 之 ARM Cortex-Mx专栏】


文章目录

    • 背景
    • EXC_RETURN 与 LR 及 PC
      • cortex-m33 从异常返回后 各个寄存器出战顺序
      • ARM 栈增长方式

背景

接着上篇文章:【ARMv8M Cortex-M33 系列 7.2 – HardFault 问题定位 1】,后面定位到是在cortex-m33/context_gcc.S执行完 BX Lr之后就发生了 HardFault,通过JLink 发现 LR的值为0xfffffffd 所以又继续调查了EXC_RETURN 的具体含义。

pendsv_exit:/* restore interrupt */MSR PRIMASK, r2ORR lr, lr, #0x04BX  lr

EXC_RETURN 与 LR 及 PC

在 ARM Cortex-M33(以及其他Cortex-M系列)处理器中,异常返回值(EXC_RETURN)用于指示当处理器完成异常处理(例如中断或系统调用)后应如何返回到异常发生前的状态。这个值被自动加载到LR(链接寄存器)中,在异常返回时由处理器使用。

当发生异常时,处理器会自动将当前的程序状态保存到堆栈中,包括程序计数器(PC)的值和其他重要寄存器,并将特定的值加载到LR。这个LR中的值称为EXC_RETURN,它决定了异常返回时处理器的行为,如使用哪个堆栈指针(MSP或PSP),以及是否返回到Thread或Handler模式。

EXC_RETURN 的值如下:

  • 0xFFFFFFF1:返回到Handler模式,使用MSP(主堆栈指针)作为堆栈指针。
  • 0xFFFFFFF9:返回到Thread模式,使用MSP作为堆栈指针。
  • 0xFFFFFFFD:返回到Thread模式,使用PSP(进程堆栈指针)作为堆栈指针。
  • 0xFFFFFFBC 的设置表示返回时,处理器将:
    • 使用 PSP 作为栈指针,
    • 返回到线程模式而不是异常模式(如中断),
    • 恢复浮点上下文。

此外,当在硬件浮点单元(FPU)支持的设备上编译代码时,还会有以下EXC_RETURN值:

  • 0xFFFFFFE1:返回到Handler模式,使用MSP作为堆栈指针,并且需要恢复浮点状态。
  • 0xFFFFFFE9:返回到Thread模式,使用MSP作为堆栈指针,并且需要恢复浮点状态。
  • 0xFFFFFFED:返回到Thread模式,使用PSP作为堆栈指针,并且需要恢复浮点状态。

在异常处理完毕后,处理器将执行一个异常返回操作,这个操作会根据LR中的EXC_RETURN值来从堆栈恢复之前保存的状态,并将控制权交回到异常发生前的代码。这个恢复过程包括将之前保存在堆栈上的PC值重新加载到PC寄存器,这样程序就会从中断前被中断的点继续执行。

在实践中,异常处理函数通常不需要显式地处理这些细节,因为处理器硬件和操作系统的异常管理机制会自动处理这些过程。当开发裸机应用或自己的操作系统时,理解EXC_RETURN和异常返回机制将非常重要。在使用操作系统(如FreeRTOS或其他RTOS)时,上下文切换和异常返回通常由操作系统管理。

在异常处理函数中,你可以检查LR的值来确定异常发生时的上下文。例如,在异常处理函数中,你可以使用类似于以下的代码:

uint32_t lr_value; 
asm("MOV %0, lr" : "=r" (lr_value)); 
// lr_value 现在包含了 EXC_RETURN 值 

或者,如果你需要在你的异常处理函数中手动操作LR以改变返回行为,你也可以编写相应的汇编代码,但通常这样的操作是不必要的,而且需要对ARM架构有深入的理解。

cortex-m33 从异常返回后 各个寄存器出战顺序

由于上面问题涉及到了入栈出栈的问题,所以又温习了一遍栈的内容:

在 ARM Cortex-M33 微控制器上,从异常(如中断)返回时,处理器会从堆栈中出栈(pop)寄存器的值来恢复到异常发生之前的状态。这一过程发生在异常处理完成后,当执行异常返回序列时。异常返回过程是自动的,由处理器硬件管理。

当异常发生时,处理器会将当前的上下文(某些寄存器的值)压入当前使用的堆栈中(MSP 或 PSP)。在从异常返回时,处理器将这些值出栈到寄存器中。这些寄存器包括程序计数器(PC)、链接寄存器(LR)、程序状态寄存器(xPSR)以及可能的一些通用寄存器。

异常返回时的出栈顺序与入栈顺序相反。入栈顺序通常如下:

  1. xPSR 2. 返回地址(PC)
  2. LR
  3. R12
  4. R3
  5. R2
  6. R1
  7. R0
  8. 如果有浮点状态,会进一步保存 S16-S31 浮点寄存器

因此,异常返回时寄存器的出栈顺序是:

  1. R0
  2. R1
  3. R2
  4. R3
  5. R12
  6. LR
  7. PC(返回地址)
  8. xPSR
  9. 如果有浮点状态,会进一步恢复 S16-S31 浮点寄存器

在异常返回序列结束时,处理器从堆栈恢复了这些寄存器的值,并跳转到返回地址(之前的PC)继续执行程序。

值得注意的是,这里所说的 LR 寄存器在异常发生时会被自动设置为一个特殊的值(EXC_RETURN),该值包含了关于返回时所需使用的堆栈指针(MSP 或 PSP)以及是否使用了浮点寄存器等信息。异常返回时,处理器会检查 LR 中的 EXC_RETURN 值,以决定如何恢复上下文并从哪个堆栈指针出栈。

此外,浮点寄存器(如果有)的保存和恢复,取决于浮点单元(FPU)的使用以及处理器的配置。如果在异常发生时使用了 FPU,则会额外保存和恢复 S16-S31 寄存器。如果 FPU 未启用或未使用,则不会保存和恢复这些浮点寄存器。

ARM 栈增长方式

在 ARM Cortex-M33 微控制器(以及所有 ARM Cortex-M 系列处理器)中,栈是向下增长的。这意味着,当数据被压入栈(push)时,栈指针(SP)会递减;相应地,当数据从栈中弹出(pop)时,栈指针会递增

这个行为符合大多数现代处理器的常见约定,即栈空间的起始地址通常较高,随着数据的增加,栈指针向着较低的内存地址方向移动。这种设计可以有效利用内存空间,因为栈的最大尺寸通常是不确定的,而向下增长可以确保栈不会与静态分配或动态分配的内存空间发生冲突。

thread.c 中可以看到对栈的具体使用选择:

static rt_err_t _rt_thread_init(struct rt_thread *thread,const char       *name,void (*entry)(void *parameter),void             *parameter,void             *stack_start,rt_uint32_t       stack_size,rt_uint8_t        priority,rt_uint32_t       tick)
{/* init thread list */rt_list_init(&(thread->tlist));thread->entry = (void *)entry;thread->parameter = parameter;/* stack init */thread->stack_addr = stack_start;thread->stack_size = stack_size;/* init thread stack */rt_memset(thread->stack_addr, '#', thread->stack_size);
#ifdef ARCH_CPU_STACK_GROWS_UPWARDthread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,(void *)((char *)thread->stack_addr),(void *)_rt_thread_exit);
#elsethread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,(rt_uint8_t *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)),(void *)_rt_thread_exit);

所以宏ARCH_CPU_STACK_GROWS_UPWARD 处的内容不会编译进去,使用的是#else分支。

相关文章:

【ARMv8M Cortex-M33 系列 7.3 -- EXC_RETURN 与 LR 及 PC 的关系详细介绍】

请阅读【嵌入式开发学习必备专栏 之 ARM Cortex-Mx专栏】 文章目录 背景EXC_RETURN 与 LR 及 PCcortex-m33 从异常返回后 各个寄存器出战顺序ARM 栈增长方式 背景 接着上篇文章:【ARMv8M Cortex-M33 系列 7.2 – HardFault 问题定位 1】,后面定位到是在…...

Linux之权限(内容详细,细节满满)

个人主页:点我进入主页 专栏分类:C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 数据结构初阶 Linux 欢迎大家点赞,评论,收藏。 一起努力 目录 一.前言 二.权限修改的两种方法 …...

了解云工作负载保护:技术和最佳实践

云工作负载是指云环境中的应用程序或存储元素,无论是公共云、私有云还是混合云。每个云工作负载都使用云的资源,包括计算、网络和存储。 云工作负载可以多种多样,例如运行应用程序、数据库或托管网站。它们可以是静态的或动态的,…...

【Godot4自学手册】第三节设置主人公的动画

继续,今天是第三节,我们主要实现主人公的动画效果,共有两种方法实现动画效果 一、通过AnimationPlayer节点实现动画效果 我们首先在player场景下,player节点下添加AnimationPlayer节点,添加方法是,在play…...

excel学习1

直接ctrl cctrl v会报错位移选择粘贴时用123那个数字粘贴而不是ctrl V 只要结果不要公式 上面复制的为数值这里是复制的公式他们两个不一样 这个方法太麻烦了直接用格式刷,选择一个区域一个单元格,不要选择多个一刷就出来了 第一个计算后向下拖就行了&…...

裁员致谷歌中国籍程序员身亡,技术变革下裁员对程序员的影响有多大

裁员,这是一个令无数人心悸的词汇。在瞬息万变的科技时代,裁员仿佛成了不少公司应对困境的“救命稻草”。然而,在这背后,每一名员工,每一个程序员,他们所承担的代价,又有多少人能够深切地理解&a…...

MybatisPlus的主键ID生成策略和公共字段自动填充的使用及注意事项

主键策略(ID自动生成) 以下是MyBatis-Plus中常见的几种主键生成策略及其对应的枚举值(3.3.0之前的版本): 主键生成策略枚举值数据库自增IdType.AUTO用户输入IdType.INPUT分布式全局唯一IDIdType.ID_WORKER分布式全局…...

【GitHub项目推荐--微软开源的可视化工具】【转载】

说到数据可视化,大家都很熟悉了,设计师、数据分析师、数据科学家等,都需要用各种方式各种途径做着数据可视化的工作.....当然许多程序员在工作中有时也需要用到一些数据可视化工具,如果工具用得好,就可以把原本枯燥凌乱…...

Python基础之文件操作(I/O)

和其他编程语言一样,Python 也具有操作文件(I/O)的能力,比如打开文件、读取和追加数据、插入和删除数据、关闭文件、删除文件等。合理应用python提供的文件操作基本函数,可大大提高自动化实现的效率与框架代码的稳定性…...

k8s--helm

什么是helm?在没有这个helm之前,deployment service ingress helm的作用 通过打包的方式,把deployment service ingress等打包在一块,一键式的部署服务,类似yum安装 官方提供的一个类似与安装仓库额功能,…...

算法训练营第五十六天|583. 两个字符串的删除操作 72. 编辑距离

目录 Leetcode583. 两个字符串的删除操作Leetcode72. 编辑距离 Leetcode583. 两个字符串的删除操作 文章链接:代码随想录 题目链接:583. 两个字符串的删除操作 思路:直接记录需要改(增或删)几个,也就是求不…...

使用WAF防御网络上的隐蔽威胁之目录穿越

目录穿越(Directory Traversal)是一种网络安全攻击手段,也被称为路径穿越。 这种攻击允许攻击者访问存储在Web服务器文件系统上的文件和目录,这些文件和目录原本不应该对用户可见或可访问。 通过利用安全漏洞,攻击者…...

Linux:vim的相关知识

目录 vim 是一个较为常见的编译文件的命令操作。 三种模式的区分的作用如下: 命令模式: 插入模式: 进入插入模式的标志:左下角有INSERT 底行模式: 命令模式的常见命令: 底行模式常见命令&#xff1…...

Qt 国产嵌入式操作系统实现文字转语音功能(ekho库)

1.简介 Qt 国产嵌入式操作系统实现文字转语音功能(TTS)_tts驱动 转文字-CSDN博客 在继上篇文章之后,甲方粑粑不满意使用eSpeak发出的声音太难听了,这就不得不找个替代品,声音稍微好听了一些。 使用ekho开源库。 Ekho(余音)是一个免费、开源的中文语音合成软件。它目…...

Redis常见类型及常用命令

目录 常见的数据类型 一、String类型 1、简介 2、常用命令 (1)新建key (2)设值取值 ​编辑 (3)批量操作 (4)递增递减 3、原子性操作 4、数据结构 二、list类型 1、list常…...

实战纪实 | 某配送平台zabbix 未授权访问 + 弱口令

本文由掌控安全学院 - 17828147368 投稿 找到一个某src的子站,通过信息收集插件wappalyzer,发现ZABBIX-监控系统: 使用谷歌搜索历史漏洞:zabbix漏洞 通过目录扫描扫描到后台,谷歌搜索一下有没有默认弱口令 成功进去了…...

【第十五课】数据结构:堆 (“堆”的介绍+主要操作 / acwing-838堆排序 / c++代码 )

目录 关于堆的一些知识的回顾 数据结构:堆的特点 "down" 和 "up":维护堆的性质 down up 数据结构:堆的主要操作 acwing-838堆排序 代码如下 时间复杂度分析 确实是在写的过程中频繁回顾了很多关于树的知识&…...

前端JavaScript篇之JavaScript有哪些数据类型,它们的区别?

目录 JavaScript有哪些数据类型,它们的区别?数据类型区别 JavaScript有哪些数据类型,它们的区别? 数据类型 JavaScript数据类型有: Undefined、Null、Boolean、Number、String、Array、Object、Symbol、BigInt… St…...

LeetCode---380周赛

题目列表 3005. 最大频率元素计数 3006. 找出数组中的美丽下标 I 3007. 价值和小于等于 K 的最大数字 3008. 找出数组中的美丽下标 II 一、最大频率元素计数 这题就是个简单的计数题,正常遍历统计数据即可,关键是你要会写代码逻辑。 代码如下&…...

archlinux 如何解决安装以后没有声音的问题

今天安装完archlinux以后发现看视频没声音 检查一下是否有 /lib/firmware/intel/sof 发现没有 如果你也是这样的话,可以尝试安装: sudo pacman -S sof-firmware 重启后再看看有没有声音: reboot 反正我有声音了...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

【Oracle APEX开发小技巧12】

有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...