19 декабря 2011 г.

Делаем курсач по VMEbus. Часть 7. Прерывания, прерыватели, шина приоритетных прерываний, вектор прерывания


Начинаем важную и непонятную тему - прерывания.

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




Шина приоритетных прерываний

Вспомним, что шина VME состоит из четырех шин:

  • data transfer bus (DTB) - шина пересылки данных;
  • priority interrupt bus - шина приоритетных прерываний;
  • DTB arbitration bus - шина арбитража;
  • utility bus -  служебная шина.

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

Шина приоритетных прерываний используется для генерации прерываний и их обработки. На этой шине различают три типа устройств:
  1. INTERRUPTER (прерыватель) - устройство,  генерирующее запрос прерывания.
  2. INTERRUPT HANDLER (обработчик прерывания) - устройство, обслуживающее прерывание. 
  3. IACK DAISY-CHAIN DRIVER (формирователь цепочки подтверждения прерываний) - устройство, использующееся для координации обслуживания прерываний.

Шина приоритетных прерываний состоит из следующих 9 линий:
  • IRQ1*, IRQ2*, IRQ3*, IRQ4*, IRQ5*, IRQ6*, IRQ7* - линии запросов прерывания. Прерыватели выставляют низкий уровень на одной из этих линий, чтобы сгенерировать запрос. Самым приоритетным считается уровень 7, наименее приоритетным - уровень 1. 
  • IACK* - линия подтверждения прерывания. 
  • IACKIN*/IACKOUT* - цепочка подтверждения прерываний. Эта линия проходит последовательно через все модули на шине VME. Каждую из линий запроса прерываний может использовать одновременно несколько прерывателей, поэтому необходимо использовать эту цепочку, чтобы гарантировать ответ только одного прерывателя на подтверждение.  

Вот как выглядит цепочка обработки прерывания, обратите внимание, как линия IACKIN*/IACKOUT* пронизывает все устройства:



Цепочка подтверждения прерываний - более важная деталь, чем может показаться в начале. Она необходима для корректной обработки прерываний.  Все устройства сидят на ней, как бусины на нитке.

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

Все это происходит до тех пор, пока один из прерывателей не поймет, что его спалили и не раскается в содеянном. Он оставляет свой IACKOUT* в высоком состоянии, и сигнал подтверждения не проходит дальше.


Прерыватель

Посмотрим, как сидит прерыватель на шине приоритетных прерываний:


   * С линиями, отмеченными прямой стрелкой наше устройство точно должно взаимодействовать. 

Как работает прерыватель:
  1. Он запрашивает прерывание у обработчика прерывания.
  2. Если он получает отрицательный фронт на входе цепочки подтверждения прерывания и если это он запросил прерывание, а полученный номер уровня прерывания совпадает с его собственным уровнем и длина запрашиваемого вектора прерывания соответствует его собственному, он выставляет свой вектор прерывания на шину данных и опускает линию DTACK* на низкий уровень.
Каждый прерыватель может управлять только одной линией IRQ. Если он получает отрицательный фронт на входе цепочки подтверждения прерывания, но запрашивал прерывание не он, или уровни A01-A03 не соответствуют его собственным, или длина запрашиваемого вектора прерывания меньше, чем длина его собственного вектора, то он должен передать отрицательный фронт дальше по цепочке.

Снятие прерывания

После обработки прерывания устройство должно как-то снять запрос с шины. Для этого есть три пути:
  1. Когда процессор обнаруживает запрос прерывания от прерывателя, он вызывает программу обслуживания прерывания и считывает вектор прерывания из статусного регистра. Прерыватель понимает, что его статусный регистр читают, и снимает запрос.
  2. Когда процессор обнаруживает запрос прерывания, он вызывает подпрограмму обслуживания прерывания и осуществляет запись в управляющий регистр прерывателя. Прерыватель понимает, что в его регистры пишут, и снимает запрос.
  3. Когда процессор обнаруживает запрос прерывания он читает вектор прерывания. Прерыватель понимает, что его регистр считывают, и снимает запрос.
