Ответ 1
Обычно процедура прерывания обслуживания продолжается до тех пор, пока она не будет завершена, не прервется сама в большинстве систем. Однако, если у нас есть более крупная система, где несколько устройств могут прерывать работу микропроцессора, может возникнуть проблема приоритет.
Если вы установите флаг флаг прерывания в текущем прерывании, то вы можете разрешить дальнейшие прерывания более высокий приоритет, чем тот, который выполняется. Это "прерывание прерывания" называется вложенным прерыванием. Он обрабатывается путем прекращения выполнения первоначальной сервисной процедуры и сохранения другой последовательности регистров в стеке. Это похоже на вложенные подпрограммы. Из-за автоматического уменьшения указателя стека по каждому прерыванию и последующего приращения с помощью команды RETURN первая процедура обслуживания прерывания возобновляется после завершения второго прерывания, и прерывания обслуживаются в правильном порядке. Прерывания могут быть вложены на любую глубину, ограниченную только количеством памяти, доступной для стека.
Например, на следующей диаграмме работает Thread A. Прерывание IRQx запускает обработчик прерываний Intx, который выгружается IRQy и его обработчиком Inty. Inty возвращает событие, вызывающее запуск Thread B; Intx возвращает событие, вызывающее запуск Thread C.
Для аппаратных прерываний Приоритетные чипы контроллера прерываний (PIC) - это аппаратные микросхемы, предназначенные для простого задания задачи, представляющей свой собственный адрес для ЦП. ПИК также оценивает приоритет подключенных к нему устройств. Современный ПИК также может быть запрограммирован для предотвращения генерации прерываний, которые ниже желаемого уровня.
ОБНОВЛЕНИЕ: как вложенные прерывания работают на AVR Atmel
Аппарат AVR удаляет флаг глобального прерывания в SREG перед вводом вектора прерывания. Поэтому обычно прерывания остаются отключенными внутри обработчика до тех пор, пока обработчик не выйдет, где команда RETI (которая испускается компилятором как часть нормального эпилога для обработчика прерываний) в конечном итоге снова включит перебивает. По этой причине обработчики прерываний обычно не гнездятся. Для большинства обработчиков прерываний это желаемое поведение, для некоторых это даже требуется, чтобы предотвратить бесконечно рекурсивные прерывания (например, прерывания UART или внешние прерывания, вызванные уровнем).
В редких случаях, хотя вложенные прерывания могут потребоваться повторно включить флаг глобального прерывания как можно раньше в обработчике прерываний, чтобы не откладывать никаких других прерывать больше, чем это абсолютно необходимо. Это можно сделать с помощью команды sei() в начале обработчика прерываний, но это все еще оставляет несколько инструкций внутри пролог функции, генерируемой компилятором, для запуска с отключенными глобальными прерываниями. Компилятору может быть поручено вставить инструкцию SEI в начале обработчика прерываний, объявив обработчик следующим образом:
ISR(XXX_vect, ISR_NOBLOCK)
{
...
}
где XXX_vect - это имя допустимого вектора прерывания для типа MCU.
Кроме того, посмотрите на Замечание по применению для получения дополнительной информации о прерываниях на AVR Atmel.