📌 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.