ARM Cortex-M处理器中的MSP和PSP

在ARM Cortex-M系列处理器中,MSP(主堆栈指针)和PSP(进程堆栈指针)是两种不同的堆栈指针,主要用于实现堆栈隔离和提升系统可靠性。以下是它们的核心区别和应用场景:


1. 基本定义

  • MSP(Main Stack Pointer)

    • 用途:默认堆栈指针,主要用于处理模式(Handler Mode)(如中断、异常处理)。
    • 特点:系统启动时自动初始化,所有异常处理(如中断服务例程)必须使用MSP。
    • 权限:始终在特权模式下使用。
  • PSP(Process Stack Pointer)

    • 用途:可选堆栈指针,用于**线程模式(Thread Mode)**下的应用程序代码(如用户任务)。
    • 特点:需显式配置,常见于多任务系统(如RTOS)中,每个任务拥有独立的PSP以实现堆栈隔离。
    • 权限:可在特权或非特权模式下使用(取决于配置)。

2. 操作模式与堆栈选择

Cortex-M处理器有两种执行模式:

  • 处理模式(Handler Mode)

    • 始终使用MSP
    • 触发场景:中断、异常(如SysTick、硬件错误)。
  • 线程模式(Thread Mode)

    • 可配置使用MSP或PSP,由CONTROL寄存器的SPSEL位控制:
      • SPSEL=0 → 使用MSP(默认)。
      • SPSEL=1 → 使用PSP。
    • 权限
      • 特权线程模式:可自由切换MSP/PSP。
      • 非特权线程模式:无法修改CONTROL寄存器。

3. 典型应用场景

  • 单任务系统(无RTOS)

    • 通常仅使用MSP,简单可靠。
    • 中断直接使用MSP,用户代码在线程模式下默认也使用MSP。
  • 多任务系统(RTOS)

    • PSP核心作用:每个任务分配独立堆栈,任务切换时更新PSP指向当前任务堆栈。
    • 优势
      • 任务堆栈溢出不会破坏系统关键数据(如中断上下文)。
      • 实现任务间内存隔离,提升稳定性。
    • 配置示例
      // RTOS任务切换时,更新PSP
      __set_PSP(new_task_stack_top);
      // 切换CONTROL寄存器使用PSP
      __set_CONTROL(0x03); // SPSEL=1, 切换到非特权模式(可选)
      

4. 关键寄存器与控制

  • CONTROL寄存器

    • SPSEL位(Bit 1):
      • 0 → 线程模式使用MSP。
      • 1 → 线程模式使用PSP。
    • nPRIV位(Bit 0):
      • 0 → 特权模式。
      • 1 → 非特权模式(限制某些操作)。
  • 代码中操作堆栈指针

    // 读取/设置MSP和PSP(需特权模式)
    uint32_t current_msp = __get_MSP();
    uint32_t current_psp = __get_PSP();
    __set_MSP(new_msp_value);
    __set_PSP(new_psp_value);
    

5. 总结对比

特性MSPPSP
默认使用场景处理模式(中断、异常)线程模式(用户任务)
初始化系统启动自动初始化需手动配置
多任务隔离不适用(全局共享)支持(每个任务独立堆栈)
权限要求始终特权模式可配置特权或非特权模式
典型应用裸机程序、中断服务RTOS任务、复杂多任务系统

6. 实践建议

  • 裸机开发:优先使用MSP,简化设计。
  • RTOS开发:为每个任务分配PSP,避免堆栈冲突。
  • 安全性:在非特权模式下限制PSP修改,防止用户代码破坏系统。
  • 调试:通过调试器观察MSP/PSP的值,确保任务切换时堆栈正确更新。

通过合理使用MSP和PSP,可以显著提升嵌入式系统的稳定性和可维护性,尤其是在资源受限且要求高可靠性的场景中。


好的!我尽量用「大白话」和比喻来解释,保证你一听就懂!


想象你是一个打工人

假设你有 两个记事本(堆栈):

  1. 「老板专用记事本」(MSP)

    • 用途:专门用来记老板突然扔给你的急事(比如中断、系统崩溃)。
    • 特点:必须随身携带,随时能用,而且只能你自己用(特权模式)。
    • 举个栗子
      你正在写代码(普通任务),突然老板喊你修BUG(中断),你立刻放下手头工作,掏出「老板专用记事本」记录问题,修完再回去继续写代码。
  2. 「日常任务记事本」(PSP)

    • 用途:记录你平时的工作任务(比如用户程序、普通函数)。
    • 特点:可以灵活分配,比如每个项目(任务)单独用一个记事本,避免混乱。
    • 举个栗子
      你同时做两个项目(多任务),给每个项目分配一个「日常记事本」。切换项目时,只需要换一个记事本,互相不干扰。

