深入理解 Cortex-M3 的内核寄存器组

每个 MCU 开发工程师一定都了解寄存器这个东西,以 STM32 为例,其拥有非常多的外设模块,如串口、SPI、IIC 等等,如果要使用这些外设,使其按照我们的要求工作,就需要配置这些外设的寄存器,往这些寄存器中写入对应的配置数据,从而使其工作在我们所需要的模式中。

上述寄存器都是工程师日常编程会操作的寄存器,可以说和工程师的关系非常紧密。但有这么一组寄存器,与大多数工程师的关系就很疏远,甚至一些初学者完全不知道。

这,就是内核寄存器组

在大多数比较基础的日常编程中你完全无需关注内核寄存器,但实际上你写的每一行代码,最终都是去操作内核寄存器,编译器会负责完成这中间的转换。并且,如果你要进行一些高级编程,如操作系统的编写,或者做一些非常底层的优化,你就不得不去人为操作这些寄存器。

下面我们就基于 STM32F103 这款芯片来探一探其内核寄存器的究竟。

STM32F103 属于 Cortex-M3 内核,其内核寄存器组中拥有 16 个寄存器,其中 13 个为 32 位通用寄存器,另外 3 个则有特殊用途:

图片

R0 ~ R12

寄存器 R0 ~ R12 为通用寄存器,其中前 8 个 (R0 ~ R7)也被称为低寄存器。由于指令中的可用空间有限,许多 16 位的指令只能访问低寄存器。

高寄存器 R8 ~ R12 则可以用于 32 位指令和几个 16 位指令,如 MOV。

R0 ~ R12 的初始值是未定义的。

R13 栈指针 SP

R13 为栈指针,可以通过 PUSH 和 POP 指令实现栈的访问。实际在物理上存在两个栈指针:主栈指针 MSP(Main Stack Pointer)和进程栈指针 PSP(Process Stack Pointer)。

主栈指针(MSP)为默认的栈指针,在复位后或处理器处于特权模式(如进中断)时会被使用。通常用于芯片初始化代码和中断服务函数中。

进程栈指针(PSP)只能用于线程模式。在使用支持任务或线程切换的实时操作系统(RTOS)中,PSP 用于管理用户级任务的堆栈。这允许操作系统进行有效而稳定的任务调度,因为每个任务可以有自己的堆栈,在切换任务时只需要切换 PSP 的值即可。

大多数情况下,如果你是裸机编程,即没有用到嵌入式操作系统,那么 PSP 也没有必要使用。许多简单的应用可以完全依赖于 MSP,一般在操作系统中才会使用到 PSP,因其各个任务(或线程)的栈是要求相互独立的。

PSP 的初始值未定义,而 MSP 的初始值则会在复位流程中从存储器的第一个字中取出。

R14 链接寄存器 LR

R14 也被称作链接寄存器 LR,用于函数或子程序调用时返回地址的保存。

在函数或子程序被调用时,返回地址(即调用指令后面那条指令的地址)被保存到 LR 寄存器中。这样,在函数或子程序结束时,处理器可以通过 LR 寄存器中的值返回到正确的地址继续执行。

当执行了函数或子程序的调用后,LR 的数值会自动更新。若该函数或子程序内还要调用其他函数或子程序(如 A 调用 B,B 中还调用了 C),则此时需要将 LR 的数值保存在栈中,否则,一旦执行了 C 调用,LR 就会更新为 B 函数中调用 C 这条函数的下一条指令的地址,原本 A 调 B 的下一条指令地址就会被覆盖丢失,从而无法再恢复到 A 函数中继续运行。

在异常处理期间,LR 也会被自动更新为特殊的 EXC_RETURN(异常返回)数值,之后该数值会在异常处理结束时触发异常返回,从而实现从异常处理返回到正确的用户程序中 。

需要注意的是,尽管 Cortex-M 处理器中的返回地址总是偶数(由于指令会对齐到半字地址上,因此,最低位即第 0 位为 0),LR 的第 0 位是可读可写的,有些跳转/调用操作需要将 LR(或正在使用的任何寄存器)的第 0 位置 1 来表示当前处理器处于 Thumb 状态。

R15 程序计数器 PC

R15 为程序计数器 PC,可读可写。读操作返回当前指令地址加 4(这是由于流水线特性及同 ARM7TDMI 处理器兼容的需要),而对 PC 的写操作(例如使用数据传输/处理指令)则会引起程序的跳转(不会更新 LR 寄存器)。

