中断与 DMA:硬件怎么通知 CPU、DMA 为什么能省 CPU
更新时间:2026-09-05。本文是「集成电路大类 · 芯片设计」**入门层(beginner)**第三十五篇新正文。寄存器表 说软件靠读写寄存器控制硬件,但 CPU 怎么知道「外设已经收完一个字节」?搬一大块数据时 CPU 要不要亲自一个个字节地搬?这就引出两个关键机制:中断(硬件主动通知 CPU)和 DMA(硬件自己搬数据)。
本文要回答的问题
- CPU 怎么知道外设「有事了」?轮询和中断差在哪?
- 几十个外设都要通知 CPU,中断怎么管理?
- DMA 是什么,为什么它搬数据能让 CPU 几乎不参与?
- 中断、DMA、寄存器、总线怎么配合完成一次数据传输?
一、中断:让硬件「主动敲门」
外设动作慢(UART 收一个字节、网卡来一个包),CPU 如果一直轮询(polling)——反复读状态寄存器问「好了没?好了没?」——会把时间全浪费在干等上。中断(interrupt)反过来:外设完成(或出错)时,通过一根中断线主动发信号,CPU 收到后**暂停当前程序、跳到中断服务程序(ISR)**处理,处理完再回到被打断的地方继续。
- 相关寄存器:中断使能(要不要报)、中断状态(谁报了,常 W1C 清除,见 寄存器位域属性);
- 中断控制器(如 ARM 的 GIC、RISC-V 的 PLIC):把几十个外设的中断汇聚、排优先级、转发给 CPU,支持屏蔽和嵌套;
- 代价是中断延迟和现场保存/恢复开销,所以极高频率的事件不适合全靠中断。
二、DMA:数据自己搬,不用 CPU 当搬运工
没有 DMA 时,外设来一个字节 CPU 就得读一次、再写进内存——搬 1 MB 数据要 CPU 参与上百万次,什么别的都干不了。DMA(Direct Memory Access,直接存储器访问)让一个专门的 DMA 引擎作为总线主设备(master),直接在外设和内存之间(或内存到内存)批量搬数据,数据不再经过 CPU:
- CPU 只需设置源地址、目的地址、传输长度并启动,然后去干别的;
- 搬完后 DMA 发一个完成中断通知 CPU(见 片上总线上的 master、仲裁器决定谁用总线);
- DMA 内部靠 valid/ready 握手 + FIFO 缓冲突发、跨时钟域;高级 DMA 支持 scatter-gather(链表式分散/聚集传输)。
三、一次完整传输怎么配合
以「网卡收一个包到内存」为例:网卡收到数据 → DMA 引擎把数据逐拍直接写进内存环形缓冲(靠握手和 FIFO 匹配速率)→ 一帧收完,网卡/DMA 置中断状态位、经中断控制器通知 CPU → CPU 进 ISR,读状态确认、W1C 清中断标志、把数据包交给协议栈处理。寄存器负责配置和状态、DMA 负责搬数据、中断负责通知,三者分工让 CPU 从「逐字节搬运+反复查询」中解放出来。
四、这一篇在知识体系里的位置
- 想看中断使能/状态/W1C 位的寄存器机制 → 寄存器表与地址解码;
- 想看 DMA 作为 master 怎么用总线、仲裁 → 片上总线 AMBA 入门、FIFO/仲裁器/握手;
- 想看手册里怎么描述中断/DMA → 怎么读芯片手册;
- 想在架构里规划数据流和中断 → 从需求 spec 到架构。
总结
一句话总结:中断和 DMA 是让 CPU 高效与外设协作的两个机制——中断解决「CPU 怎么知道外设有事」:外设完成或出错时通过中断线主动发信号,中断控制器(GIC/PLIC)把几十个中断源汇聚、排优先级后通知 CPU,CPU 暂停当前任务执行中断服务程序 ISR、处理后返回,配合中断使能位和 W1C 中断状态位,从而避免 CPU 反复轮询状态寄存器干等浪费(代价是中断延迟与现场开销);DMA 解决「大块数据谁来搬」:DMA 引擎作为总线主设备,在外设和内存之间直接批量传输、数据不经过 CPU,CPU 只需配置源/目的地址和长度并启动即可去做别的,搬完再由 DMA 发完成中断通知;其内部用 valid/ready 握手和 FIFO 缓冲突发与跨时钟域、由总线仲裁器与 CPU 共享带宽,高级 DMA 还支持 scatter-gather;一次典型收包就是「DMA 直写内存→置中断状态→中断控制器通知 CPU→ISR 读状态、W1C 清标志、处理数据」,寄存器管配置状态、DMA 管搬运、中断管通知,三者把 CPU 从逐字节搬运和反复查询中彻底解放。