Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Обработка прерывания  (Прочитано 13785 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
acc15
Гость
« : 03-05-2006 10:49 » 

Имеется PCI-устройство.

Вопрос №1: Как определить какое устройство сгенерировало прерывание (как говорит ddk когда нужно вернуть true или false из ISR)?
Вопрос №2: Как сбросить это прерывание?

Заранее спасибо.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 10-05-2006 12:18 » 

устройство должно предоставить аппаратный механизм для этого. например: при выставленном прерывании выставлять какой нибудь бит в своем порте IO и не сбрасывать прерывание до момента пока драйвер этот бит не обнулит (или хотя бы просто этот порт не будет прочитан, но это менее корректно).
факт наличия прерывания от именно этого устройства определяется по этому же флагу)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
ort
Гость
« Ответ #2 : 14-05-2006 06:56 » 

реализована следующая схема:
1. происходит прерывание --> в функции обработки прерывания в драйвере если оно разрешено то происходит запрет прерывания и ставица в очередь DCP функция отложеной обработки прерывания
2. далее эта DCP функция сигналит эвантом(KePulseEvent(SharedEvent, 16, false)Ага 
3. в приложении в  юзер моде запущен поток с ожиданием на этот эвант
 
Код:
  while true do
  begin
    WaitForSingleObject(Hevent, INFINITE);

    1. тут обработка прерывания в юзермоде
    2.  а тут шлём драйверу через DeviceIoControl  сигнал о том что прерывание обработано и разрешаем приём нового прерывания
 
  end;
4. возвращаемся к пункту 1

эта схема прекрасно работает при относительно больших промежутках между прерываниями.
При интервале между прерываниями примерно в 1 мили секунду происходит сбой: драйвер выставляет эвант в сигнальное состояние (KePulseEvent) но WaitForSingleObject в юзер моде его не улавливает. в итоге прерывания остаюца запрещёными и весь процесс отсанавливаеца.

Подскажите в чом тут дело и как это иправить =)
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 15-05-2006 10:53 » 

что значит запрет прерываний?) ваш ISR вызывается уже на DIQRL.
правильно делать так:
в ISR вы проверяете - от вашего устройства пришло прерывание или нет(например чтением порта IO) если от вашего - сигнализируете железке чтобы оно сняло прерывание с физического вывода типа intA, intB... это надо делать сразу в ISR!
после этого можете ставить DPС в очередь KeInsertQueueDpc. и уже там выставляете событие.
DPC вызываются достаточно шустро, но чаще килогерца- двух-трех прерывания слать не стоит!!!
при 10кГц - винда только на обработку прерываний половину своих ресурсов тратила. (правда я это давно проверял)

по поводу последнего вопроса - что имеется в виду под запрещением прерываний?
PS ИМХО большую скорость обработки прерываний вы в таком режиме не получтие, потому что это примерно соответствует времени переключения задач (процессов). ВЫХОД: советую всю обработку перенести по возможности в ISR  в крайнем случае в DPC.
PPS обрабатывать прерывания в user mode - крайне малоэфективно и вообще не правильно...
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
ort
Гость
« Ответ #4 : 16-05-2006 02:47 » 

в ISR проверяеца от куда прерывание далее идёт запрет на генирацию новых прерываний на уровне железа(т.е. 100% новые прерывание не приут и не приходят =) ) и если всётаки прерывание пришло в ISR я проверяю если оно запрещено то сразу возвращаю false. Не приследуеца задача быстрой обработки прерываний в юзермоду. пусть они растягиваюца во времени(что естественно) но доходят до юзер мода, т.е. задача не потерять прерывание. При такой схеме оно и не теряеца, но почемуто при  малых промежутках времени между прерываниями не выставляеца евент, хотя функция KePulseEvent  возвращает статус положительного завершения. в результате чего происходит остановка потока в юзер моде на WaitForSingleObject т.к. прерывание я запретил в ISR а разрешение на приём нового прерывание из юзер мода поток не послал драйверу. всеь процесс остановился.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 16-05-2006 11:25 » 

The KePulseEvent routine atomically sets an event object to a signaled state, attempts to satisfy as many waits as possible, and then!!!! resets the event object to a __not signaled__ state.

PS используйте KeSetEvent.
« Последнее редактирование: 16-05-2006 11:28 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
ort
Гость
« Ответ #6 : 16-05-2006 14:01 » 

The KePulseEvent routine atomically sets an event object to a signaled state, attempts to satisfy as many waits as possible, and then!!!! resets the event object to a __not signaled__ state.

PS используйте KeSetEvent.
всё правильно! прерывание отлавилось в юзермоде по эванту и автоматически евант сбрасываеца, ждём следующего прерывания. при использовании KeSetEvent резульат  будет тот же т.к. WaitForSingleObject  после срабатывания сбрасывает эвант. Это всё правильно и как раз то что мне нужно. проблема в другом - почему не сигналит евант при интервале прихода прерываний порядка 10 мили сек., если приходят реже то всё ок.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 16-05-2006 14:38 » 

т.к. есть шанс что плата выставит прерывание (и соответственно вызовет KePulseEvent)  раньше, чем в UserMode вы дойдете до вызова функции WaitForSingleObject. в этом случае событие останется в несигнальном состоянии до вызова WaitForSingleObject.
замените на KeSetEvent - должно заработать.
еще раз: KePulseEvent (в отличии от KeSetEvent) выставлят событие ТОЛЬКО если его УЖЕ кто то ожидает! то есть эта функция удовлетворяет все УЖЕ ожидающие нити.
гарантировать это можно только если с момента разрешения прерывания до момента вызова функции WaitForSingleObject пройдет достаточное количество времени (здесь долно учитываться и время необходимое для переключения задач).

а автоматический сброс события в несигнальное состояние после WaitForSingleObject - это отдельный флаг его инициализации.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
ort
Гость
« Ответ #8 : 17-05-2006 02:25 » 

спасибо, ясно.
по логике с KeSetEvent должно заработать, но  происходит тоже самое ((
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 17-05-2006 10:37 » 

в приложении инициализация события хендел котрого потом отдается драйверу:
    hEvent = CreateEvent(   0,      //указаетль на структуру атрибутов защиты
             FALSE,  //установлен автоматичееский сбросс события
             FALSE,  //начальное состояние
             NULL);  //уникальное имя события
в драйвере инициализация ссылки на объект:
               status =
              ObReferenceObjectByHandle(  (HANDLE)hEvent,
                           EVENT_MODIFY_STATE,
                           *ExEventObjectType,
                           KernelMode,
                           (PVOID*)&pkEvent,
                           NULL);


в DPC драйвера, выставление события:
                        KeSetEvent(pkEvent,IO_NO_INCREMENT,FALSE);//только FALSE, иначе я должен находится на IQRL==PASSIVE_LEVEL

в приложении ожидание события:
       RetWaitFunc = WaitForSingleObject(hEvent,WAIT_EVENT_NEW_BLOCK_MS);

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

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #10 : 21-05-2006 20:22 » new

 Смутно, вы что то недоговариваете, но вот варианты.
 Привызове второго( третьего и т.д. ) KeSetEvent твое приложение еще не получило управление после вызова первого KeSetEvent, соотвественно когда оно управление получит то для него будет очевиден только факт прихода одного прерывания. Но это не согласуется с тем что у тебя из юзер мода разрешается генерить прерывания с девайса.
 Если ты юзаешь для DPC структуру ту что в DriverObject, то у тебя наверно DPC теряются, так как два одинаковых DPC в очередь не ставятся. Если первое DPC не отработало, тогда второе с тем же адресом структуры, описывающей этот DPC, в очередь тебе не запихать. Советую все инфу об пришедшем прерывании запихивать в некую очередь а из DPC ее вычитывать и обрабатывать, так будет две, три и т.д. записи  в очереди. Но опять же несогласованность с тем что прерывания от девайса разрешаются из юзер мода.
Записан
acc15
Гость
« Ответ #11 : 23-05-2006 23:46 » 

Как я понял должно быть что-то вроде этого:
Код:
BOOLEAN
ISR(
    IN PKINTERRUPT Interrupt,
    IN PVOID  ServiceContext
    )
{
PDEVICE_EXTENSION pDevExt = (PI232_PDEVICE_EXTENSION) ServiceContext;
        long x = ReadRegister(pDevExt,INT_CONTROL_REG); // INT_CONTROL_REG - смещение "некого" упр. регистра отн. первого базового адреса PCI пространства (PCI контроллера)
        if (x & INT_MASK) {
        DbgPrint("We got a interrupt");
                // Сброс прерывания
                x &= ~INT_MASK; // убиваем бит прерывания
                WriteRegister(pDevExt,INT_CONTROL_REG,x); // записываем упр. регистр
          IoRequestDpc(pDevExt->DeviceObject,0,pDevExt); // запрос DPC
                return TRUE;
        }
        return FALSE;
}

Я правильно думаю?

PS. ReadRegister, WriteRegister - обертки для READ_REGISTER_ULONG,WRITE_REGISTER_ULONG, а в pDevExt содержится указатель 1ого баз. смещения.
« Последнее редактирование: 23-05-2006 23:58 от acc15 » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 31-05-2006 14:56 » 

так)
один в один как у меня)
PS только я KeInsertQueueDpc использовал...
« Последнее редактирование: 31-05-2006 14:59 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines