W_LOOP
btfss EECON1,EEIF; Проверяем состояние флага EEIF
goto W_LOOP; ЕСЛИ сброшен, проверяем снова
; ИНАЧЕ продолжаем выполнение программы после сброса флага EEIF
bcf EECON1,EEIF
Вообще говоря, во всех системах, управляемых прерываниями, необходимо предпринимать некоторые меры предосторожности в случае обработки прерываний от нескольких источников. Для примера рассмотрим некоторую систему, получающую запрос прерывания от таймера, скажем, 1000 раз в секунду, а также запрос внешнего прерывания с вывода INT с нерегулярной частотой. Если обработчик внешнего прерывания выполняется, например, за 4 мс, то к моменту выхода из него будут потеряны три запроса прерывания от таймера! В некоторых процессорах[102] имеется схема назначения приоритетов прерываний, благодаря которой запросы с более высоким приоритетом (в данном случае прерывание от таймера) могут прерывать процессы с более низким приоритетом (обработчик внешнего прерывания). В нашем же случае единственным вариантом будет введение ограничения времени выполнения обработчика внешнего прерывания — не более 1 мс[103]. При наличии прерываний от нескольких источников необходимо рассчитать время выполнения (включая задержки) и частоту возникновения прерываний для наихудшего случая. Поскольку некоторые из этих параметров связаны с внешними событиями, не контролируемыми процессором, это может оказаться достаточно нетривиальной задачей.
Другая часто возникающая проблема связана с обработкой таких событий, при которых
Теперь предположим, что эти RTC являются составной частью системы центрального отопления. Фоновая программа должна переключать насос из включенного состояния в выключенное в 09:00:00:00. И в указанное время это произошло. Но вот наступило время 09:59:59:09 того же дня. Фоновая программа, основная задача которой состоит в отслеживании текущего времени, считывает значение часов, равное 09. После этого она собирается считывать значение минут, когда происходит прерывание от генератора. Работа фоновой программы прерывается, и состояние RTC изменяется на 10:00:00:00. При возврате в фоновую программу соответственно считываются значения 00:00:00. Считая, что сейчас 09:00:00:00, программа переключает насос, вследствие чего периоды, когда насос включен и выключен, меняются местами неограниченное число раз!
Разумеется, использовать в программе именно переключение состояния является плохим стилем программирования; то есть в 9 утра насос следовало именно включить, а не просто переключить его состояние. По крайней мере, в последнем случае система будет работать неверно лишь в течение ограниченного времени. Вообще говоря, в случае обработки подобных многобайтных данных в фоновой программе, необходимо на время запрещать обработчик прерывания сбросом соответствующего бита маски. Все прерывания, возникающие в этот период, будут обработаны позже, после установки этого бита маски. Хотя если интервал времени, в течение которого прерывание было замаскировано, окажется слишком большим, некоторые события могут быть пропущены.
Итак, подведем итог. Процедуры обработки прерываний аналогичны обычным подпрограммам, однако необходимо помнить следующее:
• Обработчик прерывания должен завершаться командой retfie вместо return.
• Рабочий регистр, а также все РСН, изменяемые в обработчике прерывания, должны быть сохранены при входе в обработчик и восстановлены при выходе из него, если они также используются в фоновой программе.
• Параметры не могут передаваться в/из обработчика прерывания через рабочий регистр. Вместо этого, при необходимости, следует использовать глобальные переменные (данные, расположенные в памяти по известному адресу).
• Обработчики прерывания должны быть как можно короче и должны выполнять минимальный набор операций. Это полезно при отладке, а также позволяет гарантировать, что ни одно из других событий не будет пропущено.
• Если в обработчике прерывания обрабатываются многобайтные данные, то при любом обращении фоновой программы к этим переменным необходимо запрещать прерывания (сбросом бита GIE).