Прерыватели, использующие методы 1 и 2, называются RORA (Release On Register Access - снятие по доступу к регистрам), а те, которые используют метод 3 - ROAK (Release On AcKnowledge - снятие по подтверждению). 

Прерыватели RORA не должны снимать запрос прерывания, пока не получат отрицательный фронт строба данных DS0* или DS1* во время цикла доступа к регистрам. Они должны снимать запрос только через 2 мс после того, как последний строб данных возвратится в высокое состояние в конце цикла доступа.

Прерыватели ROAK не должны снимать запрос прерывания, пока не получат отрицательный фронт строба данных DS0* или DS1* во время цикла запроса прерывания (что означает подтверждение прерывания). 

Прерыватели обоих типов должны выставлять свой вектор прерывания во время цикла подтверждения прерывания, который инициализируется в ответ на их запрос.

Вектор прерывания


Что же это за вектор такой, и где его взять?


Вектор прерывания содержит информацию о том, что процессору необходимо делать, чтобы обработать это прерывание. Инструкции и наставления, короче. Этот вектор - просто байт, который хранится в регистре прерывания (статусном регистре) прерывателя. В нашем устройстве должен быть такой регистр прерывания, соединенный входами и выходами с шиной данных через шинные формирователи (о них далее). 


В принципе, вектор прерывания может быть хардверно задан в регистре с помощью перемычек, но так делать не модно. Куда круче сделать возможность записывать базовый вектор прерывания в регистр в цикле DTB! 

Мы уже должны были сделать адресацию регистра прерывания. Еще нам надо учесть, что в этот регистр мы будем писать и будем читать из него. То есть нам надо следить за уровнем на WRITE* и поступать в соответствии с ним: WRITE* низкий - мастер пишет базовый вектор прерывания в регистр прерывателя, WRITE* высокий - обработчик прерывания читает вектор прерывания из регистра прерывателя.


Последовательность прерывания

Последовательность прерывания состоит из трех фаз:
  1. фаза запроса прерывания - начинается, когда прерыватель устанавливает на линии запроса прерывания низкий уровень, и заканчивается, когда обработчик прерывания получает управление шиной DTB;
  2. фаза подтверждения прерывания - обработчик прерываний использует шину DTB для считывания вектора прерывания;
  3. фаза обслуживания прерывания - исполняется программа обслуживания прерывания.
Посмотрим на схемке, кто что делает:


Наше дело, как всегда, за малым - реализовать следующие действия:
  1. Опустить IRQx* вниз.   /*что-то происходит после этого в других устройствах*/
  2. Обнаружить IACKIN* низким.
  3. Проверить линии A01-A03 (сравнить с номером линии приоритетного прерывания, на которой был выставлен запрос).
  4. Если A01-A03 совпали, по низкому уровню на DS0* и DS1* поместить вектор прерывания на шину данных D00-Dxx (зависит от вашего типа адресации).
  5. Опустить DTACK* вниз.
  6. ....
  7. PROFIT!
Да, и не забыть снять запрос прерывания.
    P.S. 

    Тема выглядит довольно непростой, но прерывания всегда и везде - нетривиальная задача. Придется смириться, разобраться и реализовать. Готов ответить на ваши вопросы в комментариях.

    Список статей

    Часть 1. Введение. Евромеханика
    Часть 2. Шины и устройства
    Часть 3. Шина DTB
    Часть 4. Slave-устройство на шине DTB. Циклы записи и чтения
    Часть 5. Чтение адреса slave-устройством. Типы адресации. Регистр-защелка и компаратор
    Часть 6. Программное управление slave-устройством. Дешифратор, D-триггер и свичи
    Часть 7. Прерывания, прерыватели, шина приоритетных прерываний,вектор прерывания
    Часть 8. Шинные формирователи
    Часть 9. Рисуем схему по ЕСКД. Schemagee. Автоматическое создание списка элементов
    Часть 10.Добавляем собственную микросхему в Schemagee
    Часть 11. Импорт микросхемы из P-CAD в SchemaGee с последующим допиливанием