由于指令必须要对齐到半字或字地址,PC 的最低位(LSB)为 0.不过,在使用一些跳转或读存储器指令更新 PC 时,需要将新 PC 值的 LSB 置 1 来表示 Thumb 状态,否则就会由于试图使用不支持的 ARM 指令(如 ARM7TDMI 中的 32 位 ARM 指令)而触发错误异常。对于高级编程语言(包括 C 和 C++),编译器会自动将跳转目标的 LSB 置位。

多数情况下,跳转和调用由专门的指令实现,利用数据处理指令更新 PC 的情况较为少见。不过,在访问位于程序存储器的字符数据时,PC的数值非常有用,因此,会经常发现存储器的读操作将 PC 作为基地址寄存器,而地址偏移则由指令中的立即数生成。

总结

以上就是 Cortex-M3 内核寄存器组中所有的寄存器。虽然在日常编程过程中我们很少或者可以说几乎不会直接接触并操作这些寄存器,一旦程序出现问题崩溃,或者运行过程中出现异常输出或逻辑,此时这些内核寄存器就能够为我们提供非常重要且直观的调试分析依据,以此快速定位问题并解决。如果你不理解这些内核寄存器组,那你的问题分析过程将会变得异常艰辛,甚至最终从调试到放弃。

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

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

相关文章

网络安全自动化:找准边界才能筑牢安全防线

数字时代,企业每天要面对成千上万的网络攻击。面对庞大的服务器群、分散的团队和长期不重启的设备,很多企业开始思考:哪些安全操作适合交给机器自动处理?哪些必须由人工把关?今天我们就用大白话聊聊这件事。 一、这些事…

C++负载均衡远程调用学习之负载均衡算法与实现

目录 01 lars 系统架构回顾 02 lars-lbAgentV0.4-route_lb处理report业务流程 03 lars-lbAgentV0.4-负责均衡判断参数配置 04 lars-lbAgentV0.4-负载均衡idle节点的失败率判断 05 lars-lbAgentV0.4-负载均衡overload节点的成功率判断 06 lars-lbAgentV0.4-负载均衡上报提交…

领略算法真谛: 多源bfs

嘿,各位技术潮人!好久不见甚是想念。生活就像一场奇妙冒险,而编程就是那把超酷的万能钥匙。此刻,阳光洒在键盘上,灵感在指尖跳跃,让我们抛开一切束缚,给平淡日子加点料,注入满满的pa…

雷电模拟器-超好用的Windows安卓模拟器

一、雷电模拟器介绍 雷电模拟器是一款功能强大的软件,它能够在电脑上模拟出安卓手机系统,让你可以在电脑上运行各类手机应用及游戏。其采用虚拟安卓手机操作界面,为玩家带来了独特的体验。 (一)强大的兼容性 雷电模拟…

文章三《机器学习基础概念与框架实践》

