3.4 Управление прерываниями

Предыдущая  Содержание  Следующая V*D*V

Каждая плата с её оборудованием управления прерываниями уникальна, в основном из-за интерфейса PIC (Programmable Interrupt Controller, программируемый контроллер прерываний). В этом разделе подробно описаны этапы программирования контроллера прерываний в Linux. Прежде чем углубляться в подробности программирования контроллера прерываний, познакомимся с основными функциональными возможностями PIC:

 

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

PIC обеспечивает аппаратное управление приоритетом прерываний. Это может быть полезной функцией в случае, если сам процессор не поддерживает аппаратно приоритеты прерываний. Когда процессор обрабатывает прерывание высокого приоритета, PIC не доставляет процессору прерывания более низкого приоритета. Также, когда два устройства одновременно вызывают прерывание, PIC будет проверять регистр приоритета, чтобы распознать прерывание с более высоким приоритетом, а затем доставить его в процессор.

Выполнение преобразований при переключениях. Оборудование обеспечивает прерывания двумя способами: уровнем и переключением уровня. Прерывания при переключении происходят на переходе сигнала из одного состояния в другое (как правило, от высокого к низкому); обычно это короткий импульс, указывающий на возникновение прерывания. Прерывание, работающее по уровню, с другой стороны, удерживают линию прерывания на высоком уровне, пока процессор не выключит её. Прерывания, вызываемые переключением, это старый метод прерываний и используется архитектурами шины ISA. Тем не менее, основным недостатком прерываний при переключении является то, что они не позволяют совместное использование прерываний. Срабатывания по уровню позволяют разделять прерывания, но должны использоваться осторожно, потому что неправильно спроектированный обработчик прерывания может привести к зависанию системы навсегда в цикле обработки прерываний. Некоторые процессоры позволяют сконфигурировать обработку прерываний или по переходу, или по уровню, в то время как другие процессоры распознают только прерывания по уровню. Если устройство, генерирующее прерывания переключением уровня, подключено к последнему множеству, то прерывания при переходе будут рассматриваться как ложные прерывания, поскольку причина прерывания будет снята до начала обработки. В таком случае будет удобен PIC, потому что PIC может перевести прерывания по переходу в прерывания по уровню, запоминая входное прерывание.

 

В качестве примера PIC для понимания вопросов программирования мы возьмём 8259A. Почему 8259A? Потому что это очень популярное и мощное аппаратное обеспечение и есть много вариантов его использования на встраиваемых платах. Прежде чем мы сможем понять подключение 8259A в BSP, нам требуется общее представление о 8259A. Основные функции контроллера 8259A:

 

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

Он может быть запрограммирован для различных режимов:
– Полностью вложенный режим, который вводится сразу после инициализации. В этом режиме приоритеты являются уникальными и неизменными. В этом режиме прерывание с более высоким приоритетом может прервать процессор, когда он обслуживает более низко приоритетное прерывание.
– Режим автоматической ротации для поддержки прерываний, имеющих одинаковый приоритет.
– Режим настраиваемой ротации, когда приоритет прерывания можно запрограммировать, изменяя самый низкий приоритет и тем самым назначать все другие приоритеты.

PIC может быть запрограммирован для работы по переходу или срабатывания по уровню.

Каждое прерывание может быть замаскировано.

 

В обработку прерываний 8259A вовлечены 3 регистра: IRR или interrupt request register, регистр запроса прерывания, IMR или interrupt mask register, регистр маски прерываний, и ISR или interrupt service register, регистр обслуживания прерываний. Когда внешнее устройство требует прерывания, устанавливается соответствующий бит в IRR. Если прерывание не замаскировано, что зависит от того, установлен ли бит в IMR, прерывание поступает в логику арбитража приоритета. Она проверяет содержимое регистра ISR, чтобы выяснить, обслуживается ли в настоящее время прерывание с более высоким приоритетом; если нет, поднимается флаг прерывания, чтобы процессор увидел прерывание. Процессоры x86 формируют цикл INTA, с тем, чтобы PIC управлял вектором прерывания на шине; однако процессоры не имеют такой функциональности в оборудовании; это явным образом должно сделать программное обеспечение. Бит ISR остаётся установленным, пока не выдан сигнал EOI (End Of Interrupt, Завершение Прерывания). Если PIC сконфигурирован для автоматического режима завершения прерывания, то подтверждение прерывания само вызывает очистку данного бита.

Устройство может быть подключено непосредственно к процессору и в этом случае оно прерывает процессор по одной из линий прерываний процессора; в противном случае его прерывания могут маршрутизироваться через PIC. Но маршрут захваченного прерывания не должен быть заботой программного драйвера устройства. BSP должен экранировать драйвер от фактической маршрутизации прерываний. Например, Рисунок 3.5 показывает сетевую карту, подключенную непосредственно через PIC к процессору MIPS (MIPS поддерживает шесть входов прерываний).

 

Рисунок 3.5 Подключения прерывания сетевой карты.

Рисунок 3.5 Подключения прерывания сетевой карты.

 

