第9章-Cortex-M3异常和中断
Cortex-M3中断.异常
中断号 IPSR (1)异常中断类型
中断向量控制器NVIC
CM3的所有中断机制都由 NVIC 实现。除了支持 240 个外 中断之外,NVIC 还支持16‐4‐1=11 个内部异常源。
虽然CM3 是支持 240 个外中断的,但具体使用了多少个 是由芯片生产商决定。
查询的顺序决定了中断的优先级。当发现一个中断源提出中 断请求后,就转去执行相应的服务程序,而不再继续向下查 找,不管它们是否也提出了请求。中断源1的级别最高,中断 源2的级别次之,中断源n的级别最低。
查询法的优缺点
查询法的优点是硬件简单,程序层次分明,只要改变程序 中的查询次序即可改变中断源的中断优先级,而不必变更 硬件连接。
0 号异常的功能则是个另类,它并不是什么入口地址, 而是给出了复位后MSP的初值。
(3) 嵌套向量中断控制器(NVIC)
Cortex‐M3 在内核上搭载了一颗中断控制器—嵌套向量中 断控制器 NVIC(Nested Vectored Interrupt Controller)。
NVIC 提供如下的功能: 可嵌套中断支持 向量中断支持 动态优先级调整支持 中断延迟大大缩短 中断可屏蔽
当CPU响应中断、保护断点之后,就要进行中断源的识别, 即寻找中断源,找到相应的中断服务程序入口。
识别中断源有三种方法:查询法、向量法和强置程序计数 器法(已被淘汰)。
查询法
通过程序来查询是哪一个中断源提出的中断请求。
过程:在CPU响应中断之后,对所有的中断,都进入到这个 查询流程。先看中断源1是否提出请求,若是,转去执行中断 源1的中断服务程序;否则再看中断源2是否提出请求,若是, 转去执行中断源2的中断服务程序。否则继续查看后面的中断 源…。
Cortex-M3咬尾中断与晚到中断
Cortex-M3咬尾中断与晚到中断【咬尾中断】在处理器在响应某些异常时,如果⼜发⽣其他异常,但它们优先级不够⾼,则它们会被阻塞。
那么,在当前的异常执⾏返回后,系统处理悬起的异常时,倘若还是先POP,然后⼜把POP处理的内容PUSH回去,那么就⽩⽩浪费CPU 时间了。
因此,Cortex-M3不会再POP这些寄存器,⽽是继续使⽤上⼀个异常已经PUSH好的结果,消除POP和PUSH操作的耗时。
这么⼀来,看上去好像后⼀个异常把前⼀个的尾巴要掉了,前前后后只执⾏了⼀次PUSH/POP操作。
于是,这两个异常之间的“时间沟”就变窄了很多,如图所⽰:和常规中断处理(ARM7)的⽐较:【晚到中断】Cortex-M3的中断处理还有另⼀个机制,它强调了优先级的作⽤,这就是“晚到的异常处理”。
当Cortex-M3对某异常的响应序列还处在早期:⼊栈的阶段,尚未执⾏其他服务程序时。
如果此时收到了更⾼优先级异常的请求,则本次⼊栈就成了⾼优先级中断做的了。
⼊栈后,将执⾏⾼优先级的异常服务程序。
可见,⾼优先级的异常虽然来晚了,却因为优先级⾼使得服务程序可以被先处理,低优先级异常的⼊栈操作则变成了为⾼优先级异常的⼊栈。
⽐如,若在响应某低优先级异常#1的早起,检测到了⾼优先级异常#2,则只要#2没有太晚,就能以“晚到中断”的⽅式处理,在⼊栈完毕后执⾏ISR#2。
如图所⽰:如果异常#2来得太晚,以⾄于已经执⾏了ISR#1的指令,则按普通的抢占处理,这会需要更多的处理器时间和额外32字节的堆栈空间。
在ISR#2执⾏完毕后,则以“咬尾中断”的⽅式来启动ISR#1的执⾏。
参考摘录:《Cortex-M内核系列和STM32-讲座2教程.pdf》《ARM Cortex-M3权威指南.pdf》。
CortexM3处理器异常事件相关寄存器
6
——
—— —— ——
5
——
—— —— ——
4
——
—— —— ——
3
USGFAULTACT
R
0 用法 fault 异常事件模块处于活动状态
2
——
—— —— ——
1
BUSFAULTACT
R
0 总线 fault 异常事件模块处于活动状态
0
MEMFAULTACT
R
0 存储器管理 fault 异常事件模块处于活动状态
CortexM3 处理器异常事件相关寄存器
CortexM3 处理器异常事件相关寄存器
一、概述
相对于传统单片机的中断系统,CM3 内核中断处理功能非常强大,但是带来的问题就是寄存器繁多, 不易理解、记忆,造成学习困难。本文对 CM3 内核处理器中断系统的相关寄存器进行分类,以方便学习。
二、控制开关类
2.1 总开关
1) 总标识:是内核提供的申请标识。 2) 子标识:是外设模块自己提供的具体中断申请标识(参见具体芯片手册)。
注 1:类似于 51 系列的各个中断的中断标识位。
注 2:可以人工写 1 来产生软件中断申请。
3.1 针对 CM3 内核系统级异常事件模块
1) 系统 Handler 控制及状态寄存器 SHCSR(地址:0xE000_ED24)。以存储器映射的方式来访问。
位段
名称
类型
复位值
描述
15 SVCALLPENDED R/W
0
SVC 悬起,当前有更高优先级的异常执行中。
14 BUSFAULTPENDED R/W
0
总线 fault 悬起,当前有更高优先级的异常执行中。
13 MEMFAULTPENDED R/W
Cortex—M3的异常处理机制研究
Cortex—M3的异常处理机制研究摘要:详细阐述Cortex-M3异常的分类、优先级、进入和退出,以及在Cortex-M3异常处理机制中使用的新技术——迟到(late-arriving)和尾链(tail-chanining);最后,比较Cortex-M3和ARM7异常控制机制的区别,并量化分析迟到和尾链技术在异常处理中的优越性。
关键词 Cortex-M3 异常迟到尾链中断控制器引言Cortexm—M3是ARM公司第一款基于ARMv7-M的微控制器内核,在指令执行、异常控制、时钟管理、跟踪调试和存储保护等方面相对于ARM7有很大的区别。
尤其在异常处理机制方面有很大的改进,其异常响应只需要12个时钟周期。
NVIC(Nested Vectored Inteirupt Contmller,嵌套向量中断控制器)是Cortex—M3处理器的一个紧耦合部件,可以配置1~240个带有256个优先级、8级抢占优先权的物理中断,为处理器提供出色的异常处理能力。
同时,抢占(pre-emption)、尾链(tail—chaining)、迟到(1ate—arriving)技术的使用,大大缩短了异常事件的响应时间。
异常或者中断是处理器响应系统中突发事件的一种机制。
当异常发生时,Cortex—M3通过硬件自动将编程计数器(PC)、编程状态寄存器(XPSR)、链接寄存器(LR)和R0~R3、R12等寄存器压进堆栈。
在Dbus(数据总线)保存处理器状态的同时,处理器通过Ibus(指令总线)从一个可以重新定位的向量表中识别出异常向量,并获取ISR函数的地址,也就是保护现场与取异常向量是并行处理的。
一旦压栈和取指令完成,中断服务程序或故障处理程序就开始执行。
执行完ISR,硬件进行出栈操作,中断前的程序恢复正常执行。
图1为Cortex—M3处理器的异常处理流程。
1 Cortex—M3异常类型同ARM7相比,Cortex—M3在异常的分类和优先级上有很大的差异,如表1所列。
Cortex-M3 GPIO接口配置和中断管理
GPIO接口配置和中断管理一、中断管理1.Cortex-M3 处理器和嵌套向量中断控制器Cortex-M3 处理器和嵌套向量中断控制器(NVIC)对所有异常按优先级进行排序并处理。
出现异常时,自动将处理器状态保存到堆栈中,并在中断服务程序(ISR)结束时自动从堆栈中恢复。
中断数目可配置为1~240。
中断优先级的数目可配置为1~8 位(1~256 级)。
下图显示了异常类型,优先级以及位置。
位置是指与向量表开始处的字偏移。
在优先级列中,数字越小表示优先级越高。
表中还显示了异常类型的激活方式,即是同步的还是异步的。
优先级的准确含义和使用见异常优先级。
NVIC支持由软件指定的优先级。
通过对中断优先级寄存器的8位PRI_N区执行写操作,来将中断的优先级指定为0~255。
CM3 支持中断嵌套,使得高优先级异常会抢占(preempt)低优先级异常。
有3个系统异常:复位,NMI以及硬 fault,它们有固定的优先级,并且它们的优先级号是负数,从而高于所有其它异常。
所有其它异常的优先级则都是可编程的(但不能编程为负数)。
当发生了异常并且要响应它时, CM3 需要定位其处理例程的入口地址。
这些入口地址存储在所谓的“(异常)向量表”中当中断输入脚被 assert 后,该中断就被悬起。
即使后来中断源取消了中断请求,已经被标记成悬起的中断也被记录下来。
到了系统中它的优先级最高的时候,就会得到响应。
2.CM3响应一个中断a)入栈当处理器调用异常时,它自动将下面的 8 个寄存器按以下顺序压栈:PCxPSRr0~r3r12LR在完成压栈之后, SP 减小8个字。
入栈保护R0‐R3以及R12的原因:有一套的C函数调用标准约定(《 C/C++ Procedure Call Standard for the ARM Architecture》,AAPCS, Ref5)。
原因就在它上面:它使得中断服务例程能用C语言编写,编译器优先使用被入栈的寄存器来保存中间结果。
微处理器9CortexM3异常(中断)处理
Cortex-M3的异常(中断)处理
优先级分组
为了对具有大量中断的系统加强优先级控制,NVIC
支持优先级分组机制。您可以使用应用中断和复位控制寄 存器中的PRIGROUP区来将每个PRI_N中的值分为占先优
先级区和次优先级区。我们将占先优先级称为组优先级。 如果有多个挂起异常共用相同的组优先级,则需使用次优 先级区来决定同组中的异常的优先级,这就是同组内的次 优先级。组优先级和次优先级的结合就是通常所说的优先 级。如果两个挂起异常具有相同的组优先级,则挂起异常 的编号越低优先级越高。这与优先级机制是一致的。
Cortex-M3的异常(中断)处理
优先级分组
中断优先级区(PRI_N[7:0])
占先区
次优先区
PRI_N 7 6 5 4 3 2 1 0
注意: 修改PRIGROUP区的值可改变占先区和 次优先区的位数。
1. 占先优先级又称 为组优先级
2. 如果两个挂起异 常具有相同的组 优先级,则挂起 异常的编号越低 优先级越高。
Cortex-M3的异常(中断)处理
优先级分组
PRIGROU P[2:0]
二进制点 的位置
中断优先级区,PRI_N[7:0]
占先区 次优先 占先优先级
级区
的数目
次优先级 的数目
b000
bxxxxxxx.y [7:1] [0]
128
2
b001
bxxxxxx.yy [7:2] [1:0] 64
4
b010
Cortex-M3的异常(中断)处理
返回
异常基于优先级的动作
在没有挂起异常或没有比被压栈的ISR优先级更高 的挂起异常时,处理器执行出栈操作,并返回到被压 栈的ISR或线程模式。
Cortex-M3处理器中断和FreeRTOS中断优先级配置
Cortex-M3处理器中断和FreeRTOS中断优先级配置很多朋友对中断的一些知识还是不了解,今天就写点关于Cortex-M3处理器中断相关,以及FreeRTOS中断优先级配置的内容。
1写在前面写本文之前,先写点相关的扩展内容。
STM32属于ARM中Cortex-M系列处理器,比如:STM32F1数据Cortex-M3,STM32F7数据Cortex-M7。
可以参看我之前分享文章:从Cortex-M到Cortex-A认识ARM处理器,了解一下关于ARM 处理器的种类。
本文主要结合Cortex-M3下面STM32F1系列处理器为例来讲述中断控制相关内容。
而Cortex-M其它系列,或者说STM32其它系列关于中断的内容类似。
Cortex-M3只是STM32F1的一个内核。
反过来说STM32F1是在Cortex-M3基础上增加了一些外设(如:USART、AD等)的芯片。
2STM32中断控制NVIC:Nested Vectored Interrupt Controller,即嵌套向量中断控制器。
STM32中NVIC我们比较熟悉,编程的时候使用中断都会对NVIC进行配置。
而STM32F1中的NVIC是属于Cortex-M3中的一部分,而不是STM32增加的外设。
NVIC向量中断控制器是Cortex‐M3不可分离的一部分,它与CM3 内核的逻辑紧密耦合,有一部分甚至水乳交融在一起。
所以,NVIC相关的寄存器位于Cortex-M手册中。
讲述STM32的中断控制,还得从Cortex-M3的NVIC讲起,1.中断输入向量表Cortex-M3的NVIC支持1至240个中断输入,比如STM32中xxxIRQs,也就是中断向量表,具体的数值由芯片厂商在设计芯片时决定。
比如STM32F1的中断和异常向量表:2.中断和异常区别很多初学的朋友不知道什么是中断?什么是异常?甚至有人直接把中断和异常笼统称为“中断”。
中断和异常其实有差异,也有关联,我们常说的中断其实是包含了异常。
Cortex-M3中断响应和中断返回过程分析
一、中断/异常响应当CM3开始响应一个中断时,它的内部会依次自动地进行以下三个操作:●入栈:把8个寄存器的值压入栈。
●取向量:从向量表中找出对应的服务程序入口地址。
●选择堆栈指针MSP/PSP,更新堆栈指针SP,更新连接寄存器LR,更新程序计数器PC。
1.入栈响应中断的第一个操作,就是自动保存现场:依次把xPSR(程序状态寄存器)、PC、LR、R12以及R0~R13由硬件自动压入适当的堆栈中。
响应中断时,如果当前代码使用的是PSP,也就是使用进程堆栈,则压入PSP;否则就压入MSP。
一旦进入服务例程,代码就将一直使用主堆栈(MSP)。
假设入栈开始时,SP的值为N,则在入栈后,堆栈内部的变化如下表所列。
另外,在自动入栈的过程中,寄存器压栈的先后顺序,并不与其在堆栈的位置相对应。
但是硬件会保证寄存器被保存到正确的位置,如下表的第3列所示。
表1 入栈顺序以及入栈后堆栈内容先保存PC与xPSR的值,就可以更早地启动服务例程指令的预取;同时,也可以做到在早期更新xPSR中IPSR位段的值。
至于为何保存R0~R3和R12的值,则是根据ARM的C函数调用标准约定(AAPCS,Ref5):它使得中断服务例程能用C语言编写,编译器优先使用入栈的寄存器来保存中间结果。
2.取向量当数据总线正在为入栈操作而忙得风风火火时,指令总线则正在为响应中断紧张有序地执行另一项重要的任务:从向量表中找出正确的中断向量,然后在服务程序的入口处预取指。
由此可以看到各自都有专用总线的好处:入栈和取指可以同时进行。
3.更新寄存器入栈和取向量操作完成后,在执行服务例程之前,还要更新一系列寄存器。
SP:入栈后堆栈指针(PSP或MSP)更新到新的位置。
执行服务例程时,将由MSP负责对堆栈的访问。
PSR:更新IPSR位段(PSR的最低部分)的值更新为新响应的中断编号。
PC:取向量完成后,PC指向服务例程的入口地址。
LR:在出入ISR的时候,LR的值将被重新诠释,这种特殊的值称为“EXC_RETURN”,该值在中断进入时由系统计算并赋给LR,并在中断返回时使用它。
ARMCortex-M3权威指南-中断和异常(2)
ARMCortex-M3权威指南-中断和异常(2)中断和异常它⽀持16-4-1=11 种系统异常(同步)(保留了 4+1 个档位),外加 240 个外部中断输⼊(异步)。
在 CM3 中取消了 FIQ 的概念(v7 前的ARM 都有这个 FIQ,快中断请求),这是因为有了更新更好的机制——中断优先级管理以及嵌套中断⽀持,它们被纳⼊ CM3 的中断管理逻辑中。
因此,⽀持嵌套中断的系统就更容易实现 FIQ。
虽然 CM3 是⽀持 240 个外中断的,但具体使⽤了多少个是由芯⽚⽣产商决定。
CM3还有⼀个NMI(不可屏蔽中断)输⼊脚。
当它被置为有效(assert)时, NMI 服务例程会⽆条件地执⾏。
NMI 究竟被拿去做什么,还要视处理器的设计⽽定。
在多数情况下, NMI 会被连接到⼀个看门狗定时器,有时也会是电压监视功能块,以便在电压掉⾄危险级别后警告处理器。
向量表当 CM3 内核响应了⼀个发⽣的异常后,对应的异常服务例程(ESR)就会执⾏。
为了决定 ESR 的⼊⼝地址, CM3 使⽤了“向量表查表机制”。
这⾥使⽤⼀张向量表。
向量表其实是⼀个 WORD(32 位整数)数组,每个下标对应⼀种异常,该下标元素的值则是该 ESR 的⼊⼝地址。
向量表在地址空间中的位置是可以设置的,通过 NVIC 中的⼀个重定位寄存器来指出向量表的地址。
在复位后,该寄存器的值为 0。
因此,在地址 0 处必须包含⼀张向量表,⽤于初始时的异常分配。
举个例⼦,如果发⽣了异常 11(SVC),则 NVIC 会计算出偏移移量是11x4=0x2C,然后从那⾥取出服务例程的⼊⼝地址并跳⼊。
要注意的是这⾥有个另类: 0 号类型并不是什么⼊⼝地址,⽽是给出了复位后MSP 的初值。
CM3允许向量表重定位即从其它地址处开始执⾏各异常向量。
这些地址对应的区域可以是代码区,但也可以是 RAM 区。
在 RAM区就可以修改向量的⼊⼝地址了。
为了实现这个功能, NVIC中有⼀个寄存器,称为“向量表偏移量寄存器”(在地址 0xE000_ED08 处),通过修改它的值就能定位向量表。
ARM之Cortex-M内核中断异常系统详解
ARM之Cortex-M内核中断异常系统详解问题最近在使用STM32F3芯片的时候,遇到这样一个问题:如果外部中断来的频率足够快,上一个中断没有处理完成,新来的中断如何处理?在调试时,发现有中断有挂起、激活、失能等状态,考虑这些状态都是干啥用的呢!他们是Cortex-M核所共有的,因此这里不针对与具体用的STM32 MCU,直接上升到 Cortex-M内核来了解一下!简介 中断(也称为“异常”)是微控制器一个很常见的特性。
中断一般是由硬件(例如外设、外部引脚)产生,当中断产生以后 CPU 就会中断当前的程序执行流程转而去处理中断服务中指定的操作。
所有的Cortex-M 内核都会系统一个用于中断处理的组件:NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)。
它处理处理中断,还处理其他需要服务的事件(例如 SVC 指令),通常称为“异常”。
按照 ARM 的说法,中断也是一种异常。
Cortex-M3和 Cotex-M4 的 NVIC 最多支持 240 个 IRQ(中断请求)、1 个不可屏蔽中断(NMI)、1个 Systick(滴答定时器)定时器中断和多个系统异常。
而 Cortex-M0 最多支持32个IRQ、1 个不可屏蔽中断(NMI)、1 个 Systick(滴答定时器)定时器中断和多个系统异常。
IRQ:多数由定时器、IO端口、通信接口等外设产生NMI:通常由看门狗定时器或者掉电检测器等外设产生其他:主要来自系统内核注意,本文所说的 Cortex-M 主要指定是 Cotex-M3和 Cotex-M4。
Cortex-M0、Cortex-M0+、Cortex-M1 基于 ARMv6-M。
与Cotex-M3和 Cotex-M4相比,他们的指令集较小。
而且,Cortex-M1 是专门为FPGA应用设计的,没有独立MCU。
异常类型 Cortex-M 处理器的异常中,编号 1~15 的为系统异常,16及以上的则为中断输入。
CortexM3处理器异常事件响应过程
CortexM3处理器异常事件响应过程一、异常事件响应流程示意图注:粗线条表示用户代码管理过程。
二、异常事件产生阶段1)入栈:硬件自动保存现场环境状态参数,依次把xPSR、PC(R15)、 LR(R14)、R12以及R3~R0共8个寄存器压入当前使用的堆栈中(可能为PSP也可能为MSP,取决于处理器之前的选择)。
2)取向量:硬件自动获取异常事件服务程序的入口地址并开始从这个地方预取指(并行工作)。
3)更新相关寄存器:(1)SP(R13):在入栈过程中由硬件把堆栈指针(PSP或MSP)更新到新的位置。
在执行服务例程时,将由MSP负责对堆栈的访问。
(2)PSR:更新IPSR位段(位于PSR的最低部分)的值为新响应的异常编号(提示信号)。
(3)PC(R15):在取向量完成后,PC将指向服务例程的入口地址。
(4)LR(R14):在出入ISR的时候,LR(R14)的值将得到重新的诠释,这种特殊的值称为“EXC_RETURN”(准备好回家的路线和要求(最低4位进行控制))。
但是注意LR原来的值已经入栈(也许它刚好在调用子程序,其中存的就是调用点之后的地址参数),进入异常事件响应阶段后才装入EXC_RETURN参数。
假如在这个过程中又出现了更高级别的异常事件,则前面的EXC_RETURN参数也会被入栈且又会装入新的EXC_RETURN参数。
三、异常事件执行阶段为安全起见,最好在代码中将R4~R11人工压栈处理(在C语言环境,编译器会根据寄存器的使用状况决定是否对他们进行压栈操作)。
四、异常事件返回阶段4.1 返回操作触发信号一般芯片有专门的中断返回指令,例如51的RETI指令,执行它后就会将先前保存的地址自动弹回PC。
而CM3是靠将EXC_RETURN参数装入PC寄存器来实现的。
它将启动异常事件服务程序返回操作。
1)出栈:先前压入堆栈的寄存器参数得到恢复(包括PC的值),堆栈指针自动回到先前入栈时的位置。
2)更新NVIC寄存器:该寄存器之异常事件活动指示位被硬件自动清除。
cortex-m3中断系统结构
cortex-m3中断系统结构Cortex-M3中断系统结构是一个重要的主题,它涉及到处理器的核心功能之一。
Cortex-M3处理器的中断系统结构包括中断向量表、中断优先级和中断控制器三个主要方面。
首先,让我们来谈谈中断向量表。
Cortex-M3处理器使用中断向量表来存储中断服务程序的入口地址。
当发生中断时,处理器会根据中断号从中断向量表中找到对应的中断服务程序的入口地址,并跳转到该地址开始执行中断服务程序。
中断向量表通常位于处理器的起始地址处,每个中断都有一个固定的位置,以便处理器能够快速找到对应的中断服务程序。
其次,中断优先级是Cortex-M3中断系统结构中的另一个重要方面。
Cortex-M3处理器支持多级中断优先级,允许开发人员为不同的中断设置不同的优先级。
这样可以确保在多个中断同时发生时,处理器能够按照优先级顺序来响应中断,以保证关键的中断能够及时得到处理。
最后,中断控制器是Cortex-M3中断系统结构的第三个方面。
中断控制器负责管理中断的使能、屏蔽和清除操作。
它还负责处理中断的优先级和中断请求的响应顺序。
Cortex-M3处理器的中断控制器通常具有灵活的配置选项,可以根据应用需求进行调整。
总的来说,Cortex-M3处理器的中断系统结构包括中断向量表、中断优先级和中断控制器三个主要方面,这些方面共同构成了处理器对中断的管理和响应机制。
对于嵌入式系统开发者来说,深入理解Cortex-M3中断系统结构是非常重要的,可以帮助他们更好地设计和实现中断服务程序,提高系统的稳定性和可靠性。
深入探讨ARM CORTEX—M3处理器中断异常系统的使用
深入探讨ARM CORTEX—M3处理器中断异常系统的使用【摘要】本文介绍了ARM CORTEX-M3处理器中断异常系统的使用,包括堆栈建立,向量表建立,中断优先级分配,软件中断等。
同时,本文着重论述了使用中的一些注意事项,如防止堆栈溢出,跨器件移植,数据同步隔离指令的使用等。
【关键词】中断;异常;堆栈;向量表一、概述ARM CORTEX-M3处理器基于32位ARMv7-M架构,拥有性能强劲,功耗低,实时性好,成本低,使用方便等优势。
CORTEX-M3在内核水平上搭载了一个中断异常系统,支持众多的系统异常和外部中断。
其中,编号为1-15的对应系统异常,大于等于16的则全是外部中断。
除了个别异常的优先级被定死外,其它异常的优先级都是可编程的。
在CORTEX-M3中,中断控制器自动执行了很多使用中断时的例行任务,如优先级检查、入栈、出栈、取向量等。
不过在中断控制器能自动执行任务之前,还需要我们做好如下的初始化工作:建立堆栈、建立向量表、分配各中断的优先级、使能中断。
二、堆栈建立当开发的程序比较简单时,可以从头到尾都只使用主堆栈。
这时,只需要保证开出一个容量够大的堆栈,再把主堆栈初始化到其顶即可。
这也是单片机开发最常见的做法。
堆栈溢出是非常致命的错误,必须非常严谨地计算安全容量。
在计算时,除了要计入最深函数调用时对堆栈的需求,还需要判定最多可能有多少级中断嵌套。
一个方法是假设每个中断都可以嵌套。
对于每一级嵌套的中断,至少需要8个字(32字节),而且如果中断服务程序过于复杂,还可能有更多的堆栈需求。
因为CORTEX-M3中的堆栈是以“向下生长的满栈”来操作堆栈指针的,在简单的场合中,经常可以把堆栈指针初始化为SRAM的末尾,这么一来就使所有的空闲内存都能为堆栈所用。
对于比较大型的或者是有高性能指标的嵌入式系统,往往需要两个堆栈(主堆栈和进程堆栈)配合使用[1]。
这时,必须保证各堆栈都有足够的容量,尤其是主堆栈,最容易溢出。
Cortex-M3 异常和中断
0.前言本文想解决的问题有:∙如何开启、关闭中断∙如何开启、关闭异常∙LPC177x/8x支持的中断优先级个数∙复位后,异常/中断默认的优先级∙如何设置异常/中断的优先级∙什么是优先级组,如何设置优先级组,复位后的优先级组1. Cortex-M3的异常/中断屏蔽寄存器组注:只有在特权级下,才允许访问这3个寄存器。
注:寄存器BASEPRI的有效位数受系统中表达优先级的位数影响,如果系统中只使用3个位来表达优先级,则BASEPRI有意义的值仅为0x00、0x20、0x40、0x60、0x80、0xA0、0xC0和0xE0使用MRS/MSR指令访问这三个寄存器,比如:MRS R0, BASEPRI ;读取BASEPRI到R0中MSR BASEPRI, R0 ;将R0数据写入到BASEPRI中为了快速的开关中断,CM3还专门设置了一条CPS指令,有四种用法:CPSID I ;PRIMASK=1,关中断CPSIE I ;PRIMASK=0,开中断CPSID F ;FAULTMASK=1,关异常CPSIE F ;FAULTMASK=0,开异常CMSIS-M3微控制器软件接口标准中的core_cm3.h给出了开关中断或异常的函数:1.1 开/关中断1:/**2: * @brief Set the Priority Mask value3: *4: * @param priMask PriMask5: *6: * Set the priority mask bit in the priority mask register7: */8:static __INLINE void __set_PRIMASK(uint32_t priMask)9: {10:register uint32_t __regPriMask __ASM("primask");11: __regPriMask = (priMask);12: }使用__set_PRIMASK(1)关闭中断;__setPRIMASK(0)开启中断。
CortexM3处理器异常事件相关寄存器
0xE000_E100
SETENA1 ……
SETENA7
0xE000_E104 0xE000_E11C
类型 R/W R/W
R/W
复位值 0 0
描述 中断 0-31 的使能寄存器,共 32 个使能控制位[n],中断 n 使能 (异常号 16+n) 中断 32-63 的使能寄存器,共 32 个使能控制位
类型 复位值
描述
PRI_4
0xE000_ED18 R/W
存储器管理 fault 异常事件模块的优先级
PRI_5
0xE000_ED19 R/W
总线 fault 异常事件模块的优先级
PRI_6
0xE000_ED1A R/W
用法 fault 异常事件模块的优先级
——
0xE000_ED1B —— ——
——
0xE000_ED1C —— ——
12 USGFAULTPENDED R/W
0
用法 fault 悬起,当前有更高优先级的异常执行中。
2) 中断控制及状态寄存器(地址:ICSR 0xE000_ED04)。以存储器映射的方式来访问。
位段
名称
类型
复位值
描述
31
NMIPENDSET
R/W
0
写 1 悬起 NMI,立即进入 NMI 服务例程(因为 NMI 不可能被屏蔽)。
说明:51 系列无此特性。
位段
名称
类型 复位值
描述
23
ISRPREEMPT
R
0 如为 1,表示一个悬起的异常将在下一时刻进入活动状态。
22
ISRPENDING
R
0 如为 1,表示当前正有外部中断被悬起(不包括 NMI)
CortexM3处理器工作模式及中断过程
CortexM3处理器工作模式及中断过程1. 工作模式线程模式(Thread mode):处理器复位或异常退出时为此模式。
处理模式(Handler mode):出现异常(包括中断)时进入此模式,此模式下所有代码为特权访问。
2. 工作状态Thumb状态(正常执行指令状态)和调试状态3. 代码限权特权访问:对处理器资源拥有完全访问限权;处理器复位后进入此访问模式;清零 CONTROL[0]进入用户模式。
用户访问:禁止访问多数系统寄存器。
只能通过进入异常(中断)来返回特权模式。
4. M3寄存器r0-r12:通用寄存器,其中r8-r12只能被32位指令访问。
r13(SP):堆栈指针;线程模式时可以在线程堆栈和主堆栈之间切换,但处理模式只使用主堆栈。
两个堆栈同一时刻只有一个可见,进入、退出异常时自动切换堆栈。
r14(LR):链接寄存器,保存子程序或异常的返回地址(要实现嵌套,必须入栈)。
r15(PC):程序计数器xPSR:特殊用途的程序状态寄存器5. 异常进入异常步骤:1.处理器在当前堆栈上把xPSR、PC、LR、r12、r3~r0八个寄存器自动依次入栈。
2.读取向量表(如果是复位中断,更新SP值)3.根据向量表更新PC值4.加载新PC处的指令(2、3、4步与1步同时进行)5.更新LR为EXC_RETURN(EXC_RETURN表示退出异常后返回的模式及使用的堆栈)。
退出异常步骤:1. 根据EXC_RETURN指示的堆栈,弹出进入中断时被压栈的8个寄存器。
2. 从刚出栈的IPSR寄存器[8:0]位检测恢复到那个异常(此时为嵌套中断中),若为0则恢复到线程模式。
3. 根据EXC_RETURN,选择使用相应SP。
末尾连锁(Tail-chaining):当前正在执行中断,又有一个中断到来且这个中断优先级比正在执行的中断优先级低(如果有其他被压栈的低优先级中断则要比这些中断优先级高),这个中断暂时被挂起,等到当前中断执行完后不再执行堆栈操作,而直接进入挂起的中断。
ARM Cortex-M3中断跳转过程
ARM Cortex-M3中断跳转过程在学习CM3的时候,仔细学习了CM3的中断跳转过程,发现嵌入式的MCU在这一块基本上是一样的,当然不同架构的MCU也有自己的特性。
我来介绍下CM3的中断跳转过程,首先假设中断发生,CM3内核开始响应中断,由于不同厂家的CM3可能略有区别,但CM3的内核肯定是一样的,所以我们在这个前提下开始讨论,暂时把中断屏蔽位,标志位之类的东西放在一边。
现在介绍中断响应的过程:1、压栈。
从这一点来讲几乎所有的处理器都是一样的,用压栈保护现场。
压入哪些寄存器呢,又是怎样一个顺序?如果就大多数的C语音编程来讲,这个不是很关心的内容。
但是CM3的压栈寄存器特点,让我们来见识下ARM设计的特点。
其压栈顺序如下图所示,请注意压栈的地址顺序和时间顺序不是相同的。
这一点就我们普通coding来讲,是非常奇特的,堆栈的空间顺利和进栈时间没有必然联系,跟我们“后进先出”的观点有很大出入,那么显然这里的“堆栈”,并不是我们传统意义的上的堆栈,具体怎样实现ARM没有详述,只是说他们可以做到这点。
我们可以看到PC,xPSR,R0,R1,R2,R3是率先入栈的(时间上),这样做的目的,是为了编译器优先使用入栈了的寄存器来保存中间结果(如果程序过大也可能要用到R4-R11,此时编译器负责生成代码来push它们)。
这也是要求ISR尽量短小的原因,用更少的寄存器,以加快响应。
2、查找中断向量表。
其实这一步跟第一步是并行的,只是为了分别介绍我,列了序号。
ARM是有D-Code(数据总线)和I-Code(指令总线),两条总线。
可以看到PC是第一个压栈的,此时数据总线正忙于压栈操作,与此同时指令总线就可以查找中断向量表,查询中断服务程序的入口地址。
在CM3中中断向量表位于地址从0x00000000开始的一段存储空间,每个表项占一个字(4byte)。
这是中断向量表没有重定位的情况,当然中断向量表也可以重定位,即存储在其他地方。
关于cortex m3的中断优先级描述
关于cortex-M3的中断优先级的描述1. 和之前的ARM7不同,cortex-m3 使用NVIC(嵌套向量中断管理器)来管理系统的中断。
2. 每一个中断源的优先级由3个位来决定,这3个位就是中断优先级寄存器器里(PRIx)的INTn,这里的n 一般是A、B、C、D。
3. 每个中断源的优先级由2部分组成,一部分表示中断组别,一部分表示同组的优先级编号。
组别优先级高的中断源,可以打断组别优先级低的中断处理,同一个组的中断源不能打断正在处理的中断,只能在进入中断处理时,同时发生的两个中断源进行判别优先级。
4. 我们把中断源的优先级组别和同组内的中断编号分别用抢占式优先级别和子优先级别来表示。
他们的具体表现形式就是第2条提到的INTn。
5. 由于这INTn的3个位只能表示0-7 总共8个数字,所以在这3个位之外,系统安排了另一个寄存器来说明这3个位时如何使用的,这个寄存器就是APINT。
APINT中的PRIGROUP位域就是对中断优先级的这3个位如何分配使用进行说明的,它是针对整个系统而言的,而不是针对某一个中断源而言的。
INTn的3个位可以有4种组别管理模式,由APINT的PRIGROUP描述,换句话说PRIGROUP的值描述了如何使用这3个位。
下面的表就列出了对应不同的PRIGROUP的值,如何去分析PRIX的INTn6. 我们在设置系统的中断级别符合分组管理的时候调用IntPriorityGroupingSet(), 这个函数修改的就是APINT寄存器中的PRIGROUP。
7. 我们针对每一中断源设置优先级,调用IntPrioritySet(),这个函数针对的就是PRIx寄存器中每个中断源对应的3个bits 即INTn.8. 举个例子说明,有两个中断源,A中断的中断优先级级置成INTA = b011,B 中断的中断优先级设置成INTB = b001,。
单单依靠这两个设置我们是无法判断A,B是如何进行中断调度的,我们首先要看中断的组别管理是如何的。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第九章Cortex-M3异常和中断9.1Cortex-M3异常91C t M39.2NVIC与中断控制929.1.1 异常类型异常。
CM3支持为所有能打断正常执行流的事件都称为CM3支持为数众多的系统异常和外部中断。
异常是另一种形式的中断,它是由内部fault引起的,或者内核的SysTick、SVCall等。
而中断是由随机的外部事件引发的。
件引发的编号为1~15的对应系统异常;编号为16~255的对应外部中断。
除了个别异常的优先级被定死外,其它异常的优先级都是可编程的。
可编程的当前运行的异常编号,是由特殊寄存器IPSR或NVIC的中断控制状态寄存器来给出的。
断控制状态寄存器来给出的异常表异常号异常类型优先级描述0N/A N/A没有异常在运行1复位-3 (最高)复位2NMI-2 不可屏蔽中断(外部NMI 输入)3硬件fault-1各种fault情况4内存管理fault可编程内存管理fault;MPU 访问非法地址5总线fault可编程总线fault,比如预取终止6用法fault可编程由于程序fault或尝试访问协处理器导致的异常7-10保留N/A—11SVCall可编程系统服务调用12调试监视器可编程调试监视器(续)13保留N/A—14PendSV可编程可挂起系统设备申请15SysTick可编程系统时钟定时器16外部中断#0可编程外部中断17外部中断#1可编程外部中断…………255外部中断#239可编程外部中断当一个被使能的异常发生时,如果它不能够被立即执行,它将被挂起(pending)。
9.1.2 优先级定义在CM3中优先级对于异常来说很关键的它决定一个 在CM3中,优先级对于异常来说很关键的,它决定个异常是否能被屏蔽,以及在未被屏蔽的情况下何时可以响应。
应优先级的数值越小,则优先级越高。
CM3支持中断嵌套,使得高优先级异常会抢占(preempt)低优先级异常。
3个系统异常:复位、NMI以及硬fault有固定的优先级,并且它们的优先级号是负数,从而高于所有其它异常。
Cortex-M3支持256级可编程异常,所有其它异常的优先Cortex M3支持256级可编程异常,所有其它异常的优先级则都是可编程的。
减少优先级数可以通过减少优先级配置寄存器的一些低位减少优先级数可以通过减少优先级配置寄存器的些低位来实现。
3bits优先级Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0,使用不使用, 读出值为0Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit04bits优先级Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0使用不使用, 读出值为0优先级寄存器的最小宽度值为3比特.3位表达的优先级VS.4位表达的优先级使用3-bit, 5-bit, 和8-bit 优先级寄存器优先级异常类型3比特表达5比特表达8比特表达3333-3(Highest)复位-3-3-3-2NMI-2-2-2-1硬件错误-1-1-1具有优先0x000x01 01级并且可编程的异0x000x200x000x080x00, 0x010x02, 0x03…0xFF常…0xE0…0xF8…0xFE, 0xFF抢占优先级和次优先级通过NVIC中“应用程序中断及复位控制寄存器的位段“PRIGROUP优通过中应用程序中断及复位控制寄存器的位段优先级组”设置。
该位段的值对每一个优先级可配置的异常都有影响,把其优先级分为2个位段:MSB所在的位段(左边的)对应抢占优先级,对于不同的优先组设置,抢占优先字段和次优先级字段在优先级寄存器中的定义而LSB所在的位段(右边的)对应次优先级。
优先组抢占优先级字段次优先级字段0Bit [7:1]Bit [0]1Bit [7:2]Bit [1:0]2Bit [7:3]Bit [2:0]3Bit [7:4]Bit [3:0]Bit [7:5]Bit [4:0]4Bit [7:5]Bit [4:0]5Bit [7:6]Bit [5:0]6Bit [7]Bit [6:0][][]7None Bit [7:0]应用程序中断和复位控制寄存器AIRCR(地址0xE000ED0C)Bits名称类型复位值描述31:16VECTKEY R/W —存取关键字;为了写入这个寄存器必须向这个地址写人0x05FA 15ENDIANNESS R —表示数据的排列顺序:1 表示大端(BE8)(BE8) 而0表示小端10:8PRIGROUP R/W 0优先级分组—请求芯片控制逻辑产生一个复位信号2SYSRESETREQ W 请求芯片控制逻辑产生个复位信号1VECTCLRACTIVE W —清除异常的所有活跃状态信息0VECTRESET W —复位Cortex-M3 处理器。
但不会复位处理器以外的电路。
优先组设置的例子Bit7Bit6Bit5Bit4~Bit 0抢占级次不使用, 读出值0Bit7Bit6Bit5Bit4~Bit2Bit1Bit0抢占级不使用次优先级配置寄存器的宽度331优先组5抢占优先级48次优先级数2—Bit 7抢占优先级抢占优先级[7:5]Bit 6Bit 5次优先级Bit 4抢占优先级bit[4:2] (未使用,总是0)Bit 3Bit 2Bit1次优先级(未使用总是0)Bit 1次优先级(未使用,总是0)Bit 09.1.3 向量表响应异常时,CM3需要定位其服务例程的入口地址。
这响应异常时CM3需要定位其服务例程的入口地址这些入口地址被存储在“(异常)向量表”中。
上电后的异常向量表地址异常号值(大小为“字”)0x00000000—MSP 初始值0x000000041复位向量(程序计数器初始值)0x000000082NMI 服务例程的入口地址0x0000000C3硬件故障服务例程的入口地址……其它异常服务例程的入口地址通过设置NVIC中的向量表偏移寄存器,可以将向量表重定位到其它的内存地址。
该地址偏移需要与向量表的大小对齐,扩展到2的若干次幂例:IRQ32IRQ 输入: 32总异常数:32 + 16 (system exceptions) = 48扩展到2的幂: 64.乘以4: 256.4:256.向量表地址偏移可以被编程为0x0, 0x100, 0x200等等。
向量表偏移寄存器VTOR(地址0xE000ED08)Bits名称类型复位值描述29TBLBASE R/W0表基地址在Code (0) 或RAM (1)28:7TBLOFF R/W0来自CODE区或RAM区的表偏移范围为了允许动态修改向量表,向量表的起始处包含以下向量:1. 主堆栈指针的初始值;2. 复位向量;3. NMI向量;3NMI4. 硬件fault服务例程。
9.1.4 中断输入和悬起行为⏹当中断输入脚被置为有效(assert)后,该中断就被悬起。
即使后来中断源撤消了中断请求,已经被标记成悬起的中断也被记录下来。
到了系统中它的优先级最高的时候,就会得到响应。
如果在某个中断得到响应之前其悬起状态被清除了(例如在⏹如果在某个中断得到响应之前,其悬起状态被清除了(例如,在PRIMASK或FAULTMASK置位的时候软件清除了悬起状态标志),则中断被取消。
中断挂起中断在得到处理器响应之前被清除悬起状态当处理器开始执行一个中断,称其进入“激活”状态,同时挂起位将被自动清除同时挂起位将被自动清除。
处理器进入服务例程后,中断激活状态的设置如果一个中断源持续保持中断请求信号活跃,在中断服务程序结束时中断将被再次挂起务程序结束时,中断将被再次挂起。
在中断结束后,连续中断请求再次挂起如果一个中断在处理器执行前,其请求信号多次以脉冲的方式出现,则将被视为一次中断请求,而不是多次。
只有一次中断挂起,即使在服务例程执行前有多个脉冲如果一个中断请求释放,但在服务例程结束前再次被置为有效,那么它将仍然会被再次挂起。
执行服务例程期间再次挂起中断9.1.5 Fault异常有若干个系统异常专用于处理中的可分为以下几有若干个系统异常专用于fault处理。
CM3中的Faults可分为以下几类:⏹ 总线faults存储器管理faults⏹ 存储器管理faults⏹ 用法faults⏹ 硬fault9.1.5.1 总线错误当在AHB接口数据传输过程中一个fault响应被接收时,总线fault将会产生。
总线fault可能发生的情况:1. 取指令;2. 数据读/写;2数据读/写3. 在中断处理开始阶段的压栈;中断处结束阶段的出栈;4. 中断处理结束阶段的出栈;5. 当处理器启动中断服务序列后, 读取一个中断向量地址。
当这些类型的总线fault发生时:If1. 该总线fault的服务例程被使能.2. 没有其它同级的异常在运行.Then该总线服务例程将被执行.Else if同时处理器接收另一个更高优先级的异常.Then线常将被总线fault的异常将被挂起.在一些特殊的情况下, 硬件fault服务例程将被执行,内核将进入锁定状态。
NVIC 有一些fault状态寄存器. 其中一个就是总线fault 状态寄存器()(BFSR).总线fault状态寄存器BFSR(0xE000ED29)Bits名类型复位值描述7BFARVALID—0=1时表示BFAR 无效6:5————4STKERR R/Wc0入堆栈时发生错误3UNSTKERR R/Wc0出堆栈时发生错误2IMPREISERR R/Wc0不精确的数据访问违例1PRECISERR R/Wc0精确的数据访问违例R/W0IBUSERR R/Wc0取指的访问违例9.1.5.2 存储器管理Fault常见的存储器管理fault包括:1. 在MPU启动后,访问了MPU区域之外的地址;2. 访问了没有存储器与之对应的空地址;33. 从不可执行的存储器区域试图取指;4. 向只读区域写数据;5. 在用户级下访问了只允许特权级下访问的特权地址。
当存储器fault发生时,if1. 该存储器管理fault服务例程被使能。
2. 没有其它相同或更高优先级异常在运行。
Then存储器管理fault服务例程将被执行。
Else if同时,处理器接受另个具有更高有优先级的异常。
同时,处理器接受另一个具有更高有优先级的异常。
Then存储器管理fault异常将被挂起。
在一些特殊的情况下, 硬件fault服务例程将被执行, 或者内核将进入锁定状态。
NVIC包括一个存储器管理fault寄存器(MFSR) 来映射存储器管理fault的情况。
存储器管理fault寄存器MFSR(0xE000ED28)Bits名称类型复位值描述7MMARVALID—0=1表示MMAR有效6:5————4MSTKERR R/Wc0入堆栈时发生错误3MUNSTKERR R/Wc0出堆栈时发生错误2————1DACCVIOL R/Wc0数据访问违例0IACCVIOL R/Wc0取指访问违例9.1.5.3 用法Fault可以引起用法fault的有:的有1. 执行了协处理器指令;2. 执行了未定义指令;33. 尝试转换到ARM状态;4. 无效中断返回(链接寄存器包括无效/不正确的数值);5. 使用多重加载或存储指令时,地址没有对齐;通过设置NVIC中的些位,产生用法fault:中的一些位,1.除以0;22.任何非连续内存访问.当一个用法fault产生时,if1. 用法fault服务例程使能。