Как избежать гонки общих IRQ в Linux

Я рассматриваю предстоящую ситуацию во встроенном проекте Linux (пока нет оборудования), когда два внешних чипа должны будут совместно использовать одну физическую линию IRQ. Эта линия способна аппаратно запускать фронты, но не прерывания, запускаемые по уровню.

Глядя на общую поддержку irq в Linux, я понимаю, что способ, которым это будет работать с двумя отдельными драйверами, заключается в том, что каждый из них будет вызывать свой обработчик прерываний, проверять свое оборудование и обрабатывать его, если это необходимо.

Однако я представляю себе следующее состояние гонки и хотел бы знать, упускаю ли я что-то или что можно сделать, чтобы обойти это. Допустим, есть два внешних источника прерываний, устройства A и B:

  1. происходит прерывание устройства B, IRQ становится активным
  2. Край IRQ вызывает запуск обработчика прерывания ядра Linux
  3. ISR для устройства A работает, не находит ожидающих прерываний
  4. устройство Произошло прерывание, IRQ остается активным (провод-ИЛИ)
  5. ISR для устройства B запускается, находит ожидающее прерывание, обрабатывает и очищает его
  6. основной обработчик прерывания завершает работу
  7. IRQ остается активным, фронты больше не генерируются, IRQ заблокировано

Похоже, чтобы это было исправлено, основной обработчик прерывания должен был бы проверить уровень IRQ после запуска всех обработчиков, и, если он все еще активен, запустить их снова. Будет ли Linux это делать? Я не думаю, что ядро ​​прерывания знает, как проверить уровень линии IRQ.

Может ли эта гонка произойти на самом деле, и если да, то как мне с этим справиться?


person blueshift    schedule 11.01.2012    source источник


Ответы (1)


По сути, с описанным вами оборудованием выполнение проводных операций или прерываний НИКОГДА не будет работать правильно само по себе.

Если вы хотите использовать проводное соединение, вам действительно нужно использовать входы IRQ, чувствительные к уровню. Если это невозможно, то, возможно, вы можете добавить какой-нибудь контроллер прерываний. Это устройство будет принимать N входов, чувствительных к уровню, и иметь один выход и какой-то «чистый». Когда контроллер прерывания получает сигнал сброса, он понижает свой выход, а затем повторно утверждает выход, если какой-либо из его входов все еще был подтвержден.

Что касается программного обеспечения, вы можете посмотреть, идет ли линия IRQ на вход другого процессора. Это позволит вам, по крайней мере, проверить состояние, но обработка ISR ядра Linux ничего не будет знать об этом, и поэтому вам придется что-то исправить, чтобы заставить его проверить это и снова пройти через ISR. Кроме того, это означает, что в ситуациях с тяжелой загрузкой прерывания вы НИКОГДА не собираетесь выходить из этого ISR. Учитывая, что вы используете проводное соединение или IRQ, я предполагаю, что эти устройства не будут слишком часто прерываться.

Еще одна вещь - очень внимательно присмотреться к процессору. Вы можете использовать какой-то трюк с настройкой прерывания, чтобы заставить его снова распознать прерывание.

Я бы сам не стал пробовать ничего слишком сложного, я бы либо разделил источники на отдельные входы IRQ, либо переключился на чувствительный к уровню вход, либо добавил микросхему контроллера прерывания.

person Michael Kohne    schedule 31.01.2012
comment
Спасибо за совет. Я думаю, что мы собираемся реализовать контроллер прерываний в FPGA, который нам в любом случае понадобится на плате. - person blueshift; 21.02.2012