Ядро Linux обрабатывает все прерывания как логические прерывания; логические прерывания непосредственно подключены к процессору или могут идти через PIC. В обоих случаях, когда прерывание зарегистрировано (через функцию request_irq()), драйвер устройства должен передать номер прерывания как аргумент, который определяет номер прерывания; передаваемый номер прерывания также является логическим номером прерывания. Количество логических прерываний варьируется в зависимости от процессора; для процессора MIPS оно определено как 128. За связь логических прерываний с реальными физическими прерываниями ответственнен BSP. Таким образом, в приведённом выше примере в обоих случаях драйвер может использовать один и тот же номер прерывания, но как номер прерывания маршрутизируется на реальном оборудовании решает BSP; это упрощает переносимость драйверов устройств.

Основой интерфейса прерываний BSP являются две структуры данных:

 

Описание контроллера прерываний hw_interrupt_type: эта структура задекларирована в include/linux/irq.h. Любой механизм аппаратного контроля прерываний должен использовать эту структуру. Важными полями этой структуры данных являются:
start-up: указатель на функцию, которая вызывается, когда прерывания зондируются или когда они запрашиваются (с использованием функции request_irq())
shutdown: указатель на функцию, которая вызывается, когда прерывание освобождается (с использованием функции free_irq())
enable: указатель на функцию, которая включает линию прерывания
disable: указатель на функцию, которая выключает линию прерывания
ack: указатель на зависимую от контроллера функцию, которая подтверждает прерывания
end: указатель на функцию, которая вызывается после того, как прерывание было обслужено

Описание прерывания irq_desc_t: оно также задекларировано в include/linux/irq.h. С помощью этой структуры определяется каждое логическое прерывание. Важными полями этой структуры данных являются:
status: состояние источника прерываний
handler: указатель на описание контроллера прерываний (описано выше)
action: список событий прерывания

 

Использование этих структур данных может быть лучше всего объяснено на примере. Рисунок 3.6 показывает архитектуру прерываний на плате EUREKA.

 

Рисунок 3.6 Подключения прерываний на плате EUREKA.

Рисунок 3.6 Подключения прерываний на плате EUREKA.

 

MIPS поддерживает шесть аппаратных прерываний. На плате на Рисунке 3.6 пять из них подключены непосредственно к аппаратным устройствам, в то время как шестое прерывание подключено к PIC, который в свою очередь используется для подключения ещё пяти аппаратных устройств. Таким образом, на плате есть десять источников прерываний, которые должны быть связаны с десятью логическими прерываниями для десяти устройств для использования драйверами устройств. Шаги, которые должны быть сделаны BSP для реализации логических прерываний:

 

Создание hw_interrupt_type для прерываний, которые подключены непосредственно к процессору. Назовём это generic_irq_hw.

Создание hw_interrupt_type для PIC. Назовём это pic_irq_hw.

Определение десяти структур irq_desc_t, соответствующих десяти логическим прерываниям. Первые пять привязываем к полю handler в generic_irq_hw, а последние пять привязываем к pic_irq_hw.

Написание кода запуска прерывания, который вызывается, когда процессор прерывается. Эта процедура должна проверять состояние регистра прерываний MIPS, а затем регистр состояния PIC, чтобы оценить, было ли прерывание прямым прерыванием, или же было смаршрутизировано через PIC. Если прерывание относится к PIC, код должен прочитать регистр состояния PIC и узнать логический номер прерывания. Затем должна быть вызвана функция универсального обработчика прерывания do_IRQ() с логическим номером прерывания. Она будет выполнять соответствующую обработку PIC до и после вызова фактического обработчика.

 

Каждая поддержка контроллера прерываний требует вызовов BSP. Следующие функции, заполняющие hw_interrupt_type, были описаны выше, и вызываются на различных этапах обработки прерываний.

 

Процедура инициализации: она должна быть вызвана один раз (в функции init_IRQ()). Функция выдаёт команды ICW (Initialization Command Word, Слова Команд Инициализации), которые должны быть выполнены до того, как 8259 сможет обрабатывать и принимать запросы прерываний.

Процедура запуска: эта функция вызывается, когда запрошено прерывание или когда прерывание зондируется. В 8259 эта процедура просто разрешает прерывание, демаскируя его в PIC.

Процедура выключения: это дополнение процедуры запуска; она запрещает прерывание.

Процедура включения: эта процедура демаскирует указанное прерывание в 8259. Она вызывается из функции ядра enable_irq().

Процедура запрета: эта процедура устанавливает бит в IMR. Эта функция вызывается из функции ядра disable_irq().

Процедура подтверждения: процедура подтверждения вызывается на начальной стадии обработки прерывания. Когда происходит прерывание, последующие срабатывания этого же прерывания запрещены до тех пор, пока работает обработчик прерывания. Это сделано для предотвращения проблемы повторного входа для ISR. Так что эта процедура маскирует прерывание, которое обслуживается в настоящее время. Кроме того, для 8259, если не установлен режим автоматического завершения прерывания, эта процедура посылает в PIC команду EOI.

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

 

Предыдущая  Содержание  Следующая