Сброс бита регистра IRR контроллера прерываний 8259A

Тема в разделе "WASM.DOS/BIOS/Vesa/ports", создана пользователем Jin X, 8 сен 2018.

  1. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    267
    Адрес:
    Кольца Сатурна
    Приветствую вас!

    При появлении запроса на прерывание (IRQ) в регистре запросов прерывания IRR контроллера 8259A устанавливается бит, соответствующий этому прерыванию. Если бит регистра обслуживаемых запросов ISR того же прерывания (и всех более приоритетных) сброшен и прерывание незамаскировано (в IMR или через cli), процессор подтверждает прерывание и соответствующий бит в IRR сбрасывается, а в ISR устанавливается. После отправки команды EOI сбрасывается и бит регистра ISR, разрешая процессору снова прерывать выполнение кода вызовом обработчика того же прерывания (и менее приоритетных). Соответственно, поскольку после подтверждения прерывания процессором бит в IRR сбрасывается, он в любом момент может быть установлен снова, а значит, если мы ещё не завершили обработку прерывания, по после отправки EOI и выполнения iret/sti обработчик будет вызван снова.

    Мне необходимо предотвратить эту ситуацию и сбросить соответствующий бит регистра IRR перед выходом из обработчика прерывания (iret), ну или перед отправкой EOI. Вопрос: как это сделать?
    Регистр IRR можно без проблем прочитать, интерфейс для этого есть, а вот с записью проблема...

    Вот тут написано:
    Значит, стало быть, каким-то образом IRQ может быть снято? Как это сделать, как сбросить бит регистра IRR?

    p.s. Вариант инициализации контроллера прошу не предлагать :)
     
  2. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.238
    Адрес:
    Fryazino
    Это надуманная проблема. IRR не надо сбрасывать. Когда вы сбрасываете ISR посылкой EOI, контроллер выполнит сброс проверит IRR и если там что-то есть то обнулит IRR и выставит ISR,
     
  3. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.238
    Адрес:
    Fryazino
    Тут борятся только организационно распорядительными методами:
    - обработчик прерывания должен быть как можно карочи.
    - DPC- в виндоусе, Interrupt Service Routin(ISR) - в FreeRtos.
    В обоих этих ОС есть очередь для вызова обработчиков прерываний. При приходе прерывания ОС определяет обработчик прерывания* и кладёт его в очередь. Посылает EOL контроллеру прерываний выполняет IRET, а при первом удобном** случае вызывается обработчик прерывания DPC или ISR.
    * Вернее тут два обработчика прерываний InteruptHandler. Первый тупо проверяет его ли железка вызвало прерывание или нет. А второй уже непосредственно обработчик.
    ** Удобным случаем является момент смены контекста потока. Signal/Slot, а так же при вызове сервиса ядра int 80h.

    Переводчик неправ. Снять можно только если IRR не настроен на режим защёлки. Одна беда так как ISA прерывания импульсные, поэтому IRR настроен на режим защёлки. Так что сбросить не получится без полной инициализации.
     
    Последнее редактирование: 8 сен 2018
  4. Коцит

    Коцит Member

    Публикаций:
    0
    Регистрация:
    31 янв 2017
    Сообщения:
    90
    так реги контроллёра и рулят, что значит не предлагать?
     
  5. Коцит

    Коцит Member

    Публикаций:
    0
    Регистрация:
    31 янв 2017
    Сообщения:
    90
    типа нужно настроить, но настройки не трогатьть
     
  6. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    267
    Адрес:
    Кольца Сатурна
    Он короткий, лишь в редких случаях он работает долго. Вот в этом случае и нужно сделать так, чтобы прерывание не повторялось после завершения текущего обработчика.

    Потому что полный сброс сбросит ВСЕ биты IRR, т.е. если я нажал на клавишу во время работы "долгого обработчика" IRQ 0, клавиша не сработает на выходе из прерывания.

    В принципе, я знаю, как сделать по-другому
    Изначально счётчик таймера настраивается на высокую частоту. А при долгой обработке в счётчик таймера записывается 0, а на выходе новое значение (оно всё равно перезаписывается каждый раз). 55 мс для этой "долгой обработки" хватит с лихвой (там и 1 мс хватит).
    Я просто подумал, что может есть вариант сбросить бит и всё.
     
  7. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.238
    Адрес:
    Fryazino
    Это надуманная проблема. Но если охота.
    Послал EOL не выходя из IRET читаешь ISR и если там есть ваш бит, то ещё раз шлёшь EOL. Перед чтением надобно выдержать паузу, 250 нс.
     
  8. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    267
    Адрес:
    Кольца Сатурна
    Почему надуманная? У меня на каждом вызове определённое действие выполняется, лишних вызовов быть не должно.

    EOL – это EOI ?
    А как в ISR выставится бит, если у меня прерывания запрещены (cli – это же то же самое, что маска IMR)? Его там не будет в любом случае. ISR перенимает бит из IRR только тогда, когда прерывания разрешены и нет маски в IMM, так ведь? А если я разрешу прерывания, то произойдёт "рекурсивный" вызов обработчика. Можно, конечно, отследить вложенность, но это уже нагромождение пойдёт...
     
  9. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    267
    Адрес:
    Кольца Сатурна
    Я, кстати, сейчас проверил эту тему. Действительно, так и есть. При входе в прерывание регистр ISR = 0, делаю приличную паузу, отправляю EOI, снова делаю паузу, читаю ISR = 0.
    Соответственно, IRR = 0 на входе, IRR = 1 на выходе (как и предполагалось).
    Так что, Pavia, такой вариант не прокатит...

    Код (Text):
    1.  
    2. .MODEL Tiny
    3. .286
    4. .CODE
    5. ORG     100h
    6. Start:
    7. First:          push    offset Intercept
    8. Delay           proc
    9.                 mov     bx,50
    10. DelayBX:        loop    $
    11.                 dec     bx
    12.                 jnz     DelayBX
    13.                 ret
    14. Delay           endp
    15. Show            proc
    16.                 mov     al,00001010b    ; чтение IRR
    17.                 call    Show1
    18.                 mov     al,' '
    19.                 int     29h
    20.                 mov     al,00001011b    ; чтение ISR
    21.                 call    Show1
    22.                 mov     al,13
    23.                 int     29h
    24.                 mov     al,10
    25.                 int     29h
    26.                 ret
    27. Show            endp
    28. Show1           proc
    29.                 out     20h,al
    30.                 in      al,20h
    31.                 mov     cx,8
    32.                 xchg    dx,ax
    33.         @@2:    shl     dl,1
    34.                 mov     al,'0'
    35.                 adc     al,0
    36.                 int     29h
    37.                 loop    @@2
    38.                 ret
    39. Show1           endp
    40. Handler:
    41.                 cmp     byte ptr cs:First,0
    42.                 je      skip
    43.                 mov     byte ptr cs:First,0
    44.                 pusha
    45.                 call    Show
    46.                 call    Delay
    47.                 call    Show
    48.                 mov     al,20h
    49.                 out     20h,al          ; EOI
    50.                 inc     bx
    51.                 call    DelayBX
    52.                 call    Show
    53.                 popa
    54.         skip:
    55. RealInt:        db      0EAh
    56. RealAddr        dw      ?,?
    57. TSREnd          =       $
    58. ORG     $-4
    59. Intercept:
    60.                 mov     ax,3508h
    61.                 int     21h
    62.                 mov     RealAddr[0],bx
    63.                 mov     RealAddr[2],es
    64.                 mov     ah,25h
    65.                 lea     dx,Handler
    66.                 int     21h
    67.                 mov     ah,49h
    68.                 mov     es,ds:[2Ch]
    69.                 int     21h
    70.                 lea     dx,TSREnd
    71.                 int     27h
    72. END Start
    Выдаёт
    00000000 00000001
    00000001 00000001
    00000001 00000000

    В DOSBox, правда, но и в реале, думаю, то же самое будет...
     
    Последнее редактирование: 9 сен 2018