duminică, 17 noiembrie 2013

Прерывания. Программы с прерываниями. Прерывание RESET


     Прерывания

  Прерывание представляет собой приостановку нормального процесса выполнения программы для выполнения более приоритетной задачи. По правилу, прерывание, генерируется как ответ на физический эффект, внутренний или внешний, периферийного модуля . Физический эффект сам по себе представляет нам выполнение прерывания или исключительную ситуацию, которую нужно немедленно выполнить. Например: изменение логического уровня на одном выводе, конец периода времени, конец операции передачи или приёма, конец преобразования и т.д. Большинство периферийных модулей могут генерировать одно или несколько прерываний. Выполнение прерывания предполагает существование определённой подпрограммы для этой цели. При появлении прерывания, МК устанавливает в регистре состояния флаг IF, который будет установлен пока не закончится выполнение подпрограммы обработки прерывания. Для того, чтобы прерывание было сгенерировано, необходимо, чтобы в регистре контроля, был установлен бит IE. Механизм вызова подпрограммы обработки прерывания должен быть инициализирован следующим образом: 
  1. Определилась ситуация прерывания , показанная посредством флага IF==1; 
  2. Прерывание от определённого источника (по фронту и т.д.) разрешается - IE==1;
  3. Бит глобального разрешения прерываний (SREG) I==1.   
Вектор прерываний
    Проще говоря , подпрограмма будет вызвана , если отношение IF&IE&I будет истинно.
Система прерывания, например, позволит выполнение обработки прерывания автоматически, при нажатии на кнопку, взятой, как источник внешнего прерывания EXT_INT.
    Впервые, когда прерывание было сгенерировано система выполняет вызов подпрограммы обработки прерывания (ISR), который предполагает переход на адрес , где реализована эта подпрограмма. Такой вызов не является явным, так же, как и классический вызов CALL где адрес перехода – это параметр команды, вызов hardware предполагает существование в памяти программы некоторой части памяти выделенной для подпрограммы обработки прерывания. Эта часть памяти программы называется вектором прерываний. 
  Так, можем сказать, что вектор прерываний представляет собой часть памяти программы зарезервированной для относительных адресов подпрограмм обработки прерываний. ВП для AVR находится в начале памяти программы начиная с 0x0000 адреса. Для любой подпрограммы обработки прерываний, от разного источника прерываний, зарезервировано пространство для 2-х команд. Очевидно, что этого пространства не хватает для реализации подпрограммы обработки прерываний, но достаточно для выполнения перераспределения через вызов подпрограммы посредством JUMP. Если мы хотим защитить программу от случайных вызовов ISR в этом случае регистрируется команда возврата из подпрограммы. Так, как имеем всего лишь 2 положения для программы, мы выбираем одно из них для нейтрализации нежелательных вызовов ISR путём установки индикатора и т.д.

    .org 0    ; ВП устан. в начале прог-мы
              ; перераспределение посредством прерывания RESET
    rjmp Reset
    nop
              ; заглушка
    reti 
    nop
         ; вызов программы , которая будет выполнятся посредством                ;прерывания
    rcall warn_isr 
    reti
              ; установка пина МК для сигнализации вызова ISR
    sbi PORTA, PINA0 
    reti
              ; запрет ISR
    reti 
    nop
              ; запрет ISR

    reti 
    nop
              ; запрет ISR
    reti 
    nop
              ; запрет ISR
    reti 
    nop
    ...
    ...

 Список прерываний для Atmega16 :


    Приоритет прерываний

    Если 2 внутренних прерывания происходят одновременно, будет обработано прерывание с более высоким приоритетом. Более высокий приоритет будет у того прерывания, у которого относительный адрес в ВП меньше. Таким образом RESET, у которого адрес 0х0000 будет иметь наивысший приоритет. Взяв во внимание, что частота работы МК очень большая, вероятность того, что в один и тот же момент 2 или более прерываний будут запрошены, очень мала.  Но такие случаи всё таки могут возникать, поэтому нужно сбрасывать флаг I командой CLI.


    Механизм вызова подпрограмм обработки прерываний (ISR)

    Как было сказано выше, генерация аппаратных прерываний будет включать в себя вызов ISR. Механизм вызова ISR такой же, как и вызов обычной подпрограммы, с одним отличием, что на протяжении выполнения ISR глобальный бит I=0, который запрещает вызов другого ISR, пока не закончит выполняться данной ISR. Механизм вызова ISR будет реализован в несколько этапов:

  1. При обнаружении прерывания будет выполнятся отношение IF&IE&I. Если это отношение будет истинно будет вызван механизм ISR. Если прерывание будет обнаружено во время выполнения команды, будем ждать до конца её выполнения, после чего будет вызван механизм ISR;
  1. Аппаратный вызов ISR будет выполняться аналогично команде CALL ISR_Addr, где ISR_Addr является относительным адресом в ВП для данного прерывания. Таким образом будет безусловный переход на ISR_Addr, расположенным в ВП, сопровождённый сохранением программным счётчиком (PC) в стеке, PC+1->Stack;
  1. Наряду с переходом в ВП бит I устанавливается в ноль (I=0), эквивалент команды CLI, который будет защищать выполнение ISR от другого ISR обнаруженного в течении этого времени.
  1. Последовательность выполнения инструкций в ISR. Для ISR действительны рекомендации обычных подпрограмм для сохранения состояний РОН используемых в ISR, делается путем сохранения их в начале стека подпрограмм и их восстановление до возвращения из подпрограммы. 
  1. Возврат из ISR выполняется командой RETI. Эта команда аналогична команде возврата из подпрограммы RET, с отличием, что устанавливается флаг I=1 . Можем сказать, что RETI аналогично RET+SEI. Так что, возврат из ISR будет включать в себя восстановление программного счетчика, которое было сохранено при вызове ISR, PC<-Stack и выполнение программы будет продолжаться оттуда, откуда она была приостановлена ​​прерыванием .

