Cortext-M3系统:中断的具体行为(6)

news2024/12/23 22:15:30

1、中断/异常的响应序列

        当CM3开始响应一个中断时,会在它小小的体内奔涌起三股暗流: ​ 入栈:把8个寄存器的值压入栈 ​ 取向量:从向量表中找出对应的服务程序入口地址 ​ 选择堆栈指针MSP/PSP,更新堆栈指针SP,更新连接寄存器LR,更新程序计数器PC。

1.1 入栈

        响应异常的第一个行动,就是自动保存现场的必要部分:依次把xPSR, PC,LR, R12以及R3-R0由硬件自动压入适当的堆栈中:如果当响应异常时,当前的代码正在使用PSP,则压入PSP,也就是使用进程堆栈;否则就压入MSP,使用主堆栈。一旦进入了服务例程,就将一直使用主堆栈。

        假设入栈开始时,SP的值为N,则在入栈后,堆栈内部的变化如表9.1表示。又因为AHB接口上的流水线操作本性,地址和数据都在经过一个流水线周期之后才进入。另外,在自动入栈的过程中,把寄存器写入堆栈内存的时间顺序,并不是与写入的空间顺序相对应的。但是机器会保证:正确的寄存器将被保存到正确的位置。

        CM3在看不见的内部“搅浑”了入栈的顺序,这是有深层次的原因的。先把PC与xPSR的值保存,就可以更早地启动服务例程指令的预取——因为这需要修改PC;同时,也做到了在早期就可以更新xPSR中IPSR位段的值。

        CM3内核自动保存R12以及R3-R0,不自动保存R4-R11,是因为在ARM上有一套C函数的调用标准《C/C++ Procedure Call Standard for the ARM Architecture》。有了这个标准,它使得中断服务例程能用C语言编写,编译器优先使用入栈了的寄存器来保存中间结果。如果程序过大也可能要用到R4-R11,此时编译器负责生成代码来push它们。但是,ISR应该短小精悍,不要让系统如此操心。R0-R3, R12是最后被压进去的,为的是可以更容易地使用SP基址来索引寻址,这也方便了LDM等多重加载指令。因为LDM必须加载地址连续的一串数据,而现在R0-R3, 这种顺序也舒展了参数的传递过程:使之可以方便地通过读取入栈了的R0-R3取出R12的存储地址连续了(主要为系统软件所利用,多见于SVC与PendSV中的参数传递)。

1.2 取向量

        当数据总线(系统总线)正在进行入栈操作时,指令总线(I-Code总线)从向量表中找出正确的异常向量,然后在服务程序的入口处预取指。由此可以看到各自都有专用总线的好处:入栈与取指这两个工作能同时进行。

1.3 更新寄存器

        在入栈和取向量操作完成之后,执行服务例程之前,还要更新一系列的寄存器:

                SP:在入栈后会把堆栈指针(PSP或MSP)更新到新的位置。在执行服务例程时,将由MSP负责对堆栈的访问。 ​

                PSR:更新IPSR位段(地处PSR的最低部分)的值为新响应的异常编号。 ​

                PC:在取向量完成后,PC将指向服务例程的入口地址, ​

                LR:在出入ISR的时候,LR的值将得到重新的诠释,这种特殊的值称为“EXC_RETURN”,在异常进入时由系统计算并赋给LR,并在异常返回时使用它。EXC_RETURN的二进制值除了最低4位外全为1,而其最低4位则有另外的含义。 ​

        以上是在响应异常时通用寄存器的变化。另一方面,在NVIC中,也会更新若干个相关有寄存器。例如,新响应异常的悬起位将被清除,同时其活动位将被置位。

2、异常返回

        当异常服务例程执行完毕后,需要很正式地做一个“异常返回”动作序列,从而恢复先前的系统状态,才能使被中断的程序得以继续执行。从形式上看,有3种途径可以触发异常返回序列,如图所示。而不管使用哪一种,都需要用到先前储到LR的EXC_RETURN。

         有些处理器使用特殊的返回指令来标示中断返回,例如8051就使用reti。但是在CM3中,是通过把EXC_RETURN往PC里写来识别返回动作的。因此,可以使用上述的常规返回指令,从而为使用C语 言编写服务例程扫清了最后的障碍(无需特殊的编译器命令,如__interrupt)。

        在启动了中断返回序列后,下述的处理就将进行:

        1).出栈:先前压入栈中的寄存器在这里恢复。内部的出栈顺序与入栈时的相对应,堆栈指针的值也改回先前的值。 ​

        2).更新NVIC寄存器:伴随着异常的返回,它的活动位也被硬件清除。对于外部中断,倘若中断输入再次被置为有效,悬起位也将再次置位,新一次的中断响应序列也可随之再次开始。

3、 嵌套的中断

        在CM3内核以及NVIC的深处,就已经内建了对中断嵌套的全力支持,根本无需使用汇编去写封皮代码(wrapper code)。事实上,我们要做的就只是为每个中断适当地建立优先级,不用再操心别的。表现在: ​

        1)NVIC和CM3处理器会根据优先级的设置来控制抢占与嵌套行为。因此,在某个异常正在响应时,所有优先级不高于它的异常都不能抢占之,而且它自己也不能抢占自己。 ​

        2)有了自动入栈和出栈,就不用担心在中断发生嵌套时,会使寄存器的数据损毁,从而可以放心地执行服务例程。

        有一件事需要特别注意:主堆栈容量的最小安全值。异常使用的是主堆栈,每嵌套一级,就至少再需要8个字,即32字节的堆栈空间,还不包括ISR对对战的额外需求,且嵌套多少级也很难预测,因此,适当增大主堆栈的栈空间大小有益于系统的正常运行。

        另一个要注意的,是相同的异常是不允许重入的。因为每个异常都有自己的优先级,并且在异常处理期间,同级或低优先级的异常是要阻塞的。因此对于同一个异常,只有在上次实例的服务例程执行完毕后,方可继续响应新的请求。

4、 咬尾中断

        CM3为缩短中断延迟做了很多努力,第一个要提的,就是新增的“咬尾中断”(Tail-Chaining)机制。当处理器在响应某异常时,如果又发生其它异常,但它们优先级不够高,则被阻塞。那么在当前的异常执行返回后,系统处理悬起的异常时,倘若还是先POP,然后又把POP出来的内容PUSH回去,将十分浪费时间。CM3会继续使用上一个异常已经PUSH好的成果,消灭了这种铺张浪费。这么一来,看上去好像后一个异常把前一个的尾巴咬掉了,前前后后只执行了一次入栈/出栈操作。于是,这两个异常之间的“时间沟”变窄了很多,

 5、晚到(的高优先级)异常

        CM3的中断处理还有另一个机制,它强调了优先级的作用,这就是“晚到的异常处理”。当CM3对某异常的响应序列还处在早期:入栈的阶段,尚未执行其服务例程时,如果此时收到了高优先级异常的请求,则本次入栈就成了为高优先级中断所做的了——入栈后,将执行高优先级异常的服务例程。

                                                         晚到异常的处理模式

6、异常返回值

        在进入异常服务程序后,将自动更新LR的值为特殊的EXC_RETURN。这是一个高28位全为1的值,只有[3:0]的值有特殊含义。当异常服务例程把这个值送往PC时,就会启动处理器的中断返回序列。为LR的值是由CM3自动设置的,所以只要没有特殊需求,就不要改动它。EXC_RETURN的合法值共3个,如下:

 合法的EXC_RETURN值共3个

         如果主程序在线程模式下运行,并且在使用MSP时被中断,则在服务例程中LR=0xFFFF_FFF9(主程序被打断前的LR已被自动入栈)。 ​

         如果主程序在线程模式下运行,并且在使用PSP时被中断,则在服务例程中LR=0xFFFF_FFFD(主程序被打断前的LR已被自动入栈)。

                 LR的值在异常期间被设置为EXC_RETURN(线程模式使用主堆栈)

        如果主程序在Handler模式下运行,则在服务例程中LR=0xFFFF_FFF1(主程序被打断前的LR已被自动入栈)。这时的所谓“主程序”,其实更可能是被抢占的服务例程。事实上,在嵌套时,更深层ISR所看到的LR总是0xFFFF_FFF1,如图所示。

                 LR的值在异常期间被设置为EXC_RETURN(线程模式使用进程堆栈)

由EXC_RETURN的格式可见,我们不能把0xFFFF_FFF0-0xFFFF_FFFF中的地址作为任何返回地址。其实也并不用担心会弄错,因为CM3已经把这个范围标记成“取指不可区”了。

