-
2019-10-09 18:01:51
单片机的中断分为抢占优先级和响应优先级(子优先级),中断时首先由抢占优先级决定产生哪个中断。
抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。
高的抢占式优先级可以打断低的抢占式优先级,故名抢占;而在抢占式优先级相同的情况下,响应优先级越高,同时发生则先响应它,但是不能打断低响应优先级,响应表达的是响应速度。
在解释一下这里的两点:第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。
结合实例说明一下:假定设置中断优先级组为 2,然后设置中断 3(RTC_WKUP 中断)的抢占优先级为 2,响应优先级为 1。中断 6(外部中断 0)的抢占优先级为 3,响应优先级为 0。中断 7(外部中断 1)的抢占优先级为 2,响应优先级为 0。那么这 3 个中断的优先级顺序为:中断 7>中断 3>中断 6。
抢占优先级和响应优先级,其实是一个中断所包含的两个优先级,其中前者是对抢占优先级的级别划分,后者是相同抢占优先级的优先级别的划分。
比如:中断A抢占优先级比B高,那么A的中断可以在B里面触发,忽略响应优先级
A和B抢占优先级相同,则A、B的响应优先级决定谁先响应。
参考:https://blog.csdn.net/lr1916417519/article/details/81057810
更多相关内容 -
ARM中断模式(IRQ)和快速中断模式(FIQ)区别比较
2020-07-21 22:47:26本文主要对ARM中断模式(IRQ)和快速中断模式(FIQ)区别进行了说明,希望对你的学习有所帮助。 -
Arm 中断管理 源码.
2018-04-20 14:21:14Arm 中断管理基于ucosIII的源码,清晰地展现基本的中断管理操作,可用KeilC编译。 -
最通俗易懂的方式讲解ARM中断原理以及中断嵌套
2020-07-13 18:12:44这可能是最通俗易懂的方式讲解ARM中断原理以及中断嵌套 -
ARM中断编程.rar
2021-01-04 23:07:25ARM中断编程 -
嵌入式系统/ARM技术中的ARM中断处理类型
2020-11-13 02:20:54ARM内核支持7种中断,不同的中断处于不同的处理模式(如表1所示),具有不同的优先级,而且每个中断都有固定的中断入口地址。当一个中断发生时,相应的R14(LR)存储中断返回地址,SPSR存储状态寄存器CPSR的值。 ... -
ARM中断
2020-07-24 15:06:361.STM32 中断系统回顾(Cortex-M) ...中断向量表偏移: ARM 处理器都是从地址 0X00000000 开始运行的,通过中断向量表偏移就可以将中断向量表存放到任意地址。 内嵌向量中断控制器(NVIC):Nested Vec1.STM32 中断系统回顾(Cortex-M)
以STM32为例介绍中断的一般概念:
- 中断向量表:中断向量表是一系列中断服务程序入口地址组成的表。
这些中断服务程序(函数)在中断向量表中的位置是由厂商定好的,当某个中断被触发以后就会自动跳转到中断向量表中对应的中断服务程序(函数)入口地址处。中断向量表在整个程序的最前面。 - 中断向量表偏移: ARM 处理器都是从地址 0X00000000 开始运行的,通过中断向量表偏移就可以将中断向量表存放到任意地址。
- 内嵌向量中断控制器(NVIC):Nested Vectored Interrupt Controller,中断系统管理机构。 Cortex-A 内核的中断管理机构不叫做NVIC,而是叫做 GIC, general interrupt controller。
- 中断使能:要使用某个外设的中断,肯定要先使能这个外设的中断。
- 中断服务函数:中断的目的就是为了执行中断服务函数,当中断发生以后中断服务函数就会被调用,期望中断处理的工作就可以放到中断服务函数中去完成。
2. Cortex-A7 中断系统简介
2.1 中断向量表
Cortex-A7 也有中断向量表,中断向量表也是在代码的最前面,如下。
- 对于 Cortex-M 内核来说,中断向量表列举出了一款芯片所有的中断向量,包括芯片外设的所有中断。而Cortex-A 内核 CPU 的所有外部中断都属于 IQR 中断,当任意一个外部中断发生的时候都会触发 IRQ 中断。任意一个外设中断发生的时候 IRQ 中断都会被触发,所以我们需要在 IRQ 中断服务函数中先判断究竟是哪个中断发生,再做出具体的处理。
- 当 GIC 接收到外部中断信号以后就会报给 ARM 内核,但是ARM 内核只提供了四个信号给 GIC 来汇报中断情况:VFIQ(虚拟快速 FIQ)、VIRQ(虚拟快速 IRQ)、FIQ(快速中断 IRQ)、IRQ(外部中断 IRQ)。
2.2 GIC(general interrupt controller)
左侧部分就是中断源,中间部分就是 GIC 控制器,最右侧就是中断控制器向处理器内核发送中断信息。GIC 将众多的中断源分为分为三类:- 1.SPI(Shared Peripheral Interrupt),共享中断,这些中断所有的 Core 都可以处理。外部中断都属于 SPI 中断。
- 2.PPI(Private Peripheral Interrupt),私有中断,独有的中断肯定是要指定的核心处理。
- 3.SGI(Software-generated Interrupt),软件中断,由软件触发引起的中断,系统会使用 SGI 中断来完成多核之间的通信。
GIC 逻辑分块,如上图所示: - Distributor(分发器端): 负责处理各个中断事件的分发,即中断事件应该发送到哪个 CPU Interface 。分发器收集所有的中断源,可以控制每个中断的优先级,它总是将优先级最高的中断事件发送到 CPU 接口端。
- CPU Interface(CPU 接口端): 每个 CPU Core 都可以在 GIC 中找到一个与之对应的 CPU Interface。 CPU 接口端就是分发器和 CPU Core 之间的桥梁。
2.3 中断ID
- 中断源有很多,为了区分这些不同的中断源肯定要给他们分配一个唯一 ID。
- 每一个 CPU 最多支持 1020 个中断 ID,这 1020 个 ID 包含 PPI(ID0~ID15);SPI (ID16~ID31)和 SGI(ID32~ID1019)。至于具体某个 ID 对应哪个中断那就由厂商根定义了。比如 I.MX6U 的总共使用了128 个SPI 中断 ID,加上前面属于 PPI 和 SGI 的 32 个 ID, I.MX6U 的中断源共有 128+32=160个。
2.4中断使能
- 中断使能包括两部分,一个是 IRQ 或者 FIQ 总中断使能,另一个就是 ID0~ID1019 这 1020个中断源的使能。
- 中断向量表:中断向量表是一系列中断服务程序入口地址组成的表。
-
ARM中断处理过程
2021-02-24 16:55:21本文主要以ARM体系结构下的中断处理为例,讲述整个中断处理过程中的硬件行为和软件动作。具体整个处理过程分成三个步骤来描述:1、第二章描述了中断处理的准备过程2、第三章描述了当发生中的时候,ARM硬件的行为3、... -
arm-linux内核中ARM中断实现详解
2018-10-22 14:05:10ARM--中断学习-讲的十分到位。值得一看,包括中断注册方法、中断处理过程等 -
嵌入式系统/ARM技术中的ARM中断及相关寄存器
2020-11-13 02:23:59ARM中断寄存器主要包括: ·中断模式寄存器可以设置2个中断源为IRQ或FIQ方式。 ·中断挂起寄存器,当有中断请求产生时,相应的位会被硬件置1,处于挂起状态。当进入中断处理程序时,必须通过软件清除这个... -
ARM中的中断向量表
2021-01-19 17:19:52在32位ARM系统中,一般都是在中断向量表中放置一条分支指令或PC寄存器加载指令,实现程序跳转到中 断服务例程的功能。例如: IRQEntry B HandleIRQ ;跳转范围较小 LDR PC,=HandleFIQ ... -
4. ARM中断处理实现
2021-11-15 17:21:52ARM中断处理实现1. 中断概念2. 中断流程图3. 中断控制器流程图4. 外部中断实现1. 汇编程序2. C语言程序3. 编译和运行 1. 中断概念 为什么要有中断?cpu和外设之间要进行通信,那么cpu怎么知道外设有数据来,有两种...ARM中断处理实现
1. 中断概念
为什么要有中断?cpu和外设之间要进行通信,那么cpu怎么知道外设有数据来,有两种方式:
2. 中断工作流程图
cpu处理步骤:
1.保存现场
2.向中断控制器查询是哪个中断
3.执行中断处理程序
4.恢复现场
GPIO控制器:
1.CON:功能配置寄存器
2.INTC:触发方式
3.PEND:中断记录标志位
4.MASK:开关3. 中断控制器工作流程图
以其中的一组中断控制为例:
每32个中断源为一组,fiq为快速中断,irq为普通中断,vic中有32个寄存器与中断源一一对应,存储的是中断函数的地址,address寄存器保存当前中断的中断函数地址,当enable打开时才会通知cpu有中断来临4. 外部中断驱动实现
4.1 汇编程序
start.s:
.global _start _start: b reset b undef b swi b abt_pre b abt_dat b reserved b irq b fiq reset: @重新映射异常向量表到0x40008000 ldr r0, =0x40008000 mcr p15, 0, r0, c12, c0, 0 @打开中断的总开关 mrs r0, cpsr bic r0, r0, #(0x1 << 7) msr cpsr, r0 bl main undef: swi: abt_pre: abt_dat: reserved: irq: ldr sp, =0x420000000 @初始化栈指针 stmfd sp!, {r0-r12,lr} bl irq_handler @调到中断函数 ldmfd sp!, {r0-r12,lr} subs pc, lr, #4 fiq:
4.2 C语言程序
main.c:
#define VICOINTSELECT (*(volatile unsigned int *)0xF200000C) #define VIC0VECTADDR (*(volatile unsigned int *)0xF2000100) #define VIC0INTENABLE (*(volatile unsigned int *)0xF2000010) #define VIC0ADDRESS (*(volatile unsigned int *)0xF2000F00) #define GPH0CON (*(volatile unsigned int *)0xE0200C00)) #define EXT_INT_0_CON (*(volatile unsigned int *)0xE0200E00) #define EXT_INT_0_MASK (*(volatile unsigned int *)0xE0200F00) #define EXT_INT_0_PEND (*(volatile unsigned int *)0xE0200F40) void key1_handler(void) { int (*printf)(char *format,...)=(void *)0x3ff13e54; printf("hello key1..\n"); //清理GPIO里面的中断记录 EXT_INT_0_PEND = 0x1; } int main() { //初始化中断控制器 VICOINTSELECT = 0; VIC0VECTADDR = (unsigned int)key1_handler; VIC0INTENABLE |= 0x1; //开启0号中断 //初始化按键,GPIO GPH0CON |=0xf;//设置成中断功能 EXT_INT_0_CON &=~0xf; EXT_INT_0_CON |=0x3; EXT_INT_0_MASK &=~0x1; while(1) { ; } return 0; } //中断处理函数 void irq_handler() { void(*handler)(); handler=(void *)VIC0ADDRESS ; handler(); //清理中断控制器 VIC0ADDRESS=0; }
4.3 编译和运行
PS:注意链接部分语句上机结果如下:
5. 优化中断程序
5.1 将所有中断的操作封装
irq.c:
#define VICOINTSELECT (*(volatile unsigned int *)0xF200000C) #define VIC1INTSELECT (*(volatile unsigned int *)0xF210000C) #define VIC2INTSELECT (*(volatile unsigned int *)0xF220000C) #define VIC3INTSELECT (*(volatile unsigned int *)0xF230000C) #define VIC0VECTADDR (volatile unsigned int *)0xF2000100 #define VIC1VECTADDR (volatile unsigned int *)0xF2100100 #define VIC2VECTADDR (volatile unsigned int *)0xF2200100 #define VIC3VECTADDR (volatile unsigned int *)0xF2300100 #define VIC0INTENABLE (*(volatile unsigned int *)0xF2000010) #define VIC1INTENABLE (*(volatile unsigned int *)0xF2100010) #define VIC2INTENABLE (*(volatile unsigned int *)0xF2200010) #define VIC3INTENABLE (*(volatile unsigned int *)0xF2300010) #define VIC0ADDRESS (*(volatile unsigned int *)0xF2000F00) #define VIC1ADDRESS (*(volatile unsigned int *)0xF2100F00) #define VIC2ADDRESS (*(volatile unsigned int *)0xF2200F00) #define VIC3ADDRESS (*(volatile unsigned int *)0xF2300F00) //中断控制器初始化函数 int request_irq(int irq, void(*handler)()) { if(irq>=0 && irq <= 31) { VICOINTSELECT = 0;//初始化中断控制器 VIC0VECTADDR[irq] = (unsigned int)handler; //注册中断函数 VIC0INTENABLE |= 0x1<<irq; //开启中断 } else if(irq>=32 && irq<=63) { irq-=32; VIC1INTSELECT = 0; VIC1VECTADDR[irq] = (unsigned int)handler; VIC1INTENABLE |= 0x1<<irq; //开启中断 } else if(irq>=64 && irq <=95) { irq-=64; VIC2INTSELECT = 0; VIC2VECTADDR[irq] = (unsigned int)handler; VIC2INTENABLE |= 0x1<<irq; //开启中断 } else if(irq>=96 && irq <=128) { irq-=96; VIC3INTSELECT = 0; VIC3VECTADDR[irq] = (unsigned int)handler; VIC3INTENABLE |= 0x1<<irq; //开启中断 } } //中断处理函数 void irq_handler() { void(*handler)(); //判断是那个中断发生 if(VIC0ADDRESS !=0 ) handler=(void *)VIC0ADDRESS; else if(VIC1ADDRESS !=0) handler=(void *)VIC1ADDRESS; else if(VIC2ADDRESS !=0) handler=(void *)VIC2ADDRESS; else if(VIC3ADDRESS !=0) handler=(void *)VIC3ADDRESS; //执行绑定的中断处理函数 handler(); //清理中断控制器 VIC0ADDRESS=0; VIC1ADDRESS=0; VIC2ADDRESS=0; VIC3ADDRESS=0; }
5.2 修改main
修改main.c:
#define GPH0CON (*(volatile unsigned int *)0xE0200C00)) #define EXT_INT_0_CON (*(volatile unsigned int *)0xE0200E00) #define EXT_INT_0_MASK (*(volatile unsigned int *)0xE0200F00) #define EXT_INT_0_PEND (*(volatile unsigned int *)0xE0200F40) void key1_handler(void) { int (*printf)(char *format,...)=(void *)0x3ff13e54; printf("hello key1..\n"); //清理GPIO里面的中断记录 EXT_INT_0_PEND = 0x1; } int main() { //初始化中断控制器 request_irq(0,key1_handler); //初始化按键,GPIO GPH0CON |=0xf;//设置成中断功能 EXT_INT_0_CON &=~0xf; EXT_INT_0_CON |=0x3; EXT_INT_0_MASK &=~0x1;//使能 while(1) { ; } return 0; }
5.3 编译和运行
6. WDT中断实现
看门狗定时器(WDT,Watch Dog Timer)是单片机的一个组成部分,它实际上是一个计数器,一般给看门狗一个数字,程序开始运行后看门狗开始计数。如果程序运行正常,过一段时间CPU应发出指令让看门狗置零,重新开始计数。如果看门狗增加到设定值就认为程序没有正常工作,强制整个系统复位。
6.1 WDT驱动实现
wdt.c
#define WTCON (*(volatile unsigned int *)0xE2700000)) #define WTDAT (*(volatile unsigned int *)0xE2700004)) #define WTCNT (*(volatile unsigned int *)0xE2700008)) #define WTCLRINT (*(volatile unsigned int *)0xE270000C)) void key1_handler(void) { int (*printf)(char *format,...)=(void *)0x3ff13e54; printf("hello wdt..\n"); //清理GPIO里面的中断记录 WTCLRINT = 1;//清理中断 } void wdt_init() { WTCON = (65<<8)|(0x1<<5)|(0x1<<3)|(0x1<<2)|0; //t=(32*(65+1))/ 66M = 32us WTCNT = 1000*1000/32;//1s WTDAT = 1000*1000/32; //首次喂狗 } int main() { //初始化看门狗 wdt_init(); //初始化中断控制器 request_irq(27,wdt_handler);//看门狗是27号中断 while(1) { ; } return 0; }
6.2 编译和运行
-
嵌入式系统/ARM技术中的ARM中断处理的安全性与高效性研究
2020-11-11 17:40:54摘要:重点分析了ARM处理器的多种中断处理,包括普通中断处理、任务切换中断处理、可重入中断处理和基于优先级的可重入性中断处理的上下文保存技术,并给出了程序予以实现。对普通的前后台系统和带OS的嵌入式系统都... -
ARM中断向量两种设置方法
2020-07-25 20:43:41在32位ARM系统中,一般都是在中断向量表中放置一条分支指令或PC寄存器加载指令,实现程序跳转到中断服务例程的功能。 -
ARM中断编程实验.docx编程资料
2022-04-10 10:10:24ARM中断编程实验.docx -
介绍ARM7内核的中断屏蔽方法
2020-08-14 05:13:12本文介绍一种arm7内核的中断屏蔽方法,并给出基于该方法的C语言源代码和汇编语言源代码。该段代码已经在笔者参与研制的火灾报警控制器中得到成功应用,可以完全替代x86体系下DOS.H中定义的库函数enable()和disable... -
6. ARM中断处理过程
2020-12-23 01:30:091 前言2 中断处理的准备过程2.1 中断模式的stack准备1 前言本文主要以ARM体系结构下的中断处理为例,讲述整个中断处理过程中的硬件行为和软件动作。具体整个处理过程分成三个步骤来描述:1、第二章描述了中断处理的...1 前言
2 中断处理的准备过程
2.1 中断模式的stack准备
1 前言
本文主要以ARM体系结构下的中断处理为例,讲述整个中断处理过程中的硬件行为和软件动作。具体整个处理过程分成三个步骤来描述:
1、第二章描述了中断处理的准备过程
2、第三章描述了当发生中的时候,ARM硬件的行为
3、第四章描述了ARM的中断进入过程
4、第五章描述了ARM的中断退出过程
本文涉及的代码来自3.14内核。另外,本文注意描述ARM指令集的内容,有些source code为了简短一些,删除了THUMB相关的代码,除此之外,有些debug相关的内容也会删除。
2 中断处理的准备过程
2.1 中断模式的stack准备
ARM处理器有多种processor mode,例如user mode(用户空间的AP所处于的模式)、supervisor mode(即SVC mode,大部分的内核态代码都处于这种mode)、IRQ mode(发生中断后,处理器会切入到该mode)等。对于linux kernel,其中断处理处理过程中,ARM 处理器大部分都是处于SVC mode。但是,实际上产生中断的时候,ARM处理器实际上是进入IRQ mode,因此在进入真正的IRQ异常处理之前会有一小段IRQ mode的操作,之后会进入SVC mode进行真正的IRQ异常处理。由于IRQ mode只是一个过渡,因此IRQ mode的栈很小,只有12个字节,具体如下:
[arch/arm/kernel/setup.c]
struct stack {
u32 irq[3];
u32 abt[3];
u32 und[3];
} ____cacheline_aligned;
static struct stack stacks[NR_CPUS];
除了irq mode,linux kernel在处理abt mode(当发生data abort exception或者prefetch abort exception的时候进入的模式)和und mode(处理器遇到一个未定义的指令的时候进入的异常模式)的时候也是采用了相同的策略。也就是经过一个简短的abt或者und mode之后,stack切换到svc mode的栈上,这个栈就是发生异常那个时间点current thread的内核栈。anyway,在irq mode和svc mode之间总是需要一个stack保存数据,这就是中断模式的stack,系统初始化的时候,cpu_init函数中会进行中断模式stack的设定:
void notrace cpu_init(void)
{
unsigned int cpu = smp_processor_id();------获取CPU ID
struct stack *stk = &stacks[cpu];---------获取该CPU对于的irq abt和und的stack指针
……
#ifdef CONFIG_THUMB2_KERNEL
#define PLC "r"------Thumb-2下,msr指令不允许使用立即数,只能使用寄存器。
#else
#define PLC "I"
#endif
__asm__ (
"msr cpsr_c, %1\n\t"------让CPU进入IRQ mode
"add r14, %0, %2\n\t"------r14寄存器保存stk->irq
"mov sp, r14\n\t"--------设定IRQ mode的stack为stk->irq
"msr cpsr_c, %3\n\t"
"add r14, %0, %4\n\t"
"mov sp, r14\n\t"--------设定abt mode的stack为stk->abt
"msr cpsr_c, %5\n\t"
"add r14, %0, %6\n\t"
"mov sp, r14\n\t"--------设定und mode的stack为stk->und
"msr cpsr_c, %7"--------回到SVC mode
:--------------------上面是code,下面的output部分是空的
: "r" (stk),----------------------对应上面代码中的%0
PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),------对应上面代码中的%1
"I" (offsetof(struct stack, irq[0])),------------对应上面代码中的%2
PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),------以此类推,下面不赘述
"I" (offsetof(struct stack, abt[0])),
PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
"I" (offsetof(struct stack, und[0])),
PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
: "r14");--------上面是input操作数列表,r14是要clobbered register列表
}
-
ARM中断编程实验.docx
2021-10-10 20:12:37ARM中断编程实验.docx -
ARM中断编程实验.pdf
2021-10-02 22:58:05ARM中断编程实验.pdf -
理解ARM中断原理以及中断嵌套
2017-10-14 11:50:16学习于韦东山 ARM有七种模式,我们这里值讨论SVC、IRQ和FIQ模式 ...① 我们假设ARM核心有两根中断引脚(实际上是看不见的),一根叫irq pin,一根叫fiq pin。在ARM的cpsr中,有一个I位和一个F位,分别用来禁止IR -
ARM中断学习_讲的十分到位
2014-05-12 16:54:05讲的挺好,分享下。对ARM是怎么样调用中断服务程序,把很多中断调用的中断地址给了很完善的讲解。 -
ARM中断处理之GIC
2020-06-29 15:39:08收藏一篇gic的文章 gic中断. 本章的主要内容如下: Ø 中断处理(interrupthandling)主要描述 n GIC如何识别中断 n 软件如何通过编程GIC来配置和控制中断 n GIC处理任意CPU interface中断的状态机 n CPU的异常模式... -
嵌入式系统/ARM技术中的linux-2.6.26内核中ARM中断实现详解(2)
2020-11-11 19:32:10作者:刘洪涛,华清远见嵌入式学院金牌讲师,ARM... 3.1 中断向量表 arch\arm\kernel\entry-armv.S __vectors_start: swi SYS_ERROR0 b vector_und + stubs_offset ldr pc, .LCvswi + stubs_offset -
内核ARM中断
2013-07-21 15:37:212.6内核ARM中断实现详解,详细解读实现原理,是学习的好资料 -
嵌入式系统/ARM技术中的linux-2.6.26内核中ARM中断实现详解(1)
2020-11-12 02:11:01作者:刘洪涛,华清远见嵌入式学院金牌讲师,ARM ATC授权培训讲师。 看了一些网络上关于linux中断实现的文章,感觉有一些写的非常好,在这里首先感谢他们的无私付出,然后也想再补充自己对一些问题的理解。先从... -
arm中断返回地址详细分析归类.pdf
2021-11-18 13:58:28arm中断返回地址详细分析归类.pdf -
嵌入式系统/ARM技术中的linux-2.6.26内核中ARM中断实现详解(3)
2020-11-11 13:22:12四、中断处理模型 要想弄清楚desc->handle_irq(irq, desc)和我们注册的中断有什么关联,就要了解中断处理模型了。 4.1 中断处理模型结构 中断处理模型如下图所示, 其中NR_IRQS表示最大的中断号,...