Синхронизация флага прерывания изменения контакта на 1284P
Я хочу спросить о прерываниях смены контактов на чипе 1284P с использованием MightyCore. У меня вопрос о времени нескольких прерываний на одном порту. В частности, если я обслуживаю вектор PCINT и другой вывод порта меняется, пока я нахожусь в ISR, будет ли он генерировать другое прерывание сразу после того, которое я обслуживаю?
Когда я читаю таблицу данных, я вижу:
Бит 2 – PCIF2: Флаг прерывания изменения контакта 2 При изменении логики на любом Вывод PCINT[23:16] запускает запрос прерывания, PCIF2 будет установлен. Если бит I в SREG и бит PCIE2 в PCICR установлены, MCU будет перейти к соответствующему вектору прерывания. Флаг сбрасывается, когда выполняется процедура прерывания. Альтернативно, флаг может быть очищается путем записи в него «1».
Когда говорится, что флаг сбрасывается при выполнении процедуры прерывания, означает ли это, когда она входит в ISR или выходит из него? Если он находится в конце, могу ли я очистить флаг в первой строке ISR и разрешить еще одну смену контакта, чтобы установить его снова, даже если это произойдет до выхода из ISR?
@Delta_G, 👍5
1 ответ
Лучший ответ:
Когда он введен. Формулировка немного расплывчата, но я думаю, что «когда выполняется процедура прерывания»; означает начало исполнения. В противном случае можно легко пропустить несколько прерываний по смене контактов, в зависимости от того, сколько времени вы потратили на 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 (возврат из прерывания), которая не связана с тем, из какого прерывания она возвращается. Таким образом, в этот момент будет сложно очистить флаг.
- Прерывание переполнения таймера AVR не работает
- Заставить TCNT оставаться ниже OCRxA на ATmega328P
- Проверка прерываний
- Atmega собирает и ретранслирует вызовы прерывания
- Использование millis() и micros() внутри процедуры прерывания
- Подсчет импульсов с прерыванием
- В чем разница/связь между Arduino и AVR?
- Устранение дребезга кнопки с помощью прерывания
Спасибо за быстрый и подробный (и проверенный) ответ., @Delta_G