Прерывание RESET

    Большинство цифровых систем, в которые входит и МК, предполагают выполнение сигнала RESET, после которого система входит в начальное состояние. Сигнал RESET, как правило, применяется во внутренних регистрах, приводя систему в предопределённое состояние. В нормальном режиме работы устройства сигнал сохраняется в предопределённом состоянии 0 или 1 полученному внутри или вне системы. Инициация RESET предполагает генерирование импульса определённой продолжительности обратного значения нормального состояния функционирования сигнала RESET.
    МК AVR имеет специальный модуль для генерирования внутреннего сигнала RESET. Этот модуль позволяет генерировать внутренний импульс сброса в большинстве случаев, например, при подаче напряжения POWER ON RESET, снижение уровня питания схемы, окончание времени от модуля WATCHDOG или приложение отрицательного импульса на внешний вывод RESET МК. 
    Вместе с внутренним сигналом RESET инициализируются все внутренние регистры МК, генерируется прерывание RESET, которое будет включать в себя обработку этих прерываний. 
    Прерывание RESET имеет самый большой приоритет и следовательно относительный адрес ISR будет установлен в самом начале 0х0000. Прерывание RESET является незашифрованным.

    Программы с прерываниями

    В классической программе, её выполнение начинается с адреса 0х0000, этот адрес предполагает вход в программу. Для программ с прерываниями это неверно. Выполнение программы начинается с адреса 0х0000, но в нашем случае, это предполагает переход на обработку ISR RESET, относительный адрес которой находится в начале ВП (0х0000). В этом случае, при запуске МК генерируется прерывание RESET, которое инициирует вызов ISR для обработки этого прерывания. Считается, что ISR RESET является входом в программу. В ISR RESET будет вовлечена главная программа из классической программы, включая часть инициализации системы и бесконечный цикл который поддерживает МК в течении всей операции. Принцип, по которому ISR не может быть прерван другим прерыванием, включает факт того, что когда мы хотим написать программу без прерываний, наша программа будет начинаться с адреса 0х0000 и игнорируем тот факт, что часть памяти зарезервирована под ВП. Эта возможность связана с тем, что ISR RESET сброшен и она не может быть прервана (I=0) .
    Для программ с прерываниями, рекомендуется избегать запись программы в ВП, в этом случае нам помогает директива .ORG, которая позволяет расположение последовательности кода в определённых адресах. Очевидно, что вызов ISR предполагает инициализацию стека. Исключением являются МК без RAM, которые имеют специальный механизм стека. Без инициализации стека невозможно работать с прерываниями, более того, МК войдёт в неопределённое состояние при первом прерывании, отличном от RESET .

Программа с прерываниями будет состоять из следующих частей: 

  1. Определения Вектора Прерываний;
  2. Главная программа вовлечена в прерывание RESET (П. 3 - 6)
  3. Инициализация конфигурации МК
  4. Разрешение прерываний
  5. Бесконечный цикл, который поддерживает МК
  6. Инициализация стека 
  7. Подпрограммы обработки прерываний
  8. Простые подпрограммы

    Программа с прерываниями будет выглядеть следующим образом 

   .cseg              ; указываем начало сегмента кода
 .org IntxAddr    ; Регистрирование по резервированному адресу   ISR Intx:
 
 2.1. инициализация стека
        out SPL, R16
        ldi R16, HIGH(RAMEND)
        out SPH, R16
        ...
        ...
2.4. Бесконечный цикл
        ...
        rjmp mainloop
               ; в нормальном случае не будет выполнятся никогда
3. Подпрограммы обработки прерываний
        ...
        reti
        ...
        ret

.include "m16def.inc" ; включаем файл адресов периферии для                             ;Atmega16   
1. Определение ВП 
   .org 0           ; Регистрирование по резервированному адресу ISR Reset:
    rjmp Reset      ;перераспределение посредством ISR Reset
      rjmp Intx_ISR ; перераспределение посредством ISR_Intx

   .org 100         ; программа начинается с этого адреса
2. Описание программы вовлечённой в  ISR Reset
   Reset:
    init:                 ;вход в программу

        ldi R16, LOW(RAMEND) ;

2.2. Инициализация конфигурации MCU
        cbi DDRD, PIND
        sbi PORTD, PIND2
2.3. Разрешение прерываний
                   sei

    mainLoop:
        ...
        reti   ; возврат из ISR reset

   Intx_ISR :
        ...
4. Простая подпрограмма
        sub: