На главную
Подписка
Новости










Главная / MS-DOS / MS-DOS. РУКОВОДСТВО РАЗРАБОТЧИКА / Глава 8 / Обработка прерываний последовательного порта Сделать домашней страницей Добавить в избранное Написать писмо

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Обработка прерываний последовательного порта

Наш обработчик, s_inthndlr, будет вызван при генерации последовательным портом прерывания. Мы должны немедленно разрешить прием системой последующих прерываний таким образом, чтобы другие приоритетные задачи (такие как таймер) могли обрабатываться микропроцессором.


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


Так как последовательный порт способен генерировать прерывание в то время, пока Вы обрабатываете другое, необходимо проверять бит 0 (последний значащий бит) IIR на это условие. Если этот бит равен нулю, то имеется другое прерывание и его следует обработать. С другой стороны, если значение бита равно единице, очередные прерывания отсутствуют. В этом случае Вы должны направить контроллеру 8259A сигнал "конец прерывания" и выйти из обработчика. Таким образом, обработчик представляет собой бесконечный цикл, который продолжает обрабатывать последовательные прерывания до тех пор, пока не прекратится их поступление. В Microsoft C 5.0 обработчик может быть реализован как


         void interrupt far s_inthndlr(void)
         {
             int c;
             register int int_id, intmask;

         /* прерывания разрешаются немедленно */
             _enable();

             while (TRUE)
             {
         /* чтение регистра идентификации прерываний, IIR */
                  int_id = inp(IIR);
                  if (bit0(int_id) == 1)
                  {
         /* если бит 0 равен 1, тогда прерывания не поступают. послать
          * сигнал конец прерывания программируемому контроллеру
          * прерываний 8259A и затем вернуться.
          */
                      outp(P8259_0, END_OF_INT);
                      return;
                  }
         /* если есть прерывание получения данных, разрешить прерывания
          * для "свободен регистр хранения передачи"
          */
                  if (int_id) >= RXDATAREADY)
                                    turnon_int(THEREINT,intmask);

         /* обработать прерывание в соответствии с идентификатором.
          * Следующий список составлен согласно возрастанию приоритета.
          */
                 switch (int_id)
                 {
                    case MDMSTATUS:  /* состояние готовности модема */
                                       .
                                       .
                                       .
                                      break;
                    case TXREGEMPTY:  /* послать символ */
                                       .
                                       .
                                       .
                                      break;
                    case RXDATAREADY: /* читать символ */
                                       .
                                       .
                                       .
                                      break;
                    case RLINESTATUS: /* читать состояние линии */
                                       .
                                       .
                                       .
                                      break;
         /* пропустить, если идентификатор не является одним из
          * перечисленных */
                 }
             }
         }

Обратите внимание, что мы воспользовались ключевым словом interrupt,имеющемся в Microsoft C 5.0 и позволяющем писать обработчик на языке Си. Это ключевое слово используется как спецификатор функции, которую Вы желаете установить в качестве обработчика прерываний определенного номера прерывания. При трансляции функции с атрибутом interrupt компилятор генерирует код для первоначального помещения в стек регистров AX, CX, DX, BX, SP, BP, SP, SI, DI, DS и ES. Затем он устанавливает регистр DS в режим ссылки на сегмент данных указанной функции. После этой начальной последовательности следует код функции. В заключении компилятор использует команду IRET вместо обычной команды RET для выхода из функции. Данный пример является типичным для использования атрибута interrupt. В компиляторе Turbo C также имеется это ключевое слово, но помещение регистров в стек происходит в другом порядке.


Когда Вы пишете обработчик прерываний на языке Си, то необходимо соблюдать такие же предосторожности, как и при написании обработчиков на языке ассемблера. Например, Вы не должны использовать какую-либо библиотечную подпрограмму, вызывающую функцию DOS (доступ к ним осуществляется посредством команды прерывания 21h). Такими функциями в языке Си являются подпрограммы ввода/вывода файлов. С другой стороны, подпрограммы, находящиеся в категории подпрограмм манипулирования строками, хранятся в функции interrupt.


НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Hosted by uCoz