Обслуживание прерываний
Обслуживание прерываний у микроконтроллеров семейства MAXQ осуществляется в три этапа. Первый этап: запись в 16-разрядный регистр прерываний IV адреса подпрограммы обработки прерываний. После сброса в этом регистре по умолчанию устанавливается значение 0000h, но это значение также является адресом начала программы после сброса при включении питания. Поэтому рекомендуется выполнить команду:
move IV, IntHandler ; которая транслируется в последовательность команд
; move PFX[0], #high(IntHandler)
; move IV, #low(IntHandler)
; записывать PFX[0] нет необходимости если адрес IntHandler равен 00xxh
|
Затем, необходимо разрешить прерывания. Для того чтобы обслуживались любые прерывания необходимо установить бит IGE в регистре прерываний и контроля (IC) в единицу. Затем, необходимо разрешить прерывания на модульном уровне и локально в пределах модуля. Биты разрешения прерываний на модульном уровне находятся в регистре масок прерываний (Interrupt Musk), а локальные биты разрешения прерываний находятся в соответствующих модулям регистрам.
Как только по возникновению прерывания управление передается подпрограмме обслуживания прерываний, сразу аппаратно устанавливается бит обслуживания прерываний (Interrupt in Service - INS), который блокирует дальнейшее обслуживание прерываний. Источник прерываний должен быть определен в подпрограмме обработке прерываний. Так как все прерывания имеют один и тот же адрес прерываний, то для определения источника прерывания необходимо проанализировать состояние регистра идентификации прерываний (Interrupt Identification - IIR). Например, бит II0 (IIR.0) будет установлен, если есть отложенное прерывание от модуля 0. Эти биты не могут быть очищеннепосредственно; вместо этого после обработки прерывания необходимо очистить соответствующий флаг в модуле.
Бит INS устанавливается автоматически при входе в подпрограмму обработки прерывания и автоматически очищается при выходе из нее по команде RETI.
IntHandler:
push PSF ; сохранение значения бита переноса C так как оно используется
для идентификации
move C, IIR.X ; проверка флага в регистре, имеющего самый высокий приоритет
jump C, ISR_X ; если IIR.X установлен, то прерывание произошло от модуля X
move C, IIR.Y ; проверка флага прерывания, имеющего следующий уровень приоритета
jump C, ISR_Y ; если IIR.Y установлен, то прерывание произошло от модуля Y
...
ISR_X:
...
reti
|
Обеспечение приоритета обслуживания прерываний при наличии нескольких источников прерывания может быть реализовано методом, показанным выше. Регистр масок IMR не должен использоваться при обслуживании прерывания с самым высоким уровнем приоритета, так как обработка этого прерывания никогда не должно прерываться. Это обеспечивается установкой бита INS в единицу. Приведенный ниже фрагмент кода программы демонстрирует, как можно использовать IMR для разрешения других прерываний.
ISR_Z:
pop PSF ; восстановление PSF
push IMR ; запись текущей маски прерывания
move IMR, #int_mask ; новый шаблон, разрешающий прерывания только с
более высоким уровнем приоритета
move INS, #0 ; повторное разрешение прерываний
...
(код программы обслуживания прерываний)
...
pop IMR ; восстановление предыдущей маски прерываний
ret ; возврат в тело основной программы или переход к
обслуживанию прерывания следующего уровня приоритета
|
Пожалуйста, обратите внимание, что сброс битов регистра IMR только предотвращает инициализацию обработки прерывания от соответствующих модулей или системных источников прерывания. Сброс бита в регистре масок IMR не предотвращает установку битов флагов прерываний в регистре IIR. Это означает, что при использовании регистра масок IMR для объединения прерываний в блоки может возникнуть ситуация, когда перед обслуживанием прерывания проверку маски прерывания (IMR.x) необходимо будет объединить с проверкой идентификатора прерывания (IIR.x).
|