Укажите какой флаг заставляет процессор не реагировать на поступающие к нему прерывания

Обновлено: 01.07.2024

Сегодня мы поговорим о прерываниях процессоров семейства x86 (-64). Подробнее под катом.
Прерывания — это как бы сигнал процессору, что надо прервать выполнение (их поэтому и назвали прерываниями) текущего кода и срочно сделать то, что указано в обработчике.

  • 0b0101: 32-битный гейт задачи, при появлении такого прерывания происходит хардверное переключение задачи (да-да, есть и такое, но его уже давно не используют)
  • 0b0110: 16-битный гейт прерывания
  • 0b0111: 16-битный гейт trap'a (я не знаю, как это перевести на русский язык, извините)
  • 0b1110: 32-битный гейт прерывания
  • 0b1111: 32-битный гейт trap'a
  1. Поиск вектора №0 в IDT.
  2. Сравнение уровня привилегий дескриптора и текущего уровня привилегий процессора.
  3. Если текущий уровень привилегий процессора меньше уровня привилегий дескриптора, то просто вызвать генеральную ошибку защиты и не вызывать прерывание.
  4. Происходит сохранение адреса возвращения, регистра (E)FLAGS и другой информации.
  5. Происходит переход на адрес, указанный в векторе №0 IDT.
  6. После выполнения обработчика инструкция iret возвращает управление прерванному коду.

Существует особый тип прерываний — IRQ (Interrupt ReQuest), или же аппаратные прерывания, но я буду их для краткости называть просто IRQ. Технически они почти не отличаются от любых других прерываний, но генерируются не процессором или самим кодом, а устройствами, подключенными к компьютеру. К примеру, IRQ №0 генерируется PIT (таймер с программируемым интервалом), IRQ 1 генерируется при нажатии клавиши на клавиатуре, а IRQ 12 — при действии с PS/2-мышью.


Еще есть так называемые программные прерывания. Их, как понятно из названия, программа должна вызывать сама — никто их за нее не вызывает. Таковыми являются, например, системные вызовы в некоторых системах. В Linux, например, они висят на векторе 0x80. Во многих хобби-ОС они тоже висят на векторе 0x80. Теперь немного отсебятины — я думаю, что сисвызовы сделаны в виде прерываний из-за того, что 1) их так очень легко вызывать, 2) их можно вызвать из любого кода, работающего в ОС — IDT-то одна на всю систему.
Информация взята с OSDev Wiki.

Регистр флагов содержит различные биты, отражающие текущее состояние процессора и частично управляющие его работой.

Содержание

История

Регистр флагов был уже в первом 16-разрядном микропроцессоре Intel — 8086. Он носил имя FLAGS и имел длину 16 бит. Появление микропроцессора 80286 добавило в регистр FLAGS бит NT и битовое поле IOPL, однако сам регистр оставался 16-разрядным.

С выходом микропроцессора 80386 регистр был расширен до 32 бит и стал называться EFLAGS. В нём появились ещё два дополнительных бита: VM и RF. В последующих поколениях 32-разрядных микропроцессоров были добавлены биты AC, VIF, VIP и ID. Тем не менее, сохранялась полная совместимость «снизу вверх»: любая старая программа, которая корректно работала с регистром EFLAGS, не модифицируя «неизвестные» ей биты, оставалась работоспособной и на последующих процессорах.

Расширение разрядности процессора до 64 бит, первоначально произведённое компанией AMD (технология AMD64) и позже скопированное Intel (EM64T), удвоило и размер регистра флагов, получившего название RFLAGS. Однако его старшая половина (биты с 32-го по 63-й включительно) пока не используется и является зарезервированной, поэтому формат «значащей» части RFLAGS полностью совпадает с форматом EFLAGS.

Назначение разрядов

Формат регистра EFLAGS выглядит следующим образом:

EFLAGS.jpg

Заметим, что все неиспользуемые биты равны нулю. Исключением является бит 1, который всегда имеет единичное значение.

Далее описывается назначение каждого бита, входящего в состав регистра флагов.

Флаги состояния

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

Флаги этой группы могут изменяться любыми программами с помощью команд, заносящих в регистр флагов новое значение (SAHF, POPF/POPFD/POPFQ).

