📌 IRQ
IRQ (Interrupt Request, запрос прерывания) — аппаратный или программный механизм, с помощью которого периферийные устройства, компоненты системы или само ядро могут временно приостанавливать основное выполнение программы (CPU) для немедленной обработки критического события. IRQ — фундаментальная основа реакции в реальном времени: обмен данными, таймеры, I/O, обработка ошибок, синхронизация.
🧠 Как работает
Основная логика
- Аппаратный сигнал: периферийное устройство (например, UART, Timer, GPIO, Network, DMA) формирует сигнал на одной из линий IRQ.
- Контроллер прерываний (PIC, APIC, GIC): определяет, какое устройство требует внимания, приоритет IRQ, маскирование и маршрутизацию сигнала к CPU.
- CPU: при поступлении IRQ приостанавливает основную программу (генерируется Trap), сохраняет контекст, переходит на обработчик (ISR, Interrupt Service Routine), выполняет обслуживание, возвращается к основной задаче.
Классификация IRQ
- Маскируемые (Maskable): могут быть временно отключены (маскированы), основной поток не реагирует.
- Немаскируемые (NMI): имеют высший приоритет, не могут быть отключены (обычно — ошибки питания, критические сбои).
- Программные IRQ (Software Interrupt): генерируются программно (инструкции
int
,svc
,ecall
). - Векторные IRQ: адрес ISR определяется номером/вектором IRQ.
Типовой поток обработки
- Событие на периферии → генерируется IRQ (например, приход байта на UART).
- Контроллер IRQ формирует запрос, присваивает приоритет, посылает сигнал на CPU.
- CPU прерывает текущий код, сохраняет регистры/PC, переходит на адрес ISR.
- ISR обслуживает событие (считывает данные, сбрасывает флаг, очищает IRQ).
- Возврат из ISR — восстановление контекста, продолжение основной задачи.
Иллюстрация:
flowchart TB Device["Периферия (UART, Timer, ... )"] IRQLine["IRQ Line"] PIC["Interrupt Controller"] CPU["CPU"] ISR["Interrupt Service Routine"] App["Main Program"] Device --> IRQLine IRQLine --> PIC PIC --> CPU CPU --> ISR ISR --> CPU CPU --> App
⚙️ Где применяется
-
Микроконтроллеры, SoC, CPU: обслуживание периферии (UART, SPI, ADC, Timer, Ethernet, GPIO).
-
ОС и RTOS: планирование, сервис таймеров, контекстное переключение, сетевые стеки, прерывания от устройств.
-
Системы реального времени: жёсткие требования к латентности обработки событий.
-
Встроенные системы, автоматизация, промышленность, IoT: обработка сигналов, аварий, датчиков.
-
Компьютеры и серверы: управление устройствами ввода/вывода, обработка ошибок, watchdog.
✅ Преимущества
-
Мгновенная реакция: минимальное время между событием и обработкой.
-
Освобождение CPU: выполнение основной программы не блокируется ожиданием (polling).
-
Масштабируемость: поддержка сотен/тысяч IRQ с разными приоритетами.
-
Гибкость: программное и аппаратное управление, маскирование, вложенность.
-
Энергосбережение: CPU может находиться в режиме сна до прихода IRQ.
❌ Недостатки
-
Сложность отладки: ошибки в ISR, гонки, неочищенные IRQ приводят к “зависаниям”.
-
Jitter и латентность: возможны задержки при высоких нагрузках, блокировках.
-
Проблемы приоритетов: низкоприоритетные IRQ могут “голодать” (starvation).
-
Оверхед: каждый вход/выход из ISR — сохранение/восстановление контекста, сброс кешей.
-
Зависимость от контроллера: особенности работы PIC, APIC, GIC различаются, влияет на портируемость.
🔗 Связанные технологии
CPU, PIC, APIC, GIC, ISR, Trap, NMI, DMA, Timer, GPIO, UART, SPI, RTOS, MCU, SoC
Резюме
IRQ — ключевой механизм для обслуживания событий и асинхронного обмена в цифровых системах. Он обеспечивает минимальное время реакции, повышает эффективность, критичен для управления периферией, realtime-задач и энергосберегающих сценариев. Однако требует продуманной архитектуры и аккуратной реализации ISR для избежания зависаний и ошибок.
Примеры кода
C (baremetal): обработка IRQ на Cortex-M
volatile int irq_counter = 0;
void UART0_IRQHandler(void) {
// Считываем байт из UART, очищаем флаг прерывания
char c = UART0->DR;
irq_counter++;
}
int main() {
NVIC_EnableIRQ(UART0_IRQn);
while (1) {
// основной цикл
}
}
Ассемблер x86: программный вызов и возврат из прерывания
int_handler:
pusha ; Сохраняем все регистры
; ... обработка прерывания ...
popa ; Восстановление регистров
iret ; Возврат из IRQ
; ... где-то в коде ...
int 0x21 ; Генерируем программное прерывание
Linux: регистрация обработчика IRQ
#include <linux/interrupt.h>
irqreturn_t my_irq_handler(int irq, void *dev_id) {
// обработка события
return IRQ_HANDLED;
}
static int __init my_driver_init(void) {
request_irq(IRQ_NUM, my_irq_handler, 0, "my_irq", NULL);
return 0;
}
Источники: Intel® SDM, ARM Cortex-M TRM, osdev.org, habr.com, Linux kernel docs, FreeRTOS docs, микроконтроллеры STM32/NXP/TI, Wikipedia.