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

_NTO_INTR_FLAGS_TRK_MSK    -   на время выполнения обработчика маскировать                                                                                       прерывания;

При решении стоящих перед нами задач: перехват прерываний таймера и клавиатуры аргумент intr будет соответственно принимать значения 0 и 1. Так как в рассматриваемом простейшем случае использование сложных механизмов неоправданно, аргументы area и size примут значения NULL. Аналогично им – flags.

#include <sys/neutrino.h>

Int InterruptMask(  int intr, int id);

Функция маскирования аппаратных прерываний.

intr                  номер маскируемого прерывания

id                     идентификационный номер маскируемого обработчика

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

#include <sys/neutrino.h>

int InterruptUnmask( int intr, int id);

Функция демаскирования аппаратного прерывания. Значение аргументов аналогично InterruptMask().

#include <sys/neutrino.h>

int InterruptWait(  int flags, const uint64_t * timeout);

Функция ожидания произвольного аппаратного прерывания. Аргументы должны быть 0 и NULL – зарезервированы для будущего использования.

Рассмотрим теперь примеры работы с аппаратными прерываниями в QNX.

3.1.  Транзитная программа вывода текущего времени

interrupt1.c

#include <sys/neutrino.h>

#include <time.h>

int cnt;

struct sigevent curtime;

time_t timeof;

char mtimeof[12];

//обработчик аппаратного прерывания: возвращает указатель на связанную с этим //прерванием структуру

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

{

cnt++;

// обработчик вызывается раз в 1 мс(используем программный делитель)

if(cnt == 1000)

{

cnt = 0;

return(&curtime);

}

else  return(NULL);

}

int main()

{

int id, i = 0;

// для работы с аппаратными прерываниями нить должна получить особые полномочия I/O

ThreadCtl(_NTO_TCTL_IO, 0);

// прерыванию соответствует специфический тип оповещения, указываемый в приписанном // к нему объекту структуры sigevent

curtime.sigev_notify = SIGEV_INTR;

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

for (i=0; i<7; i++)

{

InterruptWait(0, NULL);

timeof = time(NULL);

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

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

}

InterruptDetach( id );

return 0;

}

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

# make interrupt1

cc     interrupt1.c   -o interrupt1

# ./interrupt1

01:19:25

01:19:26

01:19:27

01:19:28

01:19:29

01:19:30

01:19:31

#

3.2.  Перехват прерывания от клавиатуры

Модификация транзитной программы вывода текущего времени,  выход осуществляется по нажатию клавишы «Esc».

interrupt2.c

#include <sys/neutrino.h>

#include <time.h>

#include <hw/inout.h>

int cnt, flag = 0, key = 0;

struct sigevent curtime;

time_t timeof;

char mtimeof[12];

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

{

if( key == 1) // нажата клавиша ‘Esc’   

{

flag = 1;  

return(&curtime);

}

cnt++;

if(cnt == 1000)

{

cnt = 0;

return(&curtime);

}

else  return(NULL);

}

// обработчик прерывания от клавиатуры

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

{

// получение скан-кода нажатой клавиши по опросу 8-битного порта 0x60

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);

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

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

}

InterruptDetach( id1 );

InterruptDetach( id2 );

return 0;

}

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

# make interrupt2