Результат обработки (ASCII-символ и скан-код) помещается в клавиатурный буфер, расположенный в ОЗУ. В случае переполнения буфера очередное слово не записывается и подается звуковой сигнал.
Кроме обычного способа (нажатия одной клавиши), любой символ можно ввести в буфер с помощью Alt-набора. Для этого его код в десятичной системе набирается на цифровой клавиатуре при нажатой клавише ALT, результат заносится в буфер по отпускании ALT. При таком способе в буфер будет занесен нулевой скан-код, что отличает Alt-набор от обычного ввода.
Для получения доступа к памяти устройства(клавиатура) используют функции in*()/out*().
Кодовая таблица преобразования скан-кода в ASCII-код находится в файле /usr/include/photon/keycode.h
Пример содержимого файла keycode.h:
/*
* Keyboard codes for Key caps and Key symbols
*/
#define KEYCODE_PC_KEYS UNICODE_PRIVATE_USE_AREA_FIRST + 0x1000
#define KEYCODE_PAUSE (KEYCODE_PC_KEYS + 0x13)
#define KEYCODE_SCROLL_LOCK (KEYCODE_PC_KEYS + 0x14)
#define KEYCODE_PRINT (KEYCODE_PC_KEYS + 0x61)
#define KEYCODE_SYSREQ (KEYCODE_PC_KEYS + 0x6a)
#define KEYCODE_BREAK (KEYCODE_PC_KEYS + 0x6b)
#define KEYCODE_ESCAPE (KEYCODE_PC_KEYS + 0x1b)
#define KEYCODE_BACKSPACE (KEYCODE_PC_KEYS + 0x08)
#define KEYCODE_TAB (KEYCODE_PC_KEYS + 0x09)
#define KEYCODE_BACK_TAB (KEYCODE_PC_KEYS + 0x89)
#define KEYCODE_KP_DELETE (KEYCODE_PC_KEYS + 0xae)
#define KEYCODE_F1 (KEYCODE_PC_KEYS + 0xbe)
#define KEYCODE_F2 (KEYCODE_PC_KEYS + 0xbf)
#define KEYCODE_F3 (KEYCODE_PC_KEYS + 0xc0)
#define KEYCODE_CAPITAL_A UCS_LATIN_CAPITAL_LETTER_A
#define KEYCODE_CAPITAL_B UCS_LATIN_CAPITAL_LETTER_B
#define KEYCODE_CAPITAL_C UCS_LATIN_CAPITAL_LETTER_C
#define KEYCODE_CAPITAL_D UCS_LATIN_CAPITAL_LETTER_D
#define KEYCODE_I UCS_LATIN_SMALL_LETTER_I
#define KEYCODE_J UCS_LATIN_SMALL_LETTER_J
#define KEYCODE_K UCS_LATIN_SMALL_LETTER_K
3). Пример использования функций InterruptAttach() c ненулевыми параметрами [2].
interrupt0.c
#include <sys/neutrino.h>
#include <time.h>
int cnt;
const struct sigevent *handler (void* arg, int id)
{
struct sigevent *hand_even = (struct sigevent *)arg;
cnt++;
if(cnt == 1000)
{
cnt = 0;
return(hand_even);
}
else return(NULL);
}
int main()
{
time_t timeof;
char mtimeof[12];
struct sigevent event;
int id, i = 0;
ThreadCtl(_NTO_TCTL_IO, 0);
event.sigev_notify = SIGEV_INTR;
id = InterruptAttach( 0, handler, &event, sizeof(event), 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 interrupt0
cc interrupt0.c -o interrupt0
# ./interrupt0
00:50:22
00:50:23
00:50:24
00:50:25
00:50:26
00:50:27
00:50:28
#
4 . Выводы
Попробуем сравнить результаты работы в DOS и QNX. Низкий уровень ассемблерных приложений предоставляет весьма широкие возможности по организации перехвата аппаратных прерываний в DOS. Так мы можем получить информацию о процессе, у которого мы перехватываем контроль над прерыванием. В QNX эта информация скрыта. В QNX же сложность ОС накладывает тот отпечаток на средства API, что необходимо контролировать поведение обработчика в многопроцессной среде.
Хочется отметить наличие в API QNX очень удобной функции InterruptWait(), которая позволяет определять момент выхода из обработчика прерывания без дополнительных нагромождений из циклов проверок и контрольных флагов.
5 . Источники информации
1). Программирование приложений реального времени для исполнения в среде операционной системы реального времени QNX/Neutrino2(часть II): О.Л. Никольский – Брянск,2007.
2).
“Writing interrupt handlers”
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.