CF Флаг переноса (бит 0). На самом деле он имеет разное назначение в зависимости от выполняемой инструкции. В арифметических операциях над целыми числами этот флаг, будучи установленным, показывает наличие переноса или заёма (это можно рассматривать как «беззнаковое переполнение»), а будучи сброшеннм — отсутствие переноса или заёма. Кроме того, этот флаг применяется в некоторых других инструкциях и тем или иным образом характеризует полученный результат. Подробно использование этого флага в каждой конкретной инструкции указывается в её описании
PF Флаг чётности (бит 2). Устанавливается, если младший байт результата содержит чётное число единичных битов, в противном случае сбрасывается
AF Флаг вспомогательного переноса (бит 4). Устанавливается при возникновении переноса или заёма из 4-ого раззряда в 3-ий разряд. Сбрасывается при отсутствии такового. Используется командами десятичной коррекции.
ZF Флаг нуля (бит 6). Устанавливается при получении нулевого результата, сбрасывается в противном случае.
SF Флаг знака (бит 7). Устанавливается, если в результате операции получено отрицательное число, т.е. если старший разряд результата равен единице. В противном случае сбрасывается
OF Флаг переполнения (бит 11). Устанавливается, если в результате арифметической операции зафиксировано знаковое переполнение, то есть если результат, рассматриваемый как число со знаком, не помещается в операнд-приёмник. Если знакового переполнения нет, этот флаг сбрасывается

Флаг направления

Этот флаг может изменяться любыми программами с помощью специальных инструкций CLD и STD, а также загрузкой нового содержимого регистра флагов.

Флаг прерываний ( IF ) представляет собой флаг , система немного в архитектуре x86 «ы регистра флагов , который определяет , является ли центральный процессор (ЦП) будет реагировать на маскируемых аппаратных прерываний . [1]

Бит, который является битом 9 регистра FLAGS, может быть установлен или сброшен программами с достаточными привилегиями, как обычно определяется операционной системой . Если этот флаг установлен 1 , будут обрабатываться маскируемые аппаратные прерывания. Если этот параметр не установлен (установлен в 0 ), такие прерывания будут игнорироваться. IF не влияет на обработку немаскируемых прерываний (NMI) или программных прерываний, генерируемых инструкцией INT .

Флаг может быть установлен или сброшен с помощью CLI ( Cl уха I nterrupts), STI ( S е т I nterrupts) и POPF ( Поп F LAGS) инструкции .

CLI очищает IF (устанавливается в 0), а STI устанавливает IF в 1. POPF выталкивает 16 битов из стека в регистр FLAGS , что означает, что IF будет устанавливаться или очищаться на основе девятого бита на вершине стека. [1]

Во всех трех случаях только привилегированные приложения (обычно ядро ОС ) могут изменять IF. Обратите внимание, что это относится только к коду защищенного режима . ( Код реального режима всегда может изменять IF.)

CLI и STI - это привилегированные инструкции, которые вызывают общий сбой защиты, если непривилегированное приложение пытается его выполнить, в то время как POPF просто не будет изменять флаг IF, если приложение непривилегированное.

Уровень привилегий, необходимый для выполнения инструкции CLI или STI или установки IF с помощью POPF, определяется IOPL (уровень привилегий ввода-вывода) в EFLAGS. Если IOPL установлен, например, на 2, любая программа, работающая только в кольце 0, может выполнять CLI. Большинство современных операционных систем устанавливают IOPL равным 0, поэтому только ядро ​​может выполнять CLI / STI. Причина этого в том, что, поскольку очистка IF заставит процессор игнорировать все прерывания, ядро ​​может никогда не вернуть управление, если оно не будет снова установлено в 1.

Старые программы DOS

Некоторые старые программы DOS , которые используют расширитель DOS в защищенном режиме и устанавливают свои собственные обработчики прерываний (обычно игры), используют инструкцию CLI в обработчиках для отключения прерываний и либо POPF (после соответствующего PUSHF), либо IRET (который восстанавливает флаги из стека). как часть его эффектов), чтобы восстановить его. Это работает, если программа была запущена в реальном режиме, но вызывает проблемы, когда такие программы запускаются в контейнере на основе DPMI в современных операционных системах (например, NTVDM под Windows NT или новее). Поскольку CLI является привилегированной инструкцией, она вызывает ошибку в операционной системе, когда программа пытается ее использовать. Затем ОС обычно прекращает доставлять прерывания программе до тех пор, пока программа не выполнит STI (что может вызвать другую ошибку). Однако инструкция POPF не является привилегированной и просто не может восстановить IF без уведомления. В результате ОС перестает доставлять прерывания программе, которая затем зависает. Программы DOS, которые не используют расширитель защищенного режима, не страдают от этой проблемы, поскольку они выполняются в режиме V86, где POPF действительно вызывает ошибку.

Есть несколько удовлетворительных решений по этому вопросу. Обычно невозможно изменить программу, поскольку исходный код обычно недоступен, а в потоке инструкций нет места для введения STI без массового редактирования на уровне сборки. Удаление интерфейса командной строки из программы или полное игнорирование интерфейса командной строки хостом V86 может вызвать другие ошибки, если обработчики прерываний гостя не являются безопасными для повторного входа (хотя при выполнении на современном процессоре они обычно выполняются достаточно быстро, чтобы избежать перекрытия прерываний).

CLI обычно используется как механизм синхронизации в однопроцессорных системах. Например, интерфейс командной строки используется в операционных системах для отключения прерываний, чтобы код ядра (обычно драйвер ) мог избежать состояния гонки с помощью обработчика прерывания . Обратите внимание, что CLI влияет только на флаг прерывания для процессора, на котором он выполняется; в многопроцессорных системах выполнение инструкции CLI не отключает прерывания на других процессорах. Таким образом, состояние гонки драйвера / обработчика прерываний все еще может возникать, потому что другие процессоры могут обслуживать прерывания и выполнять обработчик прерываний, вызывающих нарушение. Для этих систем другие механизмы синхронизации, такие как блокировки, должны использоваться в дополнение к CLI / STI, чтобы предотвратить все состояния гонки.

Поскольку инструкция HLT останавливается до тех пор, пока не произойдет прерывание, комбинация CLI, за которой следует HLT, обычно используется для намеренного зависания компьютера.

Инструкция STI разрешает прерывания, устанавливая IF.

Одна интересная особенность инструкции STI заключается в том, что, в отличие от интерфейса командной строки, который действует немедленно, прерывания фактически не разрешаются до тех пор, пока не будет выполнена инструкция, следующая сразу за STI. Одним из побочных эффектов этого может быть IF = 0, тогда выполнение инструкции CLI сразу после инструкции STI означает, что прерывания никогда не распознаются. Команда STI устанавливает флаг IF, но прерывания не проверяются до тех пор, пока не будет выполнена следующая инструкция, которая в данном случае будет CLI, которая вступает в силу немедленно. Такое поведение существует, поэтому процессор, который постоянно принимает прерывания, все еще может продвигаться вперед. См. Подробности в руководствах IA-32 .

В данной статье описываются прерывания GPIO, включая примеры прерываний и их различных функций. Это продолжение предыдущей статьи, в которой объясняются концепции параллелизма и прерываний для микроконтроллеров.

Что делает периферийное устройство GPIO?

Периферийное устройство GPIO способно обнаруживать (или «определять») четыре вещи: является ли состояние на выводе 1 или 0, и изменилось ли состояние с 0 на 1 или с 1 на 0.

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

Рисунок 1 Использование вывода GPIO и геркона для определения состояния двери (открыта или закрыта) и изменений состояния.

Рисунок 1 – Использование вывода GPIO и геркона для определения состояния двери (открыта или закрыта) и изменений состояния.

Сначала я объясню, как работают прерывания, предполагая, что всё настроено правильно, а затем мы рассмотрим различные составляющие, которые необходимо правильно настроить для работы прерывания.

Флаг периферийного прерывания

Давайте предположим, что аналогично предыдущему примеру, событие, которое мы пытаемся обнаружить, – это изменение состояния на выводе с 1 на 0. Внутри периферийного устройства GPIO будет находиться аппаратное обеспечение, которое обнаруживает это изменение и показывает, что это изменение произошло, установив так называемый флаг прерывания для этого вывода в 1.

