Cortex-M3架构学习:

news2024/9/25 5:21:30

异常类型

 Cortex-M3 在内核水平上搭载了一个异常响应系统,支持为数众多的系统异常和外部中断。其 中,编号为 1 15 的对应系统异常,大于等于 16 的则全是外部中断。
Cortex-M3支持的中断源数目为 240 个,做成芯片后,厂商可按需选择个数,并且优先级的位数也由芯片厂商最终决定。
类型编号为 1 15 的系统异常如下所示,
只看上述表的描述很难知道每个系统异常的作用,本文在后面会做出解释。
外部中断列表如下,

优先级

CM3 中,优先级对于异常来说很关键的,它会决定一个异常是否能被掩蔽,以及在未掩蔽的
情况下何时可以响应。
优先级的数值越小,则优先级越高。 CM3 支持中断嵌套,使得高优先级异常会抢占(preempt) 低优先级异常。
3 个系统异常:复位, NMI 以及硬 fault ,它们有固定的优先 级,并且它们的优先级号是负数,从而高于所有其它异常。
所有其它异常的优先级则都是可编程的,但是无法设置成负数。
CM3支持3个固定优先级和256个可编程优先级,且支持128级抢占式优先级。
Cortex-M3处理器支持灵活的优先级配置,可以通过实现的位数来划分优先级。3位表示优先级意味着系统总共支持2³ = 8个不同的优先级级别。
        在这个优先级寄存器中,通常低5位未实现(未使用),这意味着这些位在硬件层面被固定为零。因此,即使整个寄存器有8位,实际用于描述优先级的位数可能是较少的(例如3位)。当只使用3位来表示优先级时,这些位的值总是对齐到寄存器的高位,表示优先级的编码。
具体的编码如下,
  • 0x00:最高优先级(所有位为0)
  • 0x20:次高优先级(高3位为001)
  • 0x40:优先级略低(高3位为010)
  • 0x60:优先级略低(高3位为011)
  • 0x80:中等优先级(高3位为100)
  • 0xA0:优先级较低(高3位为101)
  • 0xC0:更低优先级(高3位为110)
  • 0xE0:最低优先级(高3位为111)
备注:CM3的优先级寄存器的MSB(高位)对齐的 

抢占优先级和子优先级

Cortex-M3处理器将完整的256个优先级按位划分为抢占优先级子优先级

这种划分方式由NVIC(嵌套向量中断控制器)中的“应用程序中断及复位控制寄存器”(AIRCR寄存器)中的“优先级组”位段决定。

  • 抢占优先级(Preempt Priority):高位部分,控制中断的抢占关系。具有更高抢占优先级的中断可以抢占低优先级中断。
  • 子优先级(Sub Priority):低位部分,当多个中断有相同的抢占优先级时,子优先级决定哪个中断首先被响应。

抢占优先级和子优先级的优先级组的配置如下,

举个例子解释上表,比如当我们选择分组位置为2时,那么八位的优先级寄存器的第7位到第2位表示的是抢占优先级,0位和1位表示子优先级;并且,从上表可以看到,子优先级至少占了1位,所以抢占优先级最多占7位,所以最多为128级。 

向量表 

Cortex-M3的向量表是一个存储指针(函数入口地址)的数组,位于内存的某个特定地址。向量表中的每个条目是一个32位的地址指针,指向该中断或异常的处理程序函数。表的最开始部分包含两个特殊的条目:

  • 初始堆栈指针(Initial Stack Pointer):向量表的第一个条目(地址0x00000000)保存处理器复位时的初始堆栈指针值。处理器复位后会从这里读取堆栈指针,并将其加载到主堆栈指针(MSP)寄存器中。
  • 复位向量(Reset Vector):向量表的第二个条目(地址0x00000004)保存复位异常(Reset)的处理程序地址。当系统复位时,处理器会从这里跳转到启动代码。

在这两个特殊条目之后,向量表的其余部分包含各种异常和中断的处理程序入口地址,如下,

向量表通常位于内存地址0x00000000处。