7、中断延迟

        在设计实时系统时,必须对中断延迟进行严肃和仔细地估算。在这里,中断延迟的定义是:从检测到某中断请求,到执行了其服务例程的第一条指令时,已经流逝了的时间。在CM3中,若存储器系统够快,且总线系统允许入栈与取指同时进行,同时该中断可以立即响应,则中断延迟是雷打不动的12周期(满足硬实时所要求的确定性)。在与时间赛跑的这12个周期里,处理器内部一直开足马力,进行了入栈、取向量、更新寄存器以及服务例程取指的一系列操作。但若存储器太慢以至于引入等待周期,或者还有其它因素,则会引入额外的延时

        当处理咬尾中断时,省去了堆栈操作,因此切入新异常服务例程的耗时可以短至6周期。 ​ 有些指令需要较多的周期才能完成。它们是除法指令,双字传送指令LDRD/STRD以及多重数据传送指令(LDM/STM)。对于前两者,CM3将为了保证中断及时响应而取消它们的执行,待返回后重新开始,对于LDM/STM,则有另外的处理方式。因为它们不照前两者那么浑然一体——它们其实是一串LDR/STR的速度优化版。于是,为了加速中断的响应,CM3支持LDM/STM指令的中止和继续,就好像它们只是普通的一串LDR/STR一样。为了实现“指令撕裂与粘合”的目的,需要记录中断时数据传送的进程。为此,CM3在xPSR中开出若干个“ICI位”,记录下一个即将传送的寄存器是哪一个(LDM/STM在汇编时,都把寄存器号升序排序)。在服务例程返回后,xPSR被弹出,CM3再从ICI bits中获取当时LDM/STM执行的进度,从而可以继续传送。

        在个别情况下还有一点限制:IF-THEN(IT)指令的执行也需要在xPSR中使用几个位,可它需要的位刚好与ICI位重合(类似C中的union)——ICI bits和IT条件都记录在EPSR中。所以,如果在IF-THEN中使用了LDM/STM,则不再记录LDM/STM的执行进度。但尽管如此,及时响应中断依然是首要任务。此时只好把LDM/STM取消,待中断返回后继续执行。

        另外,如果在总线接口上还有未完成的(outstanding)数据传送,例如有一个带缓冲的写操作未完成,处理器也只能等待此传送完成。这是迫不得以的——只有这样,才能保证在发生了总线fault时,其服务例程能够安全地抢占其它程序。

        当多个中断同时请求时,也会发生中断延迟,这表现在只有优先级最高的得到立即响应,所有其它的中断将被延迟。另外,在中断嵌套时,每个中断都会阻塞同级和低优先级的中断。最后,如果中断被掩蔽(也就是俗称的关中,在多任务系统下满地都有),则在掩蔽期间也会附加中断延迟。

8、异常响应期间的faults

        Faults是运行时发生各种故障的表现,在中断响应期间的故障也不例外。中断响应的每一步骤都可以触发faults。

8.1 入栈期间

        如果在入栈期间引起了总线fault,则本次入栈操作将被强行中止,并且把总线异常悬起或者在允许时立即响应。若除能了总线fault,则此次故障将成为“硬伤”——上访至硬fault。在总线fault被使能的情况下,如果它的优先级比正在响应的异常高,则抢占之,否则将悬起直到引起fault的异常执行完毕。这种情况被称为“入栈错误”(stacking error),由总线fault状态寄存器(BFSR,地址:0xE000_ED29)的STKERR位指示(位偏移:4)。 ​ 如果入栈操作引起MPU访问违例,则产生存储管理fault,并且必须能立即执行MemFault服务例程,否则将无条件上访成硬fault。在发生入栈时访问违例时,存储管理fault寄存器(MFSR,地址:0xE000_ED28)中的MSTKERR位(位偏移:4)被置位,用于指示该fault。入栈是自动完成的,因此不可能产生用法fault。