Это показано на рисунке 2.

Рисунок 2 Установка флага прерывания вывода GPIO после обнаружения события, которое должно генерировать прерывание.

Рисунок 2 – Установка флага прерывания вывода GPIO после обнаружения события, которое должно генерировать прерывание.

Контроллер прерываний и флаги контроллера прерываний

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

Как правило, контроллер прерываний имеет список возможных прерываний, а также их соответствующий приоритет. Наше периферийное устройство GPIO может иметь в списке, хранящемся в контроллере прерываний, одно или несколько прерываний.

Например, у CC2544 есть группа из восьми выводов, которые являются частью GPIO, которая называется PORT0 . Каждый вывод обозначен как P0_0 , P0_1 и т. д. до P0_7 . Хотя каждый вывод имеет свой собственный флаг прерывания, у контроллера прерываний есть только одно прерывание для всего порта, P0INT . Всякий раз, когда в периферийном устройстве GPIO устанавливаются какие-либо флаги выводов, в контроллере прерываний также устанавливается флаг для всего порта.

Обратите внимание, что здесь есть два флага, один – флаг для конкретного вывода, который является частью периферийного устройства GPIO, а другой – флаг прерывания для всего порта, который является частью контроллера прерываний. Это показано на рисунке 3.

Рисунок 3 Установка флага прерывания вывода GPIO и флага прерывания для GPIO в контроллере прерываний после обнаружения события, которое должно генерировать прерывание.

Рисунок 3 – Установка флага прерывания вывода GPIO и флага прерывания для GPIO в контроллере прерываний после обнаружения события, которое должно генерировать прерывание.

Таблица векторов

Многие микроконтроллеры используют для прерываний так называемый векторный подход. При таком подходе в памяти имеется таблица векторов, в которой для каждого прерывания указывается адрес, по которому находится обработчик прерывания (ISR), который должен выполнить центральный процессор (CPU) для этого конкретного прерывания. Этот адрес обычно называется вектором прерывания.

Например, у CC2544, который использует архитектуру микроконтроллера 8501, вектор прерывания для PORT0 является адресом памяти 0x6B . Когда контроллер прерываний сообщает CPU, что есть прерывание от определенного вектора, CPU выполняет некоторое сохранение и затем начинает выполнять обработчик прерывания из этого вектора прерывания. Это показано на рисунке 4.

Рисунок 4 Выполнение обработчика прерывания для вектора прерывания GPIO после установки флага прерывания вывода GPIO и флага прерывания для GPIO в контроллере прерываний после обнаружения события, которое должно генерировать прерывание.

Рисунок 4 – Выполнение обработчика прерывания для вектора прерывания GPIO после установки флага прерывания вывода GPIO и флага прерывания для GPIO в контроллере прерываний после обнаружения события, которое должно генерировать прерывание.

Настройка поведения прерываний

Периферийные устройства, такие как GPIO, обычно дают вам возможность настроить, какие события периферийного устройства будут генерировать прерывание. Для GPIO типовыми являются варианты, когда состояние изменяется с 0 на 1, когда состояние изменяется с 1 на 0, любое изменение состояния (т. е. с 0 на 1 или с 1 на 0, не имеет значения какое), или когда состояние остается в 1 или 0.

В зависимости от микроконтроллера это можно сделать для каждого вывода или для всех выводов порта. ATmega328P имеет два вывода, которые вы можете настроить индивидуально. Другие выводы GPIO по умолчанию обнаруживают любые изменения на выводе (с 0 на 1 или с 1 на 0). В предыдущей статье, где мы иллюстрировали работу прерываний, мы предполагали, что вывод был настроен на обнаружение изменений только с 1 на 0.

Кроме того, некоторые микроконтроллеры требуют, чтобы для установки флага прерывания при возникновении события интересующий нас вывод был сконфигурирован в качестве входа (например, CC2544). Другие (например, ATmega328P) установят флаг независимо от того, сконфигурирован ли вывод в качестве выхода или входа.

Маскирование прерываний

