嵌入式-中断
中断是什么?
CPU在处理当前任务时,因为内部或外部事件的发生(中断源),暂停当前任务的执行(上下文切换保存执行状态),
转而执行与事件相关的程序(中断服务程序),处理完成后再放回原任务的过程(恢复执行状态)。
中断的种类?
1.同步中断:也即是我们通常所说的异常(),是在CPU执行特定指令时出现的非法情况,它的产生是由于前面的CPU操作引起的,是同步发生的;如除零异常;
2.异步中断:主要是由外部事件触发的,这就是我们常说的中断,它的发生不可预料的,是异步的;比如键盘中断;
3.软中断:在大多数硬件体系结构中,都提供软中断的功能,主要用于进入管理模式等的手段。如kill(pid, SIGUSR1)、raise()
4.自定义中断
中断是怎么发生的?
1.外部中断:外部中断通常用于处理外部引脚状态变化的事件,如按键触发;
2.定时器中断:定时器中断用于定时执行特定任务,例如定时采集传感器数据;
3.串口中断:串口中断用于处理串口接收和发送的异步事件。如程序错误引发的异常;
中断工作原理?以 ARM Cortex-M 为例
中断向量表
- 这是一个存储在内存中的表,它将每个中断号映射到对应的ISR地址。
- 当中断发生时,CPU会查询这个表,找到对应的服务例程并执行。
嵌套向量中断控制器(NVIC)
中断嵌套
sensor传感器中断完整流程
1.设备树注册中断;
点击查看代码
&i2c1 {
sensor@48 {
compatible = "mycompany,my-sensor";
reg = <0x48>;
interrupt-parent = <&gpio1>;
interrupts = <12 IRQ_TYPE_EDGE_RISING>; // GPIO1_12 上升沿触发
status = "okay";
};
};
驱动程序将从这里解析中断信息并注册;
2.驱动中中断注册流程
- 匹配 of_device_id,绑定 platform 驱动
点击查看代码
static const struct of_device_id sensor_dt_ids[] = {
{ .compatible = "mycompany,my-sensor" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sensor_dt_ids);
static struct i2c_driver my_sensor_driver = {
.probe = my_sensor_probe,
.remove = my_sensor_remove,
.driver = {
.name = "my_sensor",
.of_match_table = sensor_dt_ids,
},
};
module_i2c_driver(my_sensor_driver);
- 在 probe 中解析中断并注册中断处理函数
点击查看代码
static irqreturn_t sensor_irq_handler(int irq, void *dev_id)
{
struct my_sensor_data *data = dev_id;
// 简单处理:设置标志位或唤醒等待队列
data->irq_flag = true;
wake_up(&data->wait_queue);
return IRQ_HANDLED;
}
static int my_sensor_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct my_sensor_data *data;
int irq;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
i2c_set_clientdata(client, data);
// 解析中断号
irq = of_irq_get(client->dev.of_node, 0);
if (irq < 0)
return dev_err_probe(&client->dev, irq, "Failed to get IRQ\n");
data->irq = irq;
// 初始化等待队列(可选)
init_waitqueue_head(&data->wait_queue);
// 注册中断处理程序
return devm_request_threaded_irq(&client->dev,
irq,
NULL, // top-half (快速中断处理) 可设为 NULL
sensor_irq_handler, // bottom-half (可睡眠)
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"my_sensor_irq",
data);
}
4.中断处理函数响应
点击查看代码
static irqreturn_t sensor_irq_handler(int irq, void *dev_id)
{
struct my_sensor_data *data = dev_id;
// 常见操作:
// 1. 设置标志位
// 2. 唤醒等待队列
// 3. 调度工作队列或 tasklet 进一步处理
// 4. 读取 sensor 寄存器确认中断源
sensor_read_data(data); // 通常读取中断状态寄存器
return IRQ_HANDLED;
}
多数 sensor 在帧同步点(如帧尾或帧头)产生中断,用于通知驱动新帧就绪;
为什么需要中断?(原因分析)
-
实时性高:事件一发生就立刻响应
如:Sensor 数据采集完成、中断引脚拉高;CPU 马上响应 → 保证实时数据处理(如帧同步、运动检测) -
省资源、省功耗
不用轮询 GPIO 或 I2C:不再每几毫秒主动去检查一次状态;CPU 可空闲/休眠,直到被中断唤醒 → 适用于移动设备 -
减少 CPU 占用,提高系统效率
如果没有中断,只能不停轮询 sensor 状态;大量空转循环会占用 CPU、延迟其他任务 -
硬件必须:某些 sensor(如摄像头)必须基于帧中断(VSYNC)做控制
Camera sensor 帧同步信号用于驱动 frame buffer、ISP 等同步控制
中断调试中断常见问题
| 问题 | 原因 |
|---|---|
| 中断不触发 | 中断未使能 / 中断源未配置 、GPIO 配置错误;中断类型设置不正确;外设未连接或异常 |
| 中断触发但不进入 ISR | 中断优先级设置问题 / ISR 名错误 / ISR 没注册成功;probe() 中逻辑错误 |
| 中断反复触发不清除 | 中断标志位未清除 |
参考链接:
https://www.cnblogs.com/swk0918/category/1936804.html (宝藏博主-嵌入式100题合集)
https://www.cnblogs.com/swk0918/p/14453309.html
https://cloud.tencent.com/developer/article/2204914
https://developer.aliyun.com/article/1458003
http://www.weboch.com.cn/ARM/interrupt-mechanism.asp
https://zhuanlan.zhihu.com/p/664890195
浙公网安备 33010602011771号