Прерывает ли прерывание другие прерывания на Arduino? - PullRequest
22 голосов
/ 25 февраля 2011

У меня есть Arduino Uno (классное устройство!). У него есть два прерывания; давайте назовем их 0 и 1 . Я присоединяю обработчик к прерыванию 0, а другой к прерыванию 1, используя attachInterrupt(): http://www.arduino.cc/en/Reference/AttachInterrupt.

Прерывание 0 запускается и вызывает его обработчик, который выполняет некоторое вычисление чисел. Если обработчик прерывания 0 все еще выполняется при запуске прерывания 1 , что произойдет?

Будет ли прерывание 1 прерывание прерывания 0 или будет прерывание 1 ждать, пока не будет выполнен обработчик прерывания 0 ?

Обратите внимание, что этот вопрос относится конкретно к Arduino.

Ответы [ 3 ]

25 голосов
/ 25 февраля 2011

На оборудовании Arduino (он же AVR) вложенные прерывания не происходят, если вы не намеренно создаете условия, чтобы это произошло.

Из avr-lib:

Аппаратное обеспечение AVR очищает глобальный флаг прерывания в SREG перед вводом вектора прерывания. Таким образом, обычные прерывания будут оставаться отключенными внутри обработчика до тех пор, пока обработчик не выйдет, и команда RETI (которая передается компилятором как часть нормального функционального эпилога для обработчика прерываний) в конечном итоге вновь активирует дополнительные прерывания. По этой причине обработчики прерываний обычно не вкладываются. Для большинства обработчиков прерываний это желаемое поведение, для некоторых оно даже требуется для предотвращения бесконечно рекурсивных прерываний (таких как прерывания UART или внешние прерывания, инициируемые уровнем). В редких случаях может потребоваться повторно включить глобальный флаг прерывания как можно раньше в обработчике прерываний, чтобы не откладывать любое другое прерывание больше, чем это абсолютно необходимо. Это можно сделать с помощью инструкции sei () в самом начале обработчика прерываний, но это все еще оставляет мало инструкций внутри пролога функции, сгенерированного компилятором, для запуска с отключенными глобальными прерываниями.

(источник: http://linux.die.net/man/3/avr_interrupts)

4 голосов
/ 07 марта 2016

Будет ли прерывание 1 прерывать прерывание 0 или прерывать 1, пока не завершится выполнение обработчика прерывания 0?

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

Большинство прерываний устанавливают флаг внутри процессора, который проверяется между инструкциями, чтобы увидеть, нужно ли обрабатывать прерывание. Флаги проверяются в приоритетном порядке. На Uno это:

 1  Reset 
 2  External Interrupt Request 0  (pin D2)          (INT0_vect)
 3  External Interrupt Request 1  (pin D3)          (INT1_vect)
 4  Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
 5  Pin Change Interrupt Request 1 (pins A0 to A5)  (PCINT1_vect)
 6  Pin Change Interrupt Request 2 (pins D0 to D7)  (PCINT2_vect)
 7  Watchdog Time-out Interrupt                     (WDT_vect)
 8  Timer/Counter2 Compare Match A                  (TIMER2_COMPA_vect)
 9  Timer/Counter2 Compare Match B                  (TIMER2_COMPB_vect)
10  Timer/Counter2 Overflow                         (TIMER2_OVF_vect)
11  Timer/Counter1 Capture Event                    (TIMER1_CAPT_vect)
12  Timer/Counter1 Compare Match A                  (TIMER1_COMPA_vect)
13  Timer/Counter1 Compare Match B                  (TIMER1_COMPB_vect)
14  Timer/Counter1 Overflow                         (TIMER1_OVF_vect)
15  Timer/Counter0 Compare Match A                  (TIMER0_COMPA_vect)
16  Timer/Counter0 Compare Match B                  (TIMER0_COMPB_vect)
17  Timer/Counter0 Overflow                         (TIMER0_OVF_vect)
18  SPI Serial Transfer Complete                    (SPI_STC_vect)
19  USART Rx Complete                               (USART_RX_vect)
20  USART, Data Register Empty                      (USART_UDRE_vect)
21  USART, Tx Complete                              (USART_TX_vect)
22  ADC Conversion Complete                         (ADC_vect)
23  EEPROM Ready                                    (EE_READY_vect)
24  Analog Comparator                               (ANALOG_COMP_vect)
25  2-wire Serial Interface  (I2C)                  (TWI_vect)
26  Store Program Memory Ready                      (SPM_READY_vect)

(Обратите внимание, что сброс не может быть замаскирован).

Возможно, прерывание низкого уровня может выполняться (например, TIMER0_OVF_vect). Пока он занят своими делами, может произойти несколько других событий прерывания (и установить соответствующие биты в CPU). Они будут обслуживаться в указанном выше порядке, а не в том порядке, в котором они действительно происходят во времени.

Существуют аппаратные регистры, в которые можно записывать данные для отмены ожидающего прерывания, то есть для очистки флага.


Причина упоминания «еще одной инструкции машинного кода» заключается в том, что процессор спроектирован так, чтобы при переходе от не включенных прерываний к разрешенным прерываниям всегда выполнялась еще одна инструкция.

Это позволяет вам написать код, подобный этому:

  interrupts ();             // guarantees next instruction executed
  sleep_cpu ();              // sleep now

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


Как чудесно идиотски и Freescale, и Atmel используют одинаковые названия команд, но с перевернутыми значениями

Именно поэтому я предпочитаю мнемонику interrupts и noInterrupts, потому что цель там очень ясна. Они реализованы с помощью определений в основных включаемых файлах.

1 голос
/ 03 февраля 2016

В документации упоминается, что прерывания Arduino имеют приоритет:

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

Также имеется ссылка на дополнительную информацию:

Подробнее о прерываниях см. Примечания Ника Гаммона .

В соответствии с разделами Что такое приоритет прерывания? и Могут ли прерывания происходить, когда прерывания отключены? , мы можем заключить, что:

  1. Прерывания основаны на списке флагов. Когда происходит событие, устанавливается соответствующий флаг.
  2. Если ISR не может срабатывать прямо сейчас, его можно вызвать в любое время позже, поскольку флаг сохранен.
  3. Существует список всех доступных прерываний, и он обычно зависит от чипа. Чем выше список, тем выше приоритет .

Таким образом, различные прерывания не будут прерывать друг друга. Они будут выполнены в соответствии с их приоритетом.

...