Общим термином, используемым для описания включения и отключения прерываний, является «маскирование». Как правило, существуют различные уровни, на которых прерывания могут быть отключены. Процессор может включать или отключать все прерывания, хотя обычно существуют критические прерывания, называемые немаскируемыми прерываниями, которые никогда не отключаются.

Отключение всех прерываний в CPU по существу останавливает связь между контроллером прерываний и CPU. Это означает, что при обнаружении события будут установлены и флаг вывода в периферийном устройстве GPIO, и флаг соответствующего прерывания в контроллере; однако центральный процессор не получит запрос прерывания. Это показано на рисунке 5.

Рисунок 5 Глобальное отключение прерываний на уровне процессора.

Рисунок 5 – Глобальное отключение прерываний на уровне процессора.

Другой уровень, на котором можно маскировать прерывания, – это уровень контроллера прерываний. Здесь мы можем включить или отключить определенное прерывание внутри контроллера.

Пример прерывания CC2544

Будет полезен конкретный пример. Допустим, мы используем CC2544, и мы отключили PORT0 . Допустим, вывод P0_3 изменил свое состояние, и поэтому в периферийном устройстве GPIO был установлен его флаг. В контроллере прерываний также будет установлен флаг прерывания PORT0 , но контроллер прерываний проигнорирует его.

Это отличается от того, как центральный процессор отключает все прерывания, потому что контроллер прерываний все еще находится на связи с CPU. Так, если, например, для PORT1 разрешено прерывание, и на выводе P1_2 изменилось состояние так, чтобы его флаг был установлен на периферийном устройстве GPIO, а также был установлен флаг прерывания PORT1 , контроллер прерываний прервет CPU для обработки этого прерывания.

Случай, когда контроллер прерываний игнорирует флаг вектора прерывания, показан на рисунке 6.

Рисунок 6 Маскирование прерываний на уровне контроллера прерываний.

Рисунок 6 – Маскирование прерываний на уровне контроллера прерываний.

Большинство микроконтроллеров также позволяют маскировать прерывания на уровне периферийного устройства. Здесь мы можем включить или отключить прерывание для определенного вывода периферийного устройства GPIO.

Во всех микроконтроллерах, с которыми я сталкивался, флаг прерывания устанавливается всегда, когда на периферийном устройстве GPIO происходит искомое событие, независимо от того, включено или отключено прерывание для этого вывода. Например, если вывод P0_3 изменил свое значение так, как мы ищем, его флаг будет установлен в периферийном устройстве GPIO. Однако периферийное устройство GPIO не будет предупреждать контроллер прерываний об этом, поэтому флаг прерывания PORT0 в контроллере прерываний не будет установлен, и, поскольку нам необходимо установить этот флаг для прерывания CPU, прерывание не произойдет. Это показано на рисунке 7.

Рисунок 7 Маскирование прерываний на уровне периферийного устрйства GPIO

Рисунок 7 – Маскирование прерываний на уровне периферийного устройства GPIO.

Когда прерывание маскируется, событие всё равно обнаруживается. Процессор просто не реагирует на него. Если флаг прерывания не сброшен, и прерывание полностью не маскируется, тогда CPU будет реагировать на него, если оно удовлетворяет всем другим условиям (кроме маскирования) для его выполнения. Прерывание, которое было обнаружено и ожидает, пока CPU выполнит его обработку, обычно называется ожидающим прерыванием.

На рисунке 8 показан случай, когда прерывание находится в состоянии ожидания, а затем не маскируется.

Рисунок 8 Маскирование прерываний и снятие маскирования на уровне GPIO, при условии, что прерывание не маскируется на уровне контроллера прерываний и CPU.

Рисунок 8 – Маскирование прерываний и снятие маскирования на уровне GPIO, при условии, что прерывание не маскируется на уровне контроллера прерываний и CPU.

Напомним, чтобы размаскировать прерывание, чтобы процессор мог на него реагировать, когда все другие условия для прерывания выполнены, необходимо, чтобы:

  1. прерывание должно быть разрешено в периферийном устройстве (если применимо);
  2. также должно быть разрешено соответствующее ему прерывание в контроллере прерываний;
  3. все прерывания должны быть разрешены центральным процессором (т. е. должна быть разрешена связь между центральным процессором и контроллером прерываний для маскируемых прерываний).

