Изучение принципов обработки аппаратных прерываний. Логика взаимодействия процессора и контроллера прерываний, страница 11

#include <sys/neutrino.h>

#include <time.h>

#include <hw/inout.h>

int cnt, flag = 0, key = 0;

int timeok = 0, dateok = 1;

struct sigevent curtime;

time_t timeof;

char mtimeof[12];

const struct sigevent *handler (void* area, int id)

{

switch(key)

{

case 1:

flag = 1;

return(&curtime);

case 2:

timeok = 1;

dateok = 0;

break;

case 3:

dateok = 1;

timeok = 0;

}

cnt++;

if(cnt == 1000)

{

cnt = 0;

return(&curtime);

}

else  return(NULL);

}

const struct sigevent *keyboard (void* area, int id)

{

key = in8(0x60);

return(NULL);

}

int main()

{

int id1, id2, i = 0;

ThreadCtl(_NTO_TCTL_IO, 0);

curtime.sigev_notify = SIGEV_INTR;

id1 = InterruptAttach( 0, &handler, NULL, NULL, 0);

id2 = InterruptAttach( 1, &keyboard, NULL, NULL, 0);

while(1)

{    

if( flag == 1) break;

InterruptWait(0, NULL);

timeof = time(NULL);

if(timeok == 1)  

{

strftime(mtimeof, 12, " %T", localtime(&timeof));

printf( " %s\n", mtimeof);

}

if(dateok == 1)  

{

strftime(mtimeof, 12, " %D", localtime(&timeof));

printf( " %s\n", mtimeof);

}

}

InterruptDetach( id1 );

InterruptDetach( id2 );

return 0;

}

Результат выполнения программы:

# ./interrupt5

12/17/08

12/17/08

03:24:35

03:24:36

12/17/08

12/17/08

03:24:39

03:24:40

03:24:41

03:24:42

#

# ./interrupt5&

[1] 1310756

#   12/17/08

12/17/08

12/17/08

12/17/08

03:24:54

03:24:55

03:24:56

12/17/08

12/17/08

12/17/08

03:25:00

03:25:01

03:25:02

12/17/08

12/17/08

12/17/08

[1] + Done                 ./interrupt5

#

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

Дополнительные исследования:

1).Типовые уровни прерываний IRQ и приоритеты прерываний устройств для платформы x86.

Запрос преры-вания IRQ

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

Устройство, вызывающее прерывание

0*

Высший 2

Канал 0 аппаратного таймера, отсчитывающий системные такты с периодом ClockPeriod()

1*

3

Клавиатура

2*

Каскадирование прерываний (перенаправление на второй контроллер 8259)

3*

12

Асинхронный порт COM2 (или COM4)

4*

13

Асинхронный порт COM1 (или COM3)

Примечания.

  − Работу с прерываниями имеет право выполнять только пользователь с правами root.

  − Перед обращением к ядру для обработки прерываний поток должен получить права на операции с портами ввода/вывода и изменение флага прерываний процессора с помощью вызова ThreadCtl( _NTO_TCTL_IO, 0).

− Самые приоритетные запросы прерываний на платформе x86 жёстко закреплены за аппаратным таймером (IRQ0) и клавиатурой (IRQ1) и не могут использоваться для других целей [1].

2). Клавиатура

Контроллер клавиатуры соединен с системной шиной данных (XD-шиной) с помощью двух однобайтных регистров - входного и выходного буферов. Выходной буфер доступен только для чтения через 60h порт и хранит коды сканирования, полученные от клавиатуры или данные, прочитанные по запросу (команды контроллера).

Входной буфер доступен для записи через порты 64h (запись команд) и 60h (запись) данных.

При записи команды в 64h устанавливается флаг записи команды (в регистре состояния). Байты, записанные в 60h, и не являющиеся данными для команд контроллера системного блока, отсылаются по интерфейсу клавиатуры контроллеру клавиатуры.

Скан-код - номер, идентифицирующий расположение клавиши на клавиатуре.

Скан-коды, принятые от клавиатуры, по аппаратному прерыванию IRQ1 (вектор 09h) обрабатываются, и результат обработки помещается в буфер, из которого по программному прерыванию этот результат для дальнейшей обработки может быть извлечен значительно позже. BIOS INT 9h обрабатывает прерывания, вызванные приходом кодов нажатия и отпускания клавиш, анализируя принятый скан-код с учетом состояния флагов и комбинации клавиш альтерации SHIFT, CTRL, ALT, CAPSLOCK, NUMLOCK.