然而,在Cortex-M3中,可以通过设置NVIC中的向量表偏移寄存器(来改变向量表的基地址。这使得在不同的内存地址区域(如RAM)中存储向量表成为可能。

中断输入及悬起

中断输入 

中断输入是由外部设备或系统内部事件引发的一种信号,用来通知处理器发生了某个事件,要求进行处理。Cortex-M3支持多种类型的中断源,如外部GPIO中断、定时器中断、UART中断等。

中断输入信号被触发后,Cortex-M3的嵌套向量中断控制器(NVIC)会根据中断的优先级来决定如何处理。

NVIC通过中断向量表查找中断服务程序(ISR)的入口地址,并执行相应的处理程序。

流程如下,

  • 中断触发:外部信号或内部事件触发中断。
  • 中断悬起:中断控制器将该中断标记为“悬起状态”。
  • 中断处理:当处理器空闲或优先级合适时,NVIC将转移到对应的中断服务程序(ISR)。
  • 中断结束:执行完中断服务程序后,NVIC清除中断悬起标志,并恢复正常程序执行。

中断悬起 

中断悬起是指在中断信号输入后,该中断进入等待处理的状态。Cortex-M3的中断系统允许多个中断同时处于悬起状态,并根据优先级进行调度。

  • 多个中断的悬起:如果多个中断同时触发,NVIC会根据中断的优先级来决定哪个中断优先处理。优先级更高的中断将优先被服务,而优先级较低的中断将继续处于悬起状态,直到处理器有空处理它们。
  • 中断嵌套:如果一个中断正在处理过程中,又有更高优先级的中断触发且悬起,处理器会暂停当前的中断处理,转而执行优先级更高的中断。这就是所谓的中断嵌套。
  • 悬起中断的自动清除:通常,NVIC在执行完中断服务程序后,会自动清除该中断的悬起状态。然而,某些中断可能需要手动清除悬起标志,具体取决于外设和应用程序的设计。

Fault异常

 总线Fault 

总线Fault是指当处理器尝试访问总线上的设备或内存时发生的错误。这类错误通常与外设、内存或总线控制器等硬件组件相关。

AHB 回复的错误信号会触发总线 fault的原因有
  • 企图访问无效的存储器 region。常见于访问的地址没有相对应的存储器。
  • 访问某个外设时,外设无法正常响应(如无法执行读写操作)。
  • 在企图启动一次数据传送时,传送的尺寸不能为目标设备所支持。例如, 某设备只接受字型数据,却试图送给它字节型数据。
  • 因为某些原因,设备不能接受数据传送。例如,某些设备只有在特权级下 才允许访问,可当前却是用户级。
  • 多主设备同时访问同一总线,导致仲裁冲突。

 在发送Fault后,处理方式如下,

  • 处理器进入总线Fault异常,并执行总线Fault处理程序。
  • NVIC中的Bus Fault Status Register(BFSR)会记录具体的Fault原因,帮助开发者调试和定位问题。

总线Fault也分为精确Fault和不精确Fault,如下,

存储器Fault 

存储器管理 faults 多与 MPU 有关,其诱因常常是某次访问触犯了 MPU 设置的保护规范。

 触发存储器Fault的原因如下,

  • 访问了所有 MPU regions 覆盖范围之外的地址
  • 访问了没有存储器与之对应的空地址
  • 往只读 region 写数据,当代码尝试访问被保护的区域,如只读存储器、不可执行的存储器区域,或特定特权模式下才能访问的区域时
  • 用户级下访问了只允许在特权级下访问的地址
  • Cortex-M3有专门的硬件机制来检测栈溢出。若栈指针超出有效的栈区域(由MPU配置),则会引发存储器访问故障。

 和总线 fault 一样,MemManage fault 必须被使能才能正常响应。

 存储器管理 fault 状态寄存器(MFSR),地址为0xE000_ED28,内容如下,

备注:在 MemManage fault 发生后,如果其服务例程是使能的,则执行服务例程。如果同时还发生了其它高优先级异常,则优先处理这些高优先级的异常,MemManage 异常被悬起。

用法Fault

用法Fault常见触发原因,

  • 未定义指令: 如果程序执行了无效或未定义的指令(通常是由于代码损坏或编译错误),会触发Usage Fault。

  • 除以零错误: 当程序试图执行整数除以零的操作时,Cortex-M3会产生Usage Fault(除非除零检测被禁用)。

  • 对无效地址的访问: 访问无效地址或者超出合法范围的地址(例如NULL指针)可能导致Usage Fault。

  • 对特权指令的非法访问: 在用户模式下执行特权指令,如修改特权寄存器等,可能会引发Usage Fault。

  • 对协处理器的非法访问: 如果程序试图访问未实现的协处理器指令(Cortex-M3没有FPU,因此对浮点运算单元的非法访问也可能引发此Fault)。

  • 未对齐的内存访问: Cortex-M3内核对某些数据访问要求内存地址对齐。例如,32位访问要求地址是4字节对齐,64位访问需要8字节对齐。如果访问未对齐的地址,可能会导致Usage Fault。

  • 尝试进入 ARM 状态:因为 CM3 不支持 ARM 状态,所以用法 fault 会在切换时产生。

 那我们如何捕获用法Fault,可以使用SCB寄存器捕获错误。

在发生Usage Fault时,SCBCFSR(Configurable Fault Status Register)寄存器会提供详细的错误信息。

UFSR是CFSR(Configurable Fault Status Register)的一部分,位于该寄存器的高16位,负责记录各种与Usage Fault相关的错误。

硬Fault 

硬fault 是总线 fault 、存储器管理 fault 以及用法 fault 上访的结果。
如果这些 fault 的服务例程无法执行,它们就会成为“硬伤”——上访( escalation )成硬 fault
NVIC 中有一个硬 fault 状态寄存器( HFSR ),它指出产生硬 fault 的原因。

SVC和PendSV

在Cortex-M3内核中,SVC(Supervisor Call)PendSV(Pending Supervisor Call)是两个与操作系统任务管理密切相关的异常(异常号分别为11和14),通常用于实现系统调用和任务切换等功能。

SVC

SVC指令是一种特权指令,允许程序从用户模式切换到特权模式以执行系统调用。

它通常用于操作系统内核提供的服务,比如任务管理、内存管理或硬件资源的访问。 

在使用操作系统时,应用程序(通常在用户模式下运行)不能直接访问硬件资源,而是通过操作系统提供的接口间接控制硬件。SVC就是这种接口机制的一部分。

SVC工作机制:

  • 用户程序执行一条SVC指令(SVC指令后跟一个立即数,比如0x3,作为系统服务调用的索引)。
  • SVC指令被执行时,处理器自动产生一个SVC异常,这时处理器会切换到特权模式,保存当前上下文,并跳转到操作系统定义的SVC_Handler中断服务例程。
  • SVC_Handler根据传递的立即数,决定要执行的具体系统服务。
  • 处理完用户的系统服务请求后,操作系统返回控制权给用户程序,继续执行剩余的代码。

SVC和操作系统之间的示意图如下,

 备注:我们不能在 SVC 服务例程中嵌套使用 SVC 指令(事实上这样做 也没意义),因为同优先级的异常不能抢占自身。这种作法会产生一个用法 fault。同理,在 NMI 服务例程中也不得使用 SVC,否则将触发硬 fault

PendSV 

PendSV是Cortex-M3中的另一种异常,主要用于实现任务切换,通常用于延迟或悬挂执行低优先级的任务。

PendSV不会像SVC一样通过指令触发,而是通过设置相关寄存器触发。例如,操作系统在需要任务切换时,会手动设置PendSV中断悬起位(SCB->ICSR中的PENDSVSET位),来触发PendSV异常。

当需要切换任务时,操作系统会触发PendSV异常,以便保存当前任务状态,并切换到下一个任务。

PendSV的典型应用场景:

  • 任务调度:在RTOS中,PendSV用于触发任务调度器。每次任务切换时,操作系统会触发PendSV,保存当前任务状态并恢复下一个任务的状态。
  • 延迟任务处理:由于PendSV的优先级最低,它通常被用于在中断结束后,处理低优先级的任务或操作系统调度操作。
PendSV异常处理流程:
  1. 操作系统检测到需要任务切换时,设置PendSV。
  2. 当没有其他高优先级中断需要处理时,处理器进入PendSV异常。
  3. 操作系统保存当前任务的上下文任务的寄存器、堆栈指针),选择下一个任务,并恢复它的上下文。

 备注:PendSV中断的优先级为最小,当然也可以通过NVIC进行修改。

