Блокируют ли прерывания другие прерывания?

Если у меня есть прерывание, подключенное к двум контактам, и обработчик первого все еще выполняется, когда срабатывает второе прерывание, не так ли:

а) поставить в очередь второе прерывание,

б) проигнорировать второе прерывание (полностью пропустить его) или

в) приостановить обработку первого прерывания для выполнения второго?

Я пишу код, который регистрирует точное время возникновения прерывания. Довольно легкий, но имеет три штифта и регистрирует подъем и падение каждого из них, так что существует вероятность столкновений. Если а) то вторая метка времени прерывания будет запаздывать, б) нет метки времени для более позднего прерывания или в) время первого и второго прерываний будет неоднозначным.

б) это наихудший случай, два других вполне управляемы.

, 👍0

Обсуждение

По умолчанию компилятор отключает прерывания в начале ISR и снова включает их в конце. Вы можете отключить это и включить прерывания внутри других прерываний, добавив [ISR_NOBLOCK](https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#ga44569cb914d2aaf8fbb436f8f7c4ca68 ) атрибут вашего ISR. Но вы должны знать, что делаете., @Gerben

Похоже, что режим захвата ввода таймера может быть полезен для вашей конкретной проблемы., @Gerben

Гербен подробнее об этом расскажет. Я усердно работал над тем, чтобы ускорить работу с прерываниями, и добрался до внешних прерываний на выводах и внутренних прерываний. Возможно, вы предлагаете что-то лучшее для этой задачи, @J Collins

В зависимости от вашей платы может оказаться невозможным использовать режим захвата ввода таймера для ваших контактов. В этом режиме вы можете позволить аппаратному таймеру фиксировать длительность импульса (а не его временную метку в общем временном режиме). Но вам понадобится один аппаратный таймер на вход. У большинства плат осталось не так уж много таймера, особенно если вы все еще хотите использовать такие функции, как delay(), millis() или micros(), для настройки которых требуется Timer0. Возможно, простое прерывание смены вывода было бы самым простым. Хотя это зависит от ваших временных требований (насколько точной должна быть записанная метка времени?)., @chrisl

@Gerben: В AVR прерывания отключаются при запуске ISR не компилятором, а аппаратным обеспечением. Атрибут ISR_NOBLOCK - это способ попросить компилятор повторно включить прерывания как можно раньше в ISR., @Edgar Bonet


2 ответа


3

Это зависит от архитектуры.

Предполагая AVR (8-битный Arduino), он будет ставить в очередь второе прерывание до тех пор, пока первое не будет закончено.

Он работает, устанавливая флаг в регистре в момент возникновения прерывания. Затем между инструкциями он проверяет этот флаг и выполняет соответствующую процедуру прерывания. Если прерывание выполняется в то время, когда флаг все еще установлен, но он не может проверить состояние этого флага до тех пор, пока текущее прерывание не закончится и не произойдет нормальное выполнение, после чего после завершения следующей инструкции он проверяет состояния флага прерывания и запускает вторую процедуру прерывания.

,

1

Это зависит от конкретного микроконтроллера, не все они точно такие же.

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

Это одна из причин, по которой следует избегать длительных ISR!

,