Синхронизация флага прерывания изменения контакта на 1284P

Я хочу спросить о прерываниях смены контактов на чипе 1284P с использованием MightyCore. У меня вопрос о времени нескольких прерываний на одном порту. В частности, если я обслуживаю вектор PCINT и другой вывод порта меняется, пока я нахожусь в ISR, будет ли он генерировать другое прерывание сразу после того, которое я обслуживаю?

Когда я читаю таблицу данных, я вижу:

Бит 2 – PCIF2: Флаг прерывания изменения контакта 2 При изменении логики на любом Вывод PCINT[23:16] запускает запрос прерывания, PCIF2 будет установлен. Если бит I в SREG и бит PCIE2 в PCICR установлены, MCU будет перейти к соответствующему вектору прерывания. Флаг сбрасывается, когда выполняется процедура прерывания. Альтернативно, флаг может быть очищается путем записи в него «1».

Когда говорится, что флаг сбрасывается при выполнении процедуры прерывания, означает ли это, когда она входит в ISR или выходит из него? Если он находится в конце, могу ли я очистить флаг в первой строке ISR и разрешить еще одну смену контакта, чтобы установить его снова, даже если это произойдет до выхода из ISR?

, 👍5


1 ответ


Лучший ответ:

7

Когда он введен. Формулировка немного расплывчата, но я думаю, что «когда выполняется процедура прерывания»; означает начало исполнения. В противном случае можно легко пропустить несколько прерываний по смене контактов, в зависимости от того, сколько времени вы потратили на ISR.

Я предлагаю написать простой тест, который сохраняет где-нибудь значение флага при входе в ISR и проверяет, что он уже очищен.


Я написал этот тест для Uno (такая же базовая архитектура):

volatile bool firstTime = true;
volatile byte PCIFR_copy = 0;

ISR (PCINT0_vect)
 {
 // здесь обрабатываем прерывание смены контакта для D8-D13

 if (!firstTime)
   return;

 firstTime = false;
 PCIFR_copy = PCIFR;
 }  // конец PCINT0_vect

void setup ()
  {
  pinMode (9, INPUT_PULLUP);
  Serial.begin (115200);
  
  // прерывание по смене контакта (для D9)
  PCMSK0 |= bit (PCINT1);  // нужен контакт 9
  PCIFR  |= bit (PCIF0);   // очищаем все ожидающие прерывания
  PCICR  |= bit (PCIE0);   // включаем прерывания по смене контактов для D8-D13
  }  // конец настройки

void loop ()
  {
  Serial.print ("First time is ");
  Serial.print ((int) firstTime);
  Serial.print (", Flag is ");
  Serial.println ((int) PCIFR_copy);
  delay (1000);
  }  // конец цикла

Флаг PCIFR всегда был нулевым, даже после запуска прерывания смены контакта, что показывает, что он сбрасывался при входе в ISR.

сгенерирует ли оно еще одно прерывание сразу после того, которое я обслуживаю?

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


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


Кроме того, с точки зрения конструкции процессора имеет смысл сбрасывать флаг при входе в ISR. Помимо проблемы, заключающейся в том, что в противном случае прерывания могут быть пропущены, при входе в ISR процессор "знает"; какое прерывание оно обслуживает, потому что оно проверило бы флаг PCIFx, оно проверило бы флаг PCIEx (чтобы увидеть, должно ли прерывание быть выполнено), а затем изменило бы программный счетчик на соответствующий адрес для этого прерывания, после помещение счетчика текущей программы в стек. Это было бы логичное время для очистки этого флага, пока вся эта информация находится в «голове» процессора. так сказать.

В конце ISR код просто выполняет инструкцию RTI (возврат из прерывания), которая не связана с тем, из какого прерывания она возвращается. Таким образом, в этот момент будет сложно очистить флаг.

,

Спасибо за быстрый и подробный (и проверенный) ответ., @Delta_G