嵌入式学习笔记——ARM-中断与异常
文章目录
- 中断与异常的区别
- 中断与 DMA 的区别
- 中断能否睡眠?下半部能否睡眠?
- 1. 中断处理程序不能睡眠
- 2. 下半部(SoftIRQ、Tasklet、Workqueue)
- 中断处理注意点
- 1. 快进快出
- 2. 避免阻塞
- 3. 正确返回值
- 4. 如何处理大量任务
- 5. 避免竞态问题
- 6. 中断线程化
- 7. 清除中断标志
- 总结
- 中断 vs. 轮询:效率比较
- 应用场景
- 总结
- 为什么FIQ(Fast Interrupt Request)比 **IRQ(Interrupt Request)** 快
- 1. FIQ 具有更多的 Banked(专用)寄存器
- 为什么这会影响速度?
- 2. FIQ 拥有更高的优先级
- 3. FIQ 处理过程中屏蔽了其他中断
- 4. FIQ 的入口地址使得它可以直接执行
- 为什么这会影响速度?
- 总结
- 应用场景
中断与异常的区别
中断(Interrupt) 和 异常(Exception) 都会打断 CPU 的正常执行,但它们的来源和处理方式有所不同:
| 比较项 | 中断(Interrupt) | 异常(Exception) |
|---|---|---|
| 产生来源 | 外部设备(如键盘、网络、磁盘) | 内部软件或 CPU |
| 是否同步 | 异步(由外部事件触发,不一定与当前指令执行相关) | 同步(发生在指令执行过程中,与指令相关) |
| 处理方式 | 由中断控制器(如 PIC 或 APIC)通知 CPU,然后调用中断处理程序 | 由 CPU 自动触发异常处理程序 |
| 触发时机 | 可能发生在指令执行的任何时刻 | 只有在执行指令时才会触发 |
| 典型示例 | 时钟中断、键盘中断、网络中断 | 除零错误、非法指令、缺页异常 |
例如:
- 当你按下键盘时,会触发键盘中断,CPU 需要暂停当前执行的程序,调用键盘驱动处理输入。
- 当一个程序执行
div 0试图除以零时,CPU 会触发一个异常,让操作系统处理错误。
中断与 DMA 的区别
| 比较项 | DMA | 中断 |
|---|---|---|
| 主要作用 | 让外设直接与内存交换数据,而不经过 CPU | 让 CPU 处理突发事件 |
| 是否需要 CPU 参与 | 不需要,数据传输完全由 DMA 控制 | 需要,CPU 需要暂停当前任务并执行中断处理 |
| 速度 | 高(直接操作内存) | 可能较慢(需要 CPU 介入) |
| 典型示例 | 磁盘控制器通过 DMA 把数据传输到内存 | 网络设备收到数据后通知 CPU |
总结:
- DMA 主要用于数据传输,例如:磁盘或网卡使用 DMA 直接把数据写入内存,不需要 CPU 逐字节读取。
- 中断主要用于通知 CPU 发生了某些事件,如网络设备接收到新数据时,会触发中断,让 CPU 读取数据包。
中断能否睡眠?下半部能否睡眠?
1. 中断处理程序不能睡眠
- 原因:中断发生时,CPU 处于 中断上下文,没有具体的进程。如果在中断处理中调用了导致阻塞的函数(如
schedule()),则:- 进程调度系统不知道当前上下文对应哪个进程,无法正确恢复上下文。
- 可能会导致系统死锁或崩溃。
- 示例:
void irq_handler() {// 这会导致内核崩溃!schedule(); }
2. 下半部(SoftIRQ、Tasklet、Workqueue)
| 下半部类型 | 是否能睡眠 | 说明 |
|---|---|---|
| SoftIRQ | 否 | 仍然处于中断上下文,不允许睡眠 |
| Tasklet | 否 | 与 SoftIRQ 类似,仍不能睡眠 |
| Workqueue | 是 | 在内核线程中执行,可以睡眠 |
总结:
- 中断处理程序不能睡眠,否则会导致内核崩溃。
- SoftIRQ 和 Tasklet 不能睡眠,因为它们仍然运行在中断上下文中。
- Workqueue 可以睡眠,因为它们在一个独立的内核线程中运行。
中断处理注意点
在写中断服务程序(ISR,Interrupt Service Routine)时,需要注意以下关键点:
1. 快进快出
- 快速完成关键任务:ISR应该只做必要的工作,比如读取硬件寄存器、清除中断标志、存储关键数据等。
- 将复杂任务移至下半部:可以使用 工作队列(workqueue) 或 tasklet 来处理较复杂的任务,而ISR只执行简单、时间敏感的操作。
2. 避免阻塞
- 中断期间CPU不会进行进程切换,因此ISR 不能 执行 sleep、等待锁、I/O 操作 等可能导致阻塞的操作。
- 例如,在ISR中调用
mutex_lock()是错误的,因为它可能导致死锁。 - 如果必须同步资源,可以使用 自旋锁(spinlock),但要小心避免死锁。
3. 正确返回值
- 在Linux中,ISR必须返回 IRQ_HANDLED 或 IRQ_NONE(位于
<linux/irqreturn.h>)。 - 返回 IRQ_HANDLED 表示该中断已被正确处理,而 IRQ_NONE 则表示该中断不属于当前设备,可能需要进一步排查。
4. 如何处理大量任务
- 使用中断下半部机制(Deferred Processing):
- 软中断(SoftIRQ):适用于高吞吐量需求,如网络数据包处理。
- Tasklet:适用于优先级较高但不需要高吞吐量的任务,如调度一些紧急的任务处理。
- 工作队列(workqueue):适用于可以被内核线程调度的任务,适合耗时较长的任务处理。
- 示例代码(使用 Tasklet):
#include <linux/interrupt.h>void my_tasklet_func(unsigned long data); DECLARE_TASKLET(my_tasklet, my_tasklet_func, 0);irqreturn_t my_irq_handler(int irq, void *dev_id) {// 仅做必要的中断处理printk(KERN_INFO "Interrupt occurred\n");// 调度 tasklet 进行后续处理tasklet_schedule(&my_tasklet);return IRQ_HANDLED; }void my_tasklet_func(unsigned long data) {// 在下半部处理较复杂的任务printk(KERN_INFO "Tasklet executed\n"); }static int __init my_module_init(void) {int irq = 19; // 假设是 IRQ19request_irq(irq, my_irq_handler, IRQF_SHARED, "my_irq_device", NULL);return 0; }static void __exit my_module_exit(void) {free_irq(19, NULL);tasklet_kill(&my_tasklet); }module_init(my_module_init); module_exit(my_module_exit);
5. 避免竞态问题
- 使用自旋锁保护共享资源:
static spinlock_t my_lock;irqreturn_t my_irq_handler(int irq, void *dev_id) {unsigned long flags;spin_lock_irqsave(&my_lock, flags); // 关闭本地中断,并上锁// 访问共享资源spin_unlock_irqrestore(&my_lock, flags); // 解锁,并恢复中断return IRQ_HANDLED; }
6. 中断线程化
- 对于较复杂的任务,可以将中断处理线程化(使用
request_threaded_irq())。 - 线程化的中断 允许进程调度,但会有一定的时延:
irqreturn_t my_irq_handler(int irq, void *dev_id) {return IRQ_WAKE_THREAD; // 让内核调度中断线程执行后续操作 }irqreturn_t my_irq_thread_fn(int irq, void *dev_id) {// 处理较复杂的任务printk(KERN_INFO "Threaded IRQ handling\n");return IRQ_HANDLED; }request_threaded_irq(irq, my_irq_handler, my_irq_thread_fn, IRQF_SHARED, "my_irq_device", NULL);
7. 清除中断标志
- 在某些设备中,如果不清除 中断标志位,中断可能会持续触发,导致系统卡死:
irqreturn_t my_irq_handler(int irq, void *dev_id) {iowrite32(0, INTERRUPT_STATUS_REGISTER); // 清除中断标志return IRQ_HANDLED; }
总结
- 上半部(ISR)做 最少的事情,如读取数据、清除中断标志,然后 尽快退出。
- 下半部 通过 tasklet、工作队列 或 软中断 处理复杂任务。
- 避免阻塞,不要在ISR中调用
sleep()或等待资源。 - 保护共享资源,使用 自旋锁(在中断上下文)。
- 中断线程化 适用于较复杂的任务,但可能会有一定延迟。
中断 vs. 轮询:效率比较
| 方式 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| 中断(Interrupt) | 低频请求设备(如键盘、鼠标、串口、传感器) | - CPU 不需要主动查询,减少不必要的 CPU 开销 - 适合低频请求设备 | - 需要中断上下文处理,可能引入额外的调度开销 - 可能会影响实时性(高优先级任务打断低优先级任务) |
| 轮询(Polling) | 高频率、高吞吐设备(如高速网卡、DMA 设备、实时音视频处理) | - 对于高频设备,可以减少中断开销,提高吞吐量 - 控制简单,不涉及中断处理 | - 占用 CPU 资源,可能导致其他任务无法执行 - 低效,尤其是在设备空闲时,CPU 仍然需要不断查询 |
应用场景
-
设备请求频率低 → 中断
- 适用于 低速设备,如键盘、鼠标、传感器、串口等。
- CPU 只有在 设备有数据 时才会被打断,中断处理时间短。
- 避免 CPU 不断轮询浪费资源。
-
设备请求频率高 → 轮询
- 适用于 高速数据传输设备,如 网络设备、硬盘控制器、音视频处理 等。
- 轮询可以减少中断频繁触发的开销,提高数据吞吐能力。
- 例如,Linux 内核中的 NAPI(New API)网络处理模式就是 轮询 + 中断混合 方案。
-
折中方案:中断 + 轮询
- 许多高性能设备(如网卡、存储设备)使用 中断触发 + 轮询 结合的方式:
- 初始阶段:中断触发 → 当有新数据时,触发中断通知 CPU。
- 高负载阶段:轮询处理 → 在一段时间内,CPU 进入轮询模式,提高数据处理效率。
- 示例:Linux NAPI 模式(用于网络驱动)
- 初始时 使用中断 监听网络数据包。
- 如果数据包流量很大,则改为 轮询模式,避免频繁触发中断。
- 数据处理完毕后,系统重新 切换回中断模式。
- 许多高性能设备(如网卡、存储设备)使用 中断触发 + 轮询 结合的方式:
总结
- 低频设备(键盘、鼠标、传感器) → 中断
- 高吞吐设备(网卡、存储、视频流) → 轮询
- 高负载设备(混合场景) → 中断 + 轮询(NAPI、Hybrid Polling)
为什么FIQ(Fast Interrupt Request)比 IRQ(Interrupt Request) 快
1. FIQ 具有更多的 Banked(专用)寄存器
- FIQ 模式 在 ARM 体系结构 下有 更多的专用寄存器:
- FIQ 模式 拥有 R8-R14 的专用 Banked 寄存器,同时还有 SPSR(Saved Program Status Register)。
- IRQ 模式 只有 R13(SP)、R14(LR)、SPSR 是 Banked 寄存器,而 R8-R12 需要手动保存。
为什么这会影响速度?
- 在 IRQ 处理程序 中,由于 R8-R12 没有 Banked 版本,所以在进入中断时,必须 手动保存这些寄存器,然后在中断退出时 恢复这些寄存器,这会增加 入栈和出栈的开销。
- FIQ 由于有专门的寄存器,在 模式切换时 CPU 自动保存/恢复,无需手动压栈/出栈,从而 减少了指令开销,提高了执行速度。
2. FIQ 拥有更高的优先级
- 在 ARM 处理器中,FIQ 优先级高于 IRQ:
- 如果 FIQ 和 IRQ 同时发生,CPU 会先响应 FIQ,然后再处理 IRQ。
- 如果正在处理 IRQ 时 FIQ 触发,那么 FIQ 会抢占 IRQ 立即执行,这保证了 FIQ 的 实时性 和 低延迟。
3. FIQ 处理过程中屏蔽了其他中断
-
当 CPU 进入 FIQ 模式 时:
- 所有 IRQ 中断被屏蔽(禁用)。
- 其他异常(如未定义指令异常、软件中断异常)也被屏蔽。
- 这意味着 FIQ 不会被其他中断或异常打断,能够在 更短的时间内完成处理。
-
反之,在 IRQ 模式 下:
- FIQ 仍然可以打断 IRQ,导致 IRQ 可能会被抢占,增加了中断处理的复杂度和上下文切换的时间。
4. FIQ 的入口地址使得它可以直接执行
- ARM 处理器的中断向量表地址:
- IRQ 入口地址:
0x18 - FIQ 入口地址:
0x1C
- IRQ 入口地址:
为什么这会影响速度?
-
IRQ 入口
0x18只能放一条指令,通常是B(Branch)指令,即 必须跳转到中断处理程序:0x18: B IRQ_Handler- 由于 需要跳转,这 增加了一条额外的跳转指令,影响了中断的响应时间。
-
FIQ 入口
0x1C之后没有其他中断向量表,可以 直接放入 FIQ 处理代码:0x1C: STMFD SP!, {R0-R4} ; 直接保存寄存器LDR R0, =DATA ; 读取数据STR R0, [R1] ; 处理数据LDMFD SP!, {R0-R4} ; 恢复寄存器- 这样 FIQ 处理程序可以直接在
0x1C处执行,避免跳转,从而 进一步减少指令执行时间,提高中断响应速度。
- 这样 FIQ 处理程序可以直接在
总结
| 对比项 | FIQ(Fast Interrupt) | IRQ(Interrupt Request) |
|---|---|---|
| 专用寄存器 | R8-R14 + SPSR(Banked 寄存器,不需要手动保存) | 只有 R13(SP)、R14(LR)、SPSR(R8-R12 需要手动保存) |
| 中断优先级 | FIQ 最高优先级,可以打断 IRQ | IRQ 低于 FIQ,可能被 FIQ 抢占 |
| 中断屏蔽 | 进入 FIQ 后,所有 IRQ 被屏蔽,不受其他中断影响 | 进入 IRQ 后,FIQ 仍然可以抢占 |
| 入口地址 | 0x1C,可以直接执行,无需跳转 | 0x18 只能放一条指令,需要跳转 |
| 执行速度 | 更快,适用于高优先级、低延迟任务 | 较慢,适用于一般设备 |
应用场景
-
FIQ 适用于:
- 高实时性场景(如 DMA 传输完成中断)
- 数据流处理(如高速 音频/视频数据 处理)
- 低延迟任务(如紧急错误处理)
-
IRQ 适用于:
- 普通设备中断(如键盘、鼠标、串口)
- 网络中断(如果流量不大)
相关文章:
嵌入式学习笔记——ARM-中断与异常
文章目录 中断与异常的区别中断与 DMA 的区别中断能否睡眠?下半部能否睡眠?1. 中断处理程序不能睡眠2. 下半部(SoftIRQ、Tasklet、Workqueue) 中断处理注意点1. 快进快出2. 避免阻塞3. 正确返回值4. 如何处理大量任务5. 避免竞态问…...
Everything 安装教程与使用教程(附安装包)
文章目录 前言一、Everything 介绍二、Everything 安装教程1.Everything 安装包下载2.选择安装文件3.选择安装语言4.接受许可协议5.选择安装位置6.配置安装选项7.完成安装 三、Everything 使用教程1.启动软件2.简单关键词搜索3.按类型搜索 前言 在日常使用电脑时,随…...
嵌入式开发中栈溢出的处理方法
嵌入式开发中栈溢出的处理方法 目录 引言栈溢出的原理栈溢出的危害栈溢出检测方法 哨兵变量法栈着色法硬件监测机制编译器栈保护 裸机系统中的栈溢出处理操作系统中的栈溢出处理预防栈溢出的最佳实践结论 引言 在嵌入式系统开发中,栈溢出是一个常见且危险的问题…...
SQL语句(三)—— DQL
目录 基本语法 一、基础查询 1、查询多个字段 2、字段设置别名 3、去除重复记录 4、示例代码 二、条件查询 1、语法 2、条件列表常用的运算符 3、示例代码 三、分组查询 (一)聚合函数 1、介绍 2、常见的聚合函数 3、语法 4、示例代码 &…...
#python项目生成exe相关了解
在 Windows 上将 Python 项目 生成 EXE 可执行文件,主要使用 pyinstaller。以下是完整步骤: 📌 1. 安装 PyInstaller pip install pyinstaller如果已安装,可执行以下命令检查版本: pyinstaller --versionὌ…...
Opencv计算机视觉编程攻略-第九节 描述和匹配兴趣点
一般而言,如果一个物体在一幅图像中被检测到关键点,那么同一个物体在其他图像中也会检测到同一个关键点。图像匹配是关键点的常用功能之一,它的作用包括关联同一场景的两幅图像、检测图像中事物的发生地点等等。 1.局部模板匹配 凭单个像素就…...
JSON-lib考古现场:在2025年打开赛博古董店的奇妙冒险
各位在代码海洋里捡贝壳的探险家们!今天我们要打开一个尘封的Java古董箱——JSON-lib!这货可是2003年的老宝贝,比在座很多程序员的工龄还大!准备好穿越回Web 1.0时代,感受XML统治时期的余晖了吗? …...
Android: Handler 的用法详解
Android 中 Handler 的用法详解 Handler 是 Android 中用于线程间通信的重要机制,主要用于在不同线程之间发送和处理消息。以下是 Handler 的全面用法指南: 一、Handler 的基本原理 Handler 基于消息队列(MessageQueue)和循环器(Looper)工作,…...
汇编学习之《push , pop指令》
学习本章前线了解ESP, EBP 指令 汇编学习之《指针寄存器&大小端学习》-CSDN博客 栈的特点: 好比一个垂直容器,可以陆续放入物体,但是先放的物体通常会被后面放的物体压着,只有等上面后放的物品拿出来后,才能…...
Python循环控制语句
1. 循环类型概述 Python提供两种主要的循环结构: while循环 - 在条件为真时重复执行for循环 - 遍历序列中的元素 2. while循环 基本语法 while 条件表达式:循环体代码示例 count 0 while count < 5:print(f"这是第{count1}次循环")count 13. f…...
微信小程序(下)
目录 在事件处理函数中为 data 中的数据赋值 事件传参 bindinput 的语法格式 实现文本框和 data 之间的数据同步 条件渲染 结合 使用 wx:if hidden wx:if与 hidden 的对比 wx:for 手动指定索引和当前项的变量名 wx:key 的使用 WXSS 和 CSS 的关系 什么是 rpx 尺寸…...
【零基础入门unity游戏开发——2D篇】2D 游戏场景地形编辑器——TileMap的使用介绍
考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、…...
vector的介绍与代码演示
由于以后我们写OJ题时会经常使用到vector,所以我们必不可缺的是熟悉它的各个接口。来为我们未来作铺垫。 首先,我们了解一下: https://cplusplus.com/reference/vector/ vector的概念: 1. vector是表示可变大小数组的序列容器…...
ubuntu 22.04 解决LXC 报错CGroupV1 host system
解决CGroupV1 host system 报错 echo "cgroupv1 environment" sed -i s/^GRUB_CMDLINE_LINUX.*/GRUB_CMDLINE_LINUX_DEFAULT"quiet splash systemd.unified_cgroup_hierarchy0" / /etc/default/grub update-grub reboot 下载oracle 7 Linux 容器测试 l…...
JavaEE初阶复习(JVM篇)
JVM Java虚拟机 jdk java开发工具包 jre java运行时环境 jvm java虚拟机(解释执行 java 字节码) java作为一个半解释,半编译的语言,可以做到跨平台. java 通过javac把.java文件>.class文件(字节码文件) 字节码文件, 包含的就是java字节码, jvm把字节码进行翻译转化为…...
MINIQMT学习课程Day9
获取qmt账号的持仓情况后,我们进入下一步,如何获得当前账号的委托状况 还是之前的步骤,打开qmt,选择独立交易, 之后使用pycharm,编写py文件 导入包: from xtquant import xtdata from xtqua…...
动态规划似包非包系列一>组合总和IIV
目录 题目分析:状态表示:状态转移方程:初始化填表顺序返回值:代码呈现: 题目分析: 状态表示: 状态转移方程: 初始化填表顺序返回值: 代码呈现: class Soluti…...
Java 二叉树非递归遍历核心实现
非递归遍历的核心是用栈模拟递归的调用过程,通过手动维护栈来替代系统栈,实现前序、中序和后序遍历。以下是三种遍历的代码实现与关键逻辑分析: 一、二叉树遍历 1.1、前序遍历(根 → 左 → 右) 核心逻辑:…...
JavaScript性能优化实践:从微观加速到系统级策略
JavaScript性能优化实践:从微观加速到系统级策略 引言:性能优化的"时空折叠"思维 在JavaScript的世界里,性能优化如同在时间与空间的维度中折叠代码。本文将通过"时空折叠"的隐喻,从代码执行效率(时间维度)和内存占用(空间维度)两大核心,结合现代…...
《P1029 [NOIP 2001 普及组] 最大公约数和最小公倍数问题》
题目描述 输入两个正整数 x0,y0,求出满足下列条件的 P,Q 的个数: P,Q 是正整数。 要求 P,Q 以 x0 为最大公约数,以 y0 为最小公倍数。 试求:满足条件的所有可能的 P,Q 的个数。 输入格式 一行两个正整数 x0,y0。…...
【力扣hot100题】(052)课程表
什么人一学期要上2000节课啊jpg 看了非常久都没思路,主要是数据结构还没复习到图论,根本没思路怎么储存一个图…… 唯一记得的就是两种存储方法,一种是二维数组法,记录每一条边的有无,一种是只记录有的边,…...
SpringBoot配置文件多环境开发
目录 一、设置临时属性的几种方法 1.启动jar包时,设置临时属性 2.idea配置临时属性 3.启动类中创建数组指定临时属性 二、多环境开发 1.包含模式 2.分组模式 三、配置文件的优先级 1.bootstrap 文件优先: 2.特定配置文件优先 3.文件夹位置优…...
RSA和ECC在密钥长度相同的情况下哪个更安全?
现在常见的SSL证书,如:iTrustSSL都支持RSA和ECC的加密算法,正常情况下RAS和ECC算法该如何选择呢?实际上在密钥长度相同的情况下,ECC(椭圆曲线密码学)通常比RSA(Rivest-Shamir-Adle…...
Dive into Deep Learning - 2.4. Calculus (微积分)
Dive into Deep Learning - 2.4. Calculus {微积分} 1. Derivatives and Differentiation (导数和微分)1.1. Visualization Utilities 2. Chain Rule (链式法则)3. DiscussionReferences 2.4. Calculus https://d2l.ai/chapter_preliminaries/calculus.html For a long time, …...
【备考高项】附录:合同法全文(428条全)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 第一章 一般规定第二章 合同的订立第三章 合同的效力第四章 合同的履行第五章 合同的变更和转让第六章 合同的权利义务终止第七章 违约责任第八章 其他规定第九章 买卖合同第十章 供用电、水、气、热力合同第十…...
Ubuntu安装Podman教程
1、先修改apt源为阿里源加速 备份原文件: sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup 修改源配置: vim sources.list删除里面全部内容后,粘贴阿里源: deb http://mirrors.aliyun.com/ubuntu/ focal main re…...
9.进程信号
信号量 信号量是什么? 本质是一个计数器,通常用来表示公共资源中,资源数量多少的问题。 公共资源:可以被多个进程同时访问的资源。 访问没有保护的公共资源会导致数据不一致问题 什么是数据不一致问题 由于公共资源…...
python爬虫:小程序逆向(需要的工具前期准备)
前置知识点 1. wxapkg文件 如何查看小程序包文件 打开wechat的设置: .wxapkg概述 .wxapkg是小程序的包文件格式,且其具有独特的结构和加密方式。它不仅包含了小程序的源代码,还包括了图像和其他资源文件,这些内容在普通的文件…...
PGSQL 对象创建函数生成工具
文章目录 代码结果 代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>PGSQL 函数生成器</tit…...
查询当前用户的购物车和清空购物车
业务需求: 在小程序用户端购物车页面能查到当前用户的所有菜品或者套餐 代码实现 controller层 GetMapping("/list")public Result<List<ShoppingCart>> list(){List<ShoppingCart> list shoppingCartService.shopShoppingCart();r…...