PendSV 的典型使用场合是在上下文切换时(在不同任务之间切换)。

下面我们来看看为什么需要PendSV悬起,来延迟执行上下文切换。

假设有这么一个系统,里面有两个就绪的任务,并且通过 SysTick 异常启动上下文切换。
正常情况如下,
 

也就是当滴答定时器的时间到达以后,正常进行任务的上下文切换,但是有这样一种情况,就是现在SysTick中断触发的那一刻,处理器正在执行其他中断服务程序(ISR) ,由于滴答定时器中断的优先级一般比外部中断优先级高,那么滴答定时器中断就会抢占外部中断ISR,导致外部中断只能等滴答定时器中断执行完上下文切换在继续进行,但是这是会产生冲突的,因为一般的中断的优先级都比任务切换的优先级高,就会发生一些不好的事(具体的大家可以自行搜索),图解如下,

为了处理这个问题,PendSV中断就可以完美解决这个问题。

当出现上述情况时,滴答定时器的服务函数只会调用PendSV中断,将PendSV悬起,由于PendSV的优先级设置为最低优先级,这时候虽然滴答定时器触发仍然会抢占之前的外部中断(ISR),但是并不会在这期间进行任务切换,因为任务切换选择在PendSV中进行,此时ISR仍然继续执行,确切的说当所有的高优先级中断都执行完后,此时会触发之前悬起的PendSV,并在其中断服务函数中进行上下文切换,很好的避免上下文切换和中断一起进行这个问题。