文章3:机器学习基础概念与框架实践 ——从理论到代码,用Scikit-learn构建你的第一个分类模型 一、机器学习基础理论:三大核心类型 机器学习是人工智能的核心,通过数据让计算机自动学习规律并做出预测或决策。根据学习方式,可分为三类: 1. 监督学习(Supervised Learni…

脑机接口技术:开启人类与机器的全新交互时代

在科技飞速发展的今天,人类与机器的交互方式正经历着前所未有的变革。从最初的键盘鼠标,到触摸屏,再到语音控制,每一次交互方式的升级都极大地提升了用户体验和效率。如今,脑机接口(Brain-Computer Interfa…

8.2 GitHub企业级PDF报告生成实战:ReportLab高级技巧与性能优化全解析

GitHub企业级PDF报告生成实战:ReportLab高级技巧与性能优化全解析 GitHub Sentinel 高级功能实现:PDF 报告生成技术详解 关键词:PDF 报告生成, ReportLab 实战, 结构化数据转换, 容器化字体配置, 企业级报告模板 1. 需求分析与技术选型 PDF 报告生成需要满足以下技术要求…

架构思维:构建高并发读服务_基于流量回放实现读服务的自动化测试回归方案

文章目录 引言一、升级读服务架构,为什么需要自动化测试?二、自动化回归测试系统:整体架构概览三、日志收集1. 拦截方式2. 存储与优化策略3. 架构进化 四、数据回放技术实现关键能力 五、差异对比对比方式灵活配置 六、三种回放模式详解1. 离…

基于Spring Boot 3.0、ShardingSphere、PostgreSQL或达梦数据库的分库分表

要实现基于Spring Boot 3.0、ShardingSphere、PostgreSQL或达梦数据库的分库分表,首先需要对ShardingSphere进行一些基本配置。你提到的溯源码、批次号等数据需要考虑到跨年数据的存储,因此要设计一个能够动态扩展的分表策略 添加ShardingSphere依赖 在…

位运算的应用

1. 判断偶数&#xff0c;判断最低位是0还是1即可&#xff0c;⽐求模快 x % 2 ! 0 //x正负都可以判断&#xff1b;不⽤x%2 1&#xff0c;因为如果x为负奇数&#xff0c;x%2-1 (x & 0x1) 0 例如&#xff1a; int x; int main() { cin>>x; if((x & 0x1)0) cout<…

FOC算法开环控制基础

1. 为什么要有FOC算法 先看看从有刷电机到无刷电机的简单介绍&#xff0c;如下图1&#xff0c;通电螺线圈会产生磁场&#xff0c;这个磁场会产生N级和S级&#xff0c;然后这个电磁铁就可以吸引永磁体&#xff0c;S级吸引N级&#xff0c;N级吸引S级&#xff0c;通俗的来说&…

【计算机网络】HTTP中GET和POST的区别是什么?

从以下几个方面去说明&#xff1a; 1.定义 2.参数传递方式 3.安全性 4.幂等性 1.定义&#xff1a; GET&#xff1a; 获取资源&#xff0c;通常请求数据而不改变服务器的状态。POST&#xff1a; 提交数据到服务器&#xff0c;通常会改变服务器的状态或副作用(如创建或更新资源…

7400MB/s5050TBW完美结合,全新希捷酷玩530R SSD体验评测

7400MB/s&5050TBW完美结合&#xff0c;全新希捷酷玩530R SSD体验评测 哈喽小伙伴们好&#xff0c;我是Stark-C~ 说到希捷酷玩530 SSD&#xff0c;很多硬核进阶玩家应该都知道&#xff0c;或者说正在使用&#xff08;比如说我~&#xff09;。 作为希捷大厂旗下高性能SSD的…

(undone) MIT6.S081 2023 学习笔记 (Day11: LAB10 mmap)

url: https://pdos.csail.mit.edu/6.1810/2023/labs/mmap.html mmap和munmap系统调用允许UNIX程序对其地址空间进行精细控制。它们可用于进程间共享内存、将文件映射到进程地址空间&#xff0c;并作为用户级页面错误处理方案的一部分&#xff0c;例如课程中讨论的垃圾回收算法。…

Q_OBJECT宏的作用

Qt 中&#xff0c;如果一个类中定义了信号&#xff08;signals&#xff09;或槽&#xff08;slots&#xff09;&#xff0c;那么这个类必须包含 Q_OBJECT 宏。 Q_OBJECT宏是 Qt 元对象系统的核心部分&#xff0c;它使得信号和槽机制能够正常工作。 Q_OBJECT宏是 Qt 的元对象系统…

信息安全基石:加解密技术的原理、应用与未来

信息加解密技术是信息安全领域的核心技术之一&#xff0c;以下为你详细介绍&#xff1a; 一、加密技术 1.定义&#xff1a;加密是通过特定的算法和密钥&#xff0c;将原始的明文信息转化为看似无意义的密文信息的过程。这一过程使得信息在传输、存储等过程中&#xff0c;即使…

LeetCode:返回倒数第k个结点

1、题目描述 实现一种算法&#xff0c;找出单向链表中倒数第 k 个节点。返回该节点的值。 注意&#xff1a;本题相对原题稍作改动 示例&#xff1a; 输入&#xff1a; 1->2->3->4->5 和 k 2 输出&#xff1a; 4 说明&#xff1a; 给定的 k 保证是有效的。 2、…

R004 -计算机硬件基础

目录 1.数据表示&计算机网络组成 2.计算机网络分类 3.冯诺依曼体系结构 4.指令系统基础 5.指令系统类型 6.流水线技术 流水线周期 &#xff1a;各流水段中&#xff0c;执行时间最长的那一段。就是T 流水线时间&#xff1a;t 1t2t 3 (n-1) * T 7.流水线指标 8.存储系…

Mybatis学习(下)

目录 1. 动态sql的应用 1.2 1.2 1.3 、 、 标签 1.4 1. 动态sql的应用 使用Mybatis框架时, 对于sql数据的操作量比较大的时候, 看着会觉得很乱, 可能写着写着就乱了, 或者说回过头来发现sql语句写错了, 很麻烦, 所以动态sql就可以让我们用Java代码, 替换部分sql语句 1.2 &l…

iview 老版本合并单元格

新版的iview中已经支持了合并单元格了&#xff0c;我的版本比较老&#xff0c;为&#xff1a;"iview": "^3.5.2"。暂不支持。记录一下别的大佬的方法。感觉思路比较活&#xff0c;正在这种思路需要在解决问题的过程中学习。 核心思路&#xff1a;通过rende…