8.2 出栈期间

        如果在中断返回时的出栈期间引起了总线fault,则本次出栈操作将被强行中止,并且把总线异常悬起或立即响应。若除能了总线fault,则此次故障将成为“硬伤”——上访至硬fault。其它情况下,只要总线fault的优先级比当前的高(也包括比当前最深嵌套的优先级高),则可以立即响应。这种情况称为“出栈错误”(unstacking error),由BFSR.3指示(UNSTKERR位)。 ​ 类似地,如果是因MPU访问违例造成的MemManage fault,由MFSR.3(MUNSTKERR)指示。且MemManage fault的服务例程必须能立即执行,否则无条件硬fault。

8.3 取向量期间

        在取向量期间发生总线fault,这是非常罕见的一种情况,这也是最严重的,因此直接上硬fault(MPU的限制则管不着取向量操作)。这种情况,由硬fault状态寄存器(HFSR,地址:0xE000_ED2C)中的VECTTBL位(位偏移:1)来指示。

8.4 无效返回时

        如果LR中的EXC_RETURN不是合法的值(合法值见表9.4,包括企图返回ARM状态),则引起用法fault。如果用法fault被除能,也上访成硬fault。此时,用法Fault状态寄存器(UFSR,地址:0xE000_ED2A)中的INVPC位(位偏移:2),或者是INVSTATE位(位偏移:1)置位。

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

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

相关文章

数据恢复技巧:如何恢复已删除的手机短信

短信包含大量重要信息,例如个人联系人、密码和重要业务数据。丢失有价值的数据可能会令人失望,但很高兴知道可以使用多种方法恢复短信。 在本文中,我们将探讨您可以采取哪些步骤来恢复 Android 或 iOS 设备上丢失或删除的短信。 第 1 部分…

chatgpt赋能python:Python指定区域截图:优化截图流程的最佳方式

Python指定区域截图:优化截图流程的最佳方式 在网络时代,图片作为一种重要的信息传播方式,扮演着举足轻重的角色。截图作为最常见的图片处理方式之一,也时常被我们用于记录屏幕内容、报告问题及展示操作流程。 若想提高截图的效…

操作系统-I/O管理-磁盘和固态硬盘

目录 一、磁盘结构 二、磁盘调度算法 ​编辑 2.1先来先服务(FCFS) 2.2最短寻找时间优先(SSTF) 2.3扫描算法(SCAN) 2.4LOOK调度算法 2.5循环扫描算法(C-SCAN) 2.6 C-LOOK调度算法 三、减少延迟时间方法 交替编号 ​磁盘地址结构的设计 错位命名 四、磁盘的管理 4.1磁盘…

JDK自带的构建线程池的方式之newFixedThreadPool

在Java中基于Executors提供了很多种线程池供开发者使用,在Java的并发包下,由并发编程大佬到隔离创建。 newFixedThreadPool 这个线程池的特点是线程数是固定的,下面这个是在Executors类中提供的一种静态方法。在使用的时候需要向方法提供一个…

Excel VBA 语法基础

VBA(Visual Basic for Applications)是一种用于宏编程和自动化任务的编程语言,广泛应用于 Microsoft Office 套件中的各种应用程序,如 Excel、Word 和 PowerPoint。掌握 VBA 基础语法可以帮助您通过编写自定义的宏来增强和自动化这…

python:使用Scikit-image对遥感影像进行角点检测特征提取(corner)

作者:CSDN @ _养乐多_ 本文将介绍使用Scikit-image对遥感影像进行角点检测特征(corner)提取的一些方法及其代码。方法包括 Harris角点检测(corner_harris),Shi-Tomasi角点检测(corner_shi_tomasi),Foerstner角点检测(corner_foerstner),FAST角点检测(corner_fast…

VUE 2X 计算监视属性 ⑥

目录 文章有误请指正,如果觉得对你有用,请点三连一波,蟹蟹支持✨ V u e j s Vuejs Vuejs计算属性 C o m p u t e d Computed Computed监视属性 W a t c h Watch Watch总结 文章有误请指正,如果觉得对你有用,…

Apache Superset产品调研

Apache Superset产品调研 调研报告:Apache Superset 一、概述 Apache Superset是一个开源的数据可视化和数据探索平台,它提供了一个用户友好的界面,可以轻松地创建和分享仪表板。它支持多种数据源,包括SQLAlchemy兼容的数据库、…

io.netty学习(九)Netty 如何实现零拷贝

目录 前言 Java 实现零拷贝 1、Java提供 mmap/write 方式 2、Java 提供 sendfile 方式 Netty 实现零拷贝 1、CompositeByteBuf 方式 2、wrap 方式 3、slice 方式 4、 FileRegion 方式 总结 前言 本篇文章我们就来讲讲 Netty 的零拷贝,在这之前&#xff0…

数据结构练习题1:基本概念

练习题1:基本概念 1 抽象数据类型概念分析2. 逻辑结构与存储结构概念分析3.综合选择题4.综合判断题5.时间复杂度相关习题 1 抽象数据类型概念分析 1.可以用(抽象数据类型)定义一个完整的数据结构。 分析: 1)抽象数据…