图解如下,

备注:由于一般中断服务函数中所执行的程序都非常短,所以不必担心在处理PendSV时前面的高优先级中断处理很长时间,任务之间切换不会被显著延迟。

 

总结 

SVC与PendSV的对比

  • SVC(Supervisor Call,系统服务调用):用于执行系统服务调用,例如创建任务、删除任务、启动调度等。它通过SVC指令触发,可以从用户模式切换到特权模式,执行内核级的操作。

  • PendSV(Pending Supervisor Call,可悬起系统调用):主要用于任务切换。在需要任务切换时,通过触发PendSV中断来保存当前任务的上下文,并恢复下一个任务的上下文。

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

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

相关文章

TensorFlow深度学习框架改进K-means、SOM自组织映射聚类算法及上海招生政策影响分析研究|附代码数据

全文链接:https://tecdat.cn/?p37652 原文出处:拓端数据部落公众号 分析师:Chen Zhang 在教育政策研究领域,准确评估政策对不同区域和学生群体的影响至关重要。2021 年上海市出台的《上海市初中学业水平考试实施办法》对招生…

PDF转Excel小达人养成记

在现代职场,数据管理与格式转换可谓是日常任务的重头戏;有时我们手头有一份PDF文件,但需要将其中的数据整理成Excel表格,这该如何是好?别急,今天我就来给大家介绍几款好用的PDF转Excel工具,以及…

使用您自己的图像微调 FLUX.1 LORA 并使用 Azure 机器学习进行部署

目录 介绍 了解 Flux.1 模型系列 什么是 Dreambooth? 先决条件 使用 Dreambooth 微调 Flux 的步骤 步骤 1:设置环境 第 2 步:加载库 步骤 3:准备数据集 3.1 通过 AML 数据资产(URI 文件夹)将图像上传到…

minio集群

1 集群部署 minio集群的搭建并不复杂,别人也有很多的例子,这里只是先把自己的集群搭建记录下来,重点是后面的章节,遇到问题如何解决。 1.1 修改主机名 hostnamectl set-hostname minio1 hostnamectl set-hostname minio2 hostna…

【深度学习】训练过程中一个OOM的问题,太难查了

现象: 各位大佬又遇到过ubuntu的这个问题么? 现象是在训练过程中,ssh 上不去了,能ping通,没死机,但是ubunutu 的pc侧的显示器,鼠标啥都不好用了。只能重启。 问题原因: OOM了95G&a…

【C++】C++11-基础

目录 1、统一的列表初始化 1.1 {}初始化 1.2 std::initializer_list 2、声明 2.1 auto 2.2 decltype 2.3 nullptr 3、范围for 4、智能指针 5、STL中的一些变化 5.1 新容器 5.2 新方法 1、统一的列表初始化 1.1 {}初始化 在C98中,标准允许使用花括号{}…

光伏发电量如何计算?

真实光伏发电情况,需要根据几十种复杂因素,再通过鹧鸪云算法,快速计算出实际发电量情况。 1、自研算法,技术创新引领未来 鹧鸪云光伏发电量自研算法,是研发团队历经8个月,基于深度学习、大数据分析等前沿技…

Aqara澳门体验店开业 品牌实力与市场前景备受瞩目

在全球经济持续波动的背景下,许多品牌选择采取保守策略。然而,Aqara却还能稳步前行,展现出了强劲的发展势头。7月20日,Aqara在澳门市场迈出了重要一步,开设了该地区首家标准4S智能家居体验馆。这一战略性的布局不仅凸显…

跟《经济学人》学英文:2024年09月07日这期 Can IKEA disrupt the furniture business again?