关键区别

  1. 「老板的事 vs 你的事」

    • MSP:处理老板的急事(中断、系统级操作),必须快速响应,优先级最高。
    • PSP:处理你自己的日常工作(普通任务),可以慢慢来。
  2. 「记事本能不能共享」

    • MSP:全公司只有一个(全局共享),谁处理急事都用它。
    • PSP:每个项目(任务)单独一个,互相隔离,一个项目搞砸了(比如堆栈溢出),不会影响其他项目。
  3. 「谁有权限用」

    • MSP:只有你(系统内核、特权模式)能修改。
    • PSP:可以分权限,比如让实习生(非特权模式)也能用,但限制他乱改。

举个实际场景

假设你在写一个智能手表的程序:

  1. MSP 的用途

    • 突然要处理「心率异常报警」(中断),系统立刻停下手表界面刷新(普通任务),用 MSP 快速保存现场,处理报警。
  2. PSP 的用途

    • 平时同时运行「计步器」和「天气显示」两个任务,每个任务用自己的 PSP 堆栈。
    • 如果计步器的代码写错了(堆栈溢出),只会搞坏自己的 PSP,不会影响天气显示和 MSP(系统不会崩溃)。

一句话总结

  • MSP:系统「紧急专用通道」,处理中断和异常,全局唯一,必须可靠。
  • PSP:你的「多任务分身术」,每个任务独立堆栈,互不干扰。

再打个比方:

  • MSP 像医院的急诊室,随时处理紧急情况,全院只有一间。
  • PSP 像普通门诊,每个科室(任务)一间,病人(数据)分开排队,不会挤爆急诊室。

在嵌入式开发中,是否要关心 MSPPSP,取决于你的角色、开发场景和系统复杂度。用大白话分情况说明:


1. 如果你是写业务代码的「应用层开发人员」

  • 大多数情况下不需要关心,尤其是:

    • 用RTOS(如FreeRTOS、uCOS)
      RTOS已经帮你管理好了任务堆栈(用PSP),你只需要写任务函数,分配堆栈大小,完全不用手动操作PSP/MSP。
      // 例子:在FreeRTOS中创建任务,你只需指定堆栈大小,不用碰PSP
      xTaskCreate(task_function, "Task1", 512, NULL, 1, NULL);
      
    • 裸机开发但代码简单
      如果只是单任务循环(比如顺序执行初始化→采集数据→显示→延时),系统默认用MSP,你甚至不知道PSP的存在。
  • 需要关心的例外情况

    • 调试堆栈溢出问题
      如果程序崩溃,可能需要查看MSP/PSP指向的堆栈区域是否被写爆。
    • 写底层库或驱动
      如果你要写和中断、任务切换相关的底层代码(比如自定义调度器),需要理解MSP/PSP的切换逻辑。

2. 如果你是「系统工程师」或「内核开发者」

  • 必须深刻理解MSP/PSP,因为:
    • 任务切换
      在RTOS中切换任务时,需要保存当前任务的PSP,并加载新任务的PSP。
      ; 伪代码:任务切换的核心操作
      Save当前任务的寄存器到它的PSP堆栈;
      Load新任务的PSP值到CPU;
      从新任务的PSP堆栈恢复寄存器;
      
    • 中断处理
      系统默认用MSP处理中断,但某些高性能场景可能优化为用PSP(需谨慎)。
    • 安全隔离
      在需要权限隔离的系统(如非特权模式运行用户代码),需通过PSP限制任务对系统堆栈的访问。

3. 一句话总结

  • 业务层开发人员
    不用直接操作MSP/PSP,就当它们不存在,除非你要解决某些“玄学”崩溃问题。
    (就像开燃油车不用懂内燃机原理,但漏油了得知道去修)

  • 系统层开发人员
    必须掌握MSP/PSP,这是实现多任务、中断、内存隔离的核心机制。
    (就像赛车工程师必须懂发动机每个零件)


4. 举个实际例子

场景:你正在用STM32和FreeRTOS写一个智能家居控制器
  • 业务代码(你写的部分)

    void TemperatureTask(void *pvParameters) {
      while(1) {
        float temp = read_sensor();  // 读传感器
        send_to_display(temp);       // 发送到显示屏
        vTaskDelay(1000);            // 等1秒
      }
    }
    
    • 完全不用碰MSP/PSP,只需关注业务逻辑和任务堆栈大小(比如configMINIMAL_STACK_SIZE)。
  • 系统层(RTOS内部)

    // RTOS内核在切换任务时的隐藏操作:
    void vTaskSwitchContext() {
      // 保存旧任务的PSP到它的任务控制块(TCB)
      old_task->psp = __get_PSP();
      // 从新任务的TCB加载PSP
      __set_PSP(new_task->psp);
    }
    
    • 这里必须操作PSP,但你作为业务开发者看不到这些代码。

5. 什么情况下你会被迫了解MSP/PSP?

  • 调试时发现神秘崩溃
    比如日志显示HardFault_Handler,检查发现某个任务的PSP指向了非法地址。
  • 优化特殊场景性能
    比如在高频中断中,为了减少堆栈切换开销,刻意让中断共享PSP(需极度小心!)。
  • 自己造轮子写RTOS
    恭喜你,从此MSP/PSP会刻进你的DNA里。

6. 最终建议

  • 新手:
    先当MSP/PSP不存在,专注于业务逻辑。等遇到崩溃问题或学习RTOS原理时,再回头理解它们。

  • 进阶:
    通过调试器观察MSP/PSP的值(如下所示),加深对堆栈和任务切换的理解:
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    (图中:在Keil调试器中查看寄存器的MSP和PSP值)

  • 记住:
    MSP/PSP是CPU的“幕后工作人员”,99%的时间它们默默工作,只有1%的时间(出问题时)需要你喊它们出来对质。 😉

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32——HAL库开发笔记24(定时器5—超声波测距)(参考来源:b站铁头山羊)

一、原理 本次实验采用HC-SR04超声波传感器,结构及功能如下图 超声波传感器可以用来测距。距离 声速(340m/s) *传播时间 / 2。 这个传感器有四个引脚,其中VCC接电源正极,GND接电源负极 , Trig : 用来启动测量 &…

LCC并行光模块、PLCC并行光模块和POB并行光模块的区别

一、封装结构与材料差异 PLCC(Plastic Leaded Chip Carrier) 封装材料:采用塑料材质,引脚数量较多(20-84个),引脚分布在四周12散热设计:通常通过PCB基板嵌装铜散热片提升散热性能8…

WIFI的SSID超长,隐藏,重复 (2.4G和5G差异)

目录 1、2.4G和5G的频率范围‌ 2、2.4G和5G的差异‌: 3、隐藏ssid显示为\x00 4、 重复的ssid名称 扩展 前言 最近处理wifi设备时发现,小小一个ssid就有超多的问题。 不是中文转义就是超长,现在还发现空字符的,原来时对方路由隐藏了…

FS800DTU联动OneNET平台数据可视化View

目录 1 前言 2 环境搭建 2.1 硬件准备 2.2 软件环境 2.3 硬件连接 3 注册OneNET云平台并建立物模型 3.1 参数获取 3.2 连接OneNET 3.3上报数据 4 数据可视化View 4.1 用户信息获取 4.2 启用数据可视化View 4.3 创建项目 4.4 编辑项目 4.5 新增数据源 4.6 数据过滤器配置 4.6 项…

Linux时间日期类指令

1、data指令 基本语法: date : 显示当前时间date %Y : 显示当前年份date %m : 显示当前月份date %d : 显示当前哪一天date “%Y-%m-%d %H:%M:%S" : 显示年月日时分秒date -s 字符串时间 : 设置系统时…

Elasticsearch:使用经过训练的 ML 模型理解稀疏向量嵌入

作者:来自 Elastic Dai Sugimori 了解稀疏向量嵌入,理解它们的作用/含义,以及如何使用它们实现语义搜索。 Elasticsearch 提供语义搜索功能,允许用户使用自然语言进行查询并检索相关信息。为此,目标文档和查询必须首先…

MagicArticulate: 超48K海量数据革新3D动画,自回归Transformer驱动关节智能生成!

论文链接:https://arxiv.org/pdf/2502.12135 Git链接:https://chaoyuesong.github.io/MagicArticulate/ 亮点直击 首个大规模关节化基准数据集,包含超过33,000个具有高质量关节标注的模型; 一种新颖的两阶段框架,有效…