【Leetcode -617.合并二叉树 -1022.从根到叶的二进制数之和】

Leetcode Leetcode -617.合并二叉树Leetcode -1022.从根到叶的二进制数之和 Leetcode -617.合并二叉树 题目:给你两棵二叉树: root1 和 root2 。 想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠&#x…

ESP32-IDF VS Code进行开发

ESP32-C3 入门篇(二)使用VS Code进行开发 文章目录 前言 总结STM32的成功,除了Cortex M3的性能强之外,也离不开ST推出的标准库及简单易用的MDK IDE。完善的开发配套,极大的降低了开发门槛,让开发者更专注…

python:使用Scikit-image对遥感影像做空间滤波(中值,高斯,Sobel,Laplace,Scharr等)

作者:CSDN @ _养乐多_ 本文将介绍使用Scikit-image中的滤波函数对遥感影像做空间滤波的代码。滤波方法包括:中值滤波器,高斯滤波器,Sobel滤波器,Laplace滤波器,Scharr滤波器等。并将原始影像和结果影像绘制成图。 结果如下图所示, 文章目录 一、空间滤波函数详解二、…

RocketMQ发送消息

一.消费模式 MQ的消费模式可以大致分为两种,一种是 推Push,一种是 拉Pull。 Push 是 服务端 (MQ) 主动推送消息给客户端,优点是及时性较好,但如果客户端没有做好流控,一旦服务端推送大量消息到客户端时,…

分布式光伏电站智能管理系统

随着能源需求的增加,各种各样的光伏电站工程建设出现不同形式的技术缺陷。设计了分布式光伏电站区域智能系统,实现 了各个园区用电数据的集中管理。对光伏电站分布式运营管理进行了研究,采用集中运营管理中心的方法,建立了区域分布…

蓝牙L2CAP协议简介及报文格式

概述 逻辑链路控制和适配协议(Logical Link Control and Adaptation Protocol,L2CAP)是蓝牙的核心协议,负责适配基带中的上层协议。它同链路管理器并行工作,向上层协议提供定向连接的和无连接的数据业务。L2CAP具有分…

Baumer工业相机堡盟工业相机如何通过BGAPISDK将相机图像写入相机内存(C++)

Baumer工业相机堡盟工业相机如何通过BGAPISDK将相机图像写入相机内存(C) Baumer工业相机Baumer工业相机BGAPISDK和相机内存的技术背景Baumer工业相机通过BGAPISDK将相机图像写入相机内存功能1.引用合适的类文件2.通过BGAPISDK将相机图像写入相机内存功能…

Cortext-M3系统:异常(3)

1、异常 异常响应系统是再M3内核水平上的,支持众多的系统异常和外部中断。1-15为系统异常,大于16为外部中断。除了个别异常的优先级被定死外,其它异常的优先级都是可编程的。优先级数值越小,优先级越高。CM3支持中断嵌套&#xff…

网络嗅探与ARP欺骗

目录 一、网络嗅探概述 1.1 网络嗅探的概念 1.1.2 一把双刃剑 1.1.3 特点 1.2 网络嗅探的原理 1.2.1 网络嗅探的条件 1.2.2 网卡的工作模式 1.2.3 局域网的传输技术 1.3 网络嗅探的前提 1.3.1 网卡设置为混杂模式 1.3.2 同处在一个广播式局域网内 1.4 嗅探工具的使…

4.23 TCP状态转换 4.24半关闭、端口复用

4.23 TCP状态转换 2MSL(Maximum Segment Lifetime) 主动断开连接的一方,最后进入一个TIME_WAIT状态,这个状态会持续:2msl msl:官方建议:2分钟,实际是30s 当 TCP 连接主动关闭方接收到被动关闭方发送的 FIN…