Can IKEA disrupt the furniture business again? It wants to help you sell your Billy bookcase disrupt: 颠覆,彻底改变 这里的 “disrupt” 是指“颠覆”或“彻底改变”某个行业或市场的现有运作方式,通常通过引入创新的做法或技术来…

Django-Celery-Flower实现异步和定时爬虫及其监控邮件告警

1 Django中集成celery # Django --->python 的web框架-web项目--》用浏览器访问 # celery--->分布式异步任务框架-定时任务-延迟任务-异步任务1.1 安装模块 #官方文档:https://docs.celeryq.dev/en/stable/django/first-steps-with-django.htmlpip install …

JavaEE:文件内容操作(二)

文章目录 文件内容操作读文件(字节流)read介绍read() 使用read(byte[] b) 使用 read(byte[] b, int off, int len) 使用 写文件(字节流)write介绍write(int b) 使用write(byte[] b) 使用write(byte[] b, int off, int len) 使用 读文件(字符流)read() 使用read(char[] cbuf) 使…

[产品管理-6]:NPDP新产品开发 - 4 - 战略 - 创新支持战略,支持组织的总体创新战略(平台战略、技术战略、营销战略、知识产权战略、能力建设战略)

目录 一、创新支持战略概述 二、平台战略:大平台小产品战略 2.1 概述 1、平台战略的定义 2、平台战略的特点 3、平台战略的应用领域 4、平台战略的成功案例 5、平台战略的发展趋势 2.2 大平台小产品战略 1)大平台的建设 2)、小产品…

day-53 两个线段获得的最多奖品

思路 dp[right] 表示右端点不超过 prizePositions[right] 的线段可以覆盖最大奖品数量,然后枚举后面一条线段的右端点(第一条线段在第二条线段左边),第二条线段的长度可以表示为right-left1;第一条线段的长度可以表示dp[left] 解…

MINICPM-V2_6图像得到embedding-代码解读

目的 基于上一篇MINICPM-V2_6图像预处理流程-代码解读将输入图片得到了input_ids、attention_mask、pixel_values、image_sizes、image_bound、tgt_sizes,但是要怎么通过这些得到图片对应的embedding呢? 这里接着从MINICPM-V2_6入手,了解如何…

在 Windows 系统上,文件传输到虚拟机(VM)可以通过 VS Code 的图形界面(GUI)或命令行工具进行操作

在 Windows 系统上,文件传输到虚拟机(VM)可以通过 VS Code 的图形界面(GUI)或命令行工具进行操作。以下是几种方法: ### 方法 1: 使用 VS Code 图形界面 1. **连接到远程 VM**: - 在 VS Cod…

eNUM 原理概述(VoNR VoLTE适用) eNUM 报文解析

目录 1. eNUM 原理概述(VoNR VoLTE适用) 1.1 主要内容 1.2 什么是 eNUM 及 FAQ 1.3 eNUM 的主要信令场景 1.4 eNUM 查询结果为空,意味着什么? 1.5 eNUM 典型流程举例(VoNR 呼叫流程) 1.6 案例:因 eNUM 配置错误导致呼叫失败&#xff…

【STM32】BH1750光敏传感

1.BH1750介绍 BH1750是一个光敏传感,采用I2C协议,对于I2C的从机,都有自己的地址,用来主机选择和哪个从机通信,对于OLED来说,只有单片机通过I2C往OLED中写数据。而BH1750来说,有单片机往BH1750写…

illusionX——一个从理解情感到改变学习、创新教育体验集成情感计算的混合现实系统

概述 论文地址:https://arxiv.org/pdf/2402.07924.pdf 近年来,情感计算在丰富人类与计算机和机器的交互方式方面备受关注。这一创新领域旨在通过理解和响应用户的情绪和心理状态,将人机交互转变得更加自然和直观。无论是情感识别、面部表情分…

DAY74

#ifndef WIDGET_H #define WIDGET_H#include <QWidget>#include <QPainter> //画家类 #include <QTimer> //定时器类 #include <QTime> //时间类QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : …

C#使用TCP-S7协议读写西门子PLC(五)-测试程序

上面四篇我们进行封装连接PLC以及读写PLC内存地址表 C#使用TCP-S7协议读写西门子PLC(一)-CSDN博客 C#使用TCP-S7协议读写西门子PLC(二)-CSDN博客 C#使用TCP-S7协议读写西门子PLC(三)-CSDN博客 C#使用TCP-S7协议读写西门子PLC(四)-CSDN博客 这里我们进行测试操作 西门子PLC-…