【洛谷入门赛】B4019 皆与生物有缘

题意 两个老师会对你进行打分,我们要做的是把两个老师每题给的分全加起来,然后 2 \div 2 2 再向上取整,输出这个值即可。 思路 首先,我们要输入。 根据我们总结的题意,我们还需要把所有分数加起来。 因为我们尽…

如何选择更安全的无人自助管理私人影院物联网框架?

对于无人自助管理的私人电影院来说,安全是至关重要的,在物联网层面上,更要确保其相关安全措施,才能更好地安全运转。选择更安全的无人自助管理私人影院物联网框架时,可以从以下几个关键方面进行评估: 1. 安…

基本网络安全的实现

基本网络安全的实现 一 :AAA AAA 是Authentication,Authorization and Accounting(认证、授权和计费)的简 称,它提供了一个用来对认证、授权和计费这三种安全功能进行配置的一致性框架, 它是对网络安全…

【大模型】Ubuntu下 fastgpt 的部署和使用

前言 本次安装的版本为 fastgpt:v4.8.8-fix2。 最新版本fastgpt:v4.8.20-fix2 问答时报错,本着跑通先使用起来,就没有死磕下去,后面bug解了再进行记录。   github连接:https://github.com/labring/FastGPT fastgpt 安装说明&…

python--泰坦尼克号人员存活模型训练+预测

1.先到Kaggle平台下载关于泰坦尼克号的数据。 泰坦尼克号数据集:这是Kaggle上的经典数据集,用于预测乘客是否幸存。 地址:Titanic - Machine Learning from Disaster | Kaggle 包含以下文件: train.csv:训练集&#…

【Azure 架构师学习笔记】- Azure Databricks (12) -- Medallion Architecture简介

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (11) – UC搭建 前言 使用ADB 或者数据湖,基本上绕不开一个架构“Medallion”, 它使得数据管理更为简单有效。ADB 通过…

spring中的注解介绍

本篇文章专门用来介绍spring中的各种注解。 1、RestController 1、含义 2、举例 3、使用场景 RestController 通常用于开发 RESTful API,适合返回 JSON 或 XML 数据的场景 4、总结 RestController 是 Spring 中用于简化 RESTful Web 服务开发的注解,它结…

嵌入式开发:傅里叶变换(5):STM32和Matlab联调验证FFT

目录 1. MATLAB获取 STM32 的原始数据 2. 将数据上传到电脑 3. MATLAB 接收数据并验证 STM32进行傅里叶代码 结果分析 STM32 和 MATLAB 联调是嵌入式开发中常见的工作流程,通常目的是将 STM32 采集的数据或控制信号传输到 MATLAB 中进行实时处理、分析和可视化…

Linux设备驱动开发-SPI驱动开发详解(包含设备树处理详细过程)

基础知识及 SPI 相关结构体介绍 引脚:MISO(master 输入,slave 输出),MOSI(master 输出,slave 输入),片选引脚,SCK(时钟) 控制寄存器&…

嵌入式八股文(五)硬件电路篇

一、名词概念 1. 整流和逆变 (1)整流:整流是将交流电(AC)转变为直流电(DC)。常见的整流电路包括单向整流(二极管)、桥式整流等。 半波整流:只使用交流电的正…

C++初阶——简单实现stack和queue

目录 1、Deque(了解) 1.1 起源 1.2 结构 1.3 优缺点 1.4 应用 2、Stack 3、Queue 4、Priority_Queue 注意:stack,queue,priority_queue是容器适配器(container adaptor) ,封装一个容器,按照某种规则使用&#…

【Git】六、企业级开发模型

文章目录 Ⅰ. 前言Ⅱ. 系统开发环境Ⅲ. Git 分支设计规范master分支release分支develop分支feature分支hotfix分支 Ⅰ. 前言 ​ 我们知道,一个软件从零开始到最终交付,大概包括以下几个阶段:规划、编码、构建、测试、发布、部署和维护。 ​…

Apache SeaTunnel 构建实时数据同步管道(最新版)

文章作者 王海林 白鲸开源 数据集成引擎研发 Apache SeaTunnel Committer & PMC Member,Apache SkyWalking Committer,多年平台研发经验,目前专注于数据集成领域。 导读 在当今数字化快速发展的时代,数据已然成为企业决策…