Skip to content

kernel_irqs_ru

Serge Vakulenko edited this page Aug 26, 2015 · 1 revision

Прерывания

Для обработки аппаратных прерываний применяется механизм сообщений. При захвате мутекса задача может присвоить ему номер аппаратного прерывания, и ожидать сообщения. При возникновении прерывания задача получит сообщение (пустое).

После вызова mutex_lock_irq() аппаратное прерывание считается связанным с указанным мутексом. Для каждого аппаратного прерывания, требующего обслуживания, следует создать отдельную задачу. Такая задача обычно в бесконечном цикле ожидает сообщения о прерывании, выполняет необходимые действия с аппаратурой и посылает сообщения другим мутексам, содержащие результаты обработки.

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

Быстрый обработчик представляет собой функцию, которая регистрируется при захвате мутекса прерывания, и вызывается ядром при наступлении прерывания, обеспечивая максимально высокую скорость реакции. Обслужив прерывание, быстрый обработчик принимает решение и возвращает ядру признак: следует ли посылать основной задаче-обработчику сообщение о прерывании. Таким образом, работа по обработке разделяется между основной задачей прерывания и быстрым обработчиком: срочные действия выполняет быстрый обработчик, а "медленные" - основная задача.

Пока мутекс захвачен функцией mutex_lock(), быстрый обработчик не может быть вызван "немедленно", так как это привело бы к конфликту совместного доступа к данным. В этом случае вызов быстрого обработчика откладывается до освобождения мутекса функциями mutex_unlock() или mutex_wait().

Поскольку быстрый обработчик выполняется в обход механизма синхронизации задач, на него накладываются некоторые ограничения. Во избежание конфликта с другими задачами, он имеет право работать только с данными, защищенными мутексом прерывания. Он не должен вызывать никакие функции ядра (task_xxx(), mutex_xxx()) ни непосредственно, ни посредством вызова других модулей. В частности, он не может обращаться к модулю управления памятью (mem_alloc() и пр.). Подобные действия должны перекладываться на задачу-обработчик.

При возникновении прерывания выполняются следующие действия:

  1. Аппаратный запрет прерывания (закрывается маска в контроллере прерываний).
  2. При наличии быстрого обработчика: 1. Если мутекс занят - вызов быстрого обработчика откладывается до освобождения мутекса. Обработка прерывания закончена. 1. Вызов быстрого обработчика. Если обработчик вернул ненулевой код - обработка прерывания закончена.
  3. Посылка сообщения мутексу.
  4. Переключение задач.

Аппаратное разрешение прерывания (открытие маски в контроллере прерываний) производится при вызове функции mutex_wait().

#include "kernel/uos.h"

typedef int (*handler_t) (void*);

void mutex_lock_irq (mutex_t *lock, int irq, handler_t func, void *arg);
void mutex_unlock_irq (mutex_t *lock);

Для работы с прерываниями применяются следующие функции: | Функция | Описание | |:-----------------------|:-------------| | mutex_lock_irq () | Захват прерывания | | mutex_unlock_irq () | Освобождение прерывания | | mutex_wait () | Ожидание прерывания |

Функция mutex_lock_irq()

#include "kernel/uos.h"

void mutex_lock_irq (mutex_t *lock, int irq, handler_t func, void *arg);

Захват мутекса и привязка его к аппаратному прерыванию с указанным номером. Если мутекс свободен, переключение задач не происходит. Если мутекс занят другой задачей, текущая задача блокируется до освобождения мутекса.

После вызова mutex_lock_irq() аппаратное прерывание считается связанным с указанным мутексом. При возникновении прерываний будет вызван быстрый обработчик, а мутекс будет получать сообщение. При последующих захватах мутекса функцией mutex_lock() вызов быстрого обработчика откладывается на время удержания мутекса. Отложенное прерывание будет обработано при освобождении мутекса вызовом mutex_unlock(), или mutex_wait().

Для каждого аппаратного прерывания, требующего обслуживания, следует создать отдельную задачу. Такая задача должна работать по следующему алгоритму:

  1. захватить прерывание вызовом mutex_lock_irq()
  2. инициализировать обслуживаемую аппаратуру
  3. в цикле ожидать прерывания вызовом mutex_wait()
  4. выполнить необходимые действия с аппаратурой, сохранить данные и т.п.
  5. при необходимости послать сообщения другим мутексам вызовом mutex_signal()
  6. перейти к п.3, продолжив цикл ожидания прерывания

Параметры

  • lock --- Мутекс, который требуется захватить.
  • irq --- Номер аппаратного прерывания, который будет привязан к данному мутексу.
  • func --- Указатель на функцию -- быстрый обработчик прерывания. Необязательный параметр. Если нет необходимости использовать быстрый обработчик, следует указать параметр func равным 0.
  • arg --- Аргумент, передаваемый быстрому обработчику прерывания.

http://uos-embedded.googlecode.com/svn/wiki/images/ilock_ru.png

Пример

TODO example mutex_lock_irq.c

Функция mutex_unlock_irq()

#include "kernel/uos.h"

void mutex_unlock_irq (mutex_t *lock);

Освобождение мутекса, отмена привязки аппаратного прерывания. Прерывание блокируется (запрещается). Может произойти переключение задач.

Следует заметить, что функция mutex_unlock() не отменяет привязку и не блокирует прерывание.

Параметры

  • lock --- Мутекс, который требуется освободить.

http://uos-embedded.googlecode.com/svn/wiki/images/iunlock_ru.png

Пример

TODO example mutex_lock_irq.c

Тип handler_t

#include "kernel/uos.h"

typedef int (*handler_t) (void *arg);

Тип -- указатель на функцию быстрой обработки прерываний.

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

Быстрый обработчик представляет собой функцию, которая регистрируется при захвате мутекса прерывания, и вызывается ядром при наступлении прерывания, обеспечивая максимально высокую скорость реакции. Обслужив прерывание, быстрый обработчик принимает решение и возвращает ядру признак: следует ли посылать основной задаче-обработчику сообщение о прерывании. Таким образом, работа по обработке разделяется между основной задачей прерывания и быстрым обработчиком: срочные действия выполняет быстрый обработчик, а "медленные" - основная задача.

Поскольку быстрый обработчик выполняется в обход механизма синхронизации задач, на него накладываются некоторые ограничения. Во избежание конфликта с другими задачами, он имеет право работать только с данными, защищенными мутексом прерывания. Он не должен вызывать никакие функции ядра (task_xxx(), mutex_xxx()) ни непосредственно, ни посредством вызова других модулей. В частности, он не может обращаться к модулю управления памятью (mem_alloc() и пр.). Подобные действия должны перекладываться на задачу-обработчик.

Параметры

  • arg --- Аргумент, передаваемый быстрому обработчику прерывания. Задается при захвате прерывания функцией mutex_lock_irq().

Пример

TODO example handler.c
You can’t perform that action at this time.