/* * irq_chain_add — добавить обработчик кадрового прерывания в цепочку. * Возврат 0 / -1+errno: EINVAL (handler==NULL, или данные не в W2 — * из _irq_table_ref), ENOMEM (все IRQ_CHAIN_MAX слотов заняты). * * Первый слот захватывает IM2-таблицу (_irq_table_ref). Порядок вызова * хендлеров = порядок индексов; после remove/add взаимный порядок НЕ * гарантирован — хендлеры обязаны быть независимы (см. irq.h). */ #include #include "_irq.h" int irq_chain_add(isr_t handler) { if (!handler) { errno = EINVAL; return -1; } uint8_t i; for (i = 0; i < IRQ_CHAIN_MAX; i++) if (!_irq_chain[i]) break; if (i == IRQ_CHAIN_MAX) { errno = ENOMEM; return -1; } /* Первый обработчик — захватить таблицу и включить IM2. Делаем ДО * записи слота: при неудаче (EINVAL в small) состояние не тронуто. * Пока слот не выставлен, chain_n==0 → трамплин на кадре просто * чейнит к DSS. */ if (_irq_chain_n == 0) if (_irq_table_ref() != 0) return -1; IRQ_DISABLE(); _irq_chain[i] = handler; _irq_chain_n++; IRQ_ENABLE(); return 0; }