Приоритеты прерываний

Иногда два или более события, которые приводят к прерываниям, происходят одновременно. Когда это происходит, поскольку CPU может обрабатывать только одно прерывание за раз, контроллеру прерываний нужен механизм, чтобы знать, какое из них должно идти первым, вторым и т. д. Контроллер прерываний обычно предоставляет конфигурацию, называемую приоритетом, которая позволяет пользователю через свой код указывать, какие прерывания имеют более высокий приоритет, а какие – более низкий. Большинство микроконтроллеров также предоставляет настройки по умолчанию для каждого прерывания.

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

  1. Флаги прерываний с более высоким и более низким приоритетами устанавливаются одновременно. Процессор выполняет прерывание с более высоким приоритетом, а затем прерывание с более низким приоритетом (поскольку его флаг все еще ожидает обработки, пока выполняется прерывание с более высоким приоритетом).
  2. Флаг прерывания с более высоким приоритетом устанавливается после того, как CPU начал обрабатывать прерывание с более низким приоритетом. Прерывание с более высоким приоритетом вытесняет прерывание с более низким приоритетом, и CPU выполняет обработчик для прерывания с более высоким приоритетом до полного завершения, прежде чем возобновить выполнение обработчика для прерывания с более низким приоритетом. Обратите внимание, что CPU возобновляет выполнение обработчика для прерывания с более низким приоритетом, даже если его флаг всё еще не установлен к моменту, когда он выполнит обработчик для высокоприоритетного прерывания. Это связано с тем, что после выполнения обработчика, если код не мешает нормальной обработке прерывания, CPU всегда возвращается к тому состоянию, в котором он находился до того, как начал выполнять обработчик. Это состояние, к которому он возвращается, может быть другим обработчиком прерывания.
  3. Флаг прерывания с более низким приоритетом устанавливается после флага с более высоким приоритетом. Поскольку прерывания с более низким приоритетом не могут вытеснять прерывания с более высоким приоритетом, CPU выполняет обработку прерывание с более высоким приоритетом до полного завершения, прежде чем реагировать на прерывание с более низким приоритетом.

Проверка и очистка флагов прерываний

Ранее мы видели, что для некоторых микроконтроллеров, таких как CC2544, когда код обработчика прерывания начинает выполняться, мы знаем только, какой порт вызвал прерывание, но не конкретный вывод. Например, если P0_3 изменяет свое значение, его флаг будет установлен внутри периферийного устройства GPIO, но центральный процессор выполняет обработчик прерывания только в ответ на флаг прерывания PORT0 от контроллера прерываний. Проверка флагов прерываний периферийного устройства GPIO внутри обработчика прерывания говорит нам, какой конкретный вывод вызвал прерывание, чтобы мы могли реагировать соответствующим образом.

Поскольку флаг прерывания указывает, что искомое событие произошло, пока установлен флаг прерывания, CPU будет реагировать на прерывание каждый раз, когда у него есть такая возможность. Например, допустим, что P0_3 изменил состояние только один раз и заставил установить его флаг прерывания. Если мы оставим флаг установленным, то после того, как CPU запустит обработчик прерывания, связанный с PORT0 , он всё равно будет думать, что есть новое прерывание, поэтому он снова запустит обработчик.

Чтобы избежать этого, нам нужно очистить флаг прерывания. Иногда флаг прерывания автоматически очищается процессором, когда он запускает обработчик прерывания; в остальных случаях вы должны очистить флаг самостоятельно. Техническая документация на микроконтроллер позволит вам узнать, что делать в этом случае. Например, CC2544 автоматически не сбрасывает флаг для прерываний выводов, а ATmega328P – сбрасывает его автоматически. Если вам нужно очистить прерывание самостоятельно, это обычно первое, что вы делаете в коде обработчика, обычно сразу после выяснения того, прерывание по какому выводу вызвало выполнение обработчика.

Резюме. Получение прерывания GPIO для работы

Обобщим всё описанное выше. Чтобы прерывание GPIO работало с вашим кодом, вы должны:

Читайте также: