Где найти флаг прерывания для ядер платы Arduino сторонних производителей?

Этот вопрос может быть немного широким, но я столкнулся с очевидно классической проблемой с прерываниями Arduino, когда флаг нарастающего или спадающего фронта срабатывает до того, как технически возникает нарастающий или спадающий фронт до того, как вывод будет поднят на высокий уровень/ низкий уровень, и микроконтроллер «запоминает»; это событие произошло, и прерывание запускается в тот момент, когда оно привязывается к выводу. В данном случае я работаю с модулем Artemis от Sparkfun (используя Микроконтроллер Apollo3). Соответствующий код можно увидеть ниже:

#define SLEEP_INTERRUPT   4

void setup
{
    pinMode(SLEEP_INTERRUPT, INPUT);
#ifdef DEBUG
  Serial.print("About to attach interrupt");
#endif
  attachInterrupt(digitalPinToInterrupt(SLEEP_INTERRUPT), sleepModeSwitch, FALLING);
#ifdef DEBUG
  Serial.print("Interrupt attached");
#endif
}

void sleepModeSwitch()
{
#ifdef DEBUG
  Serial.print("Interrupt triggered! button status: "); Serial.println(digitalRead(SLEEP_INTERRUPT));
#endif
  if(sleep_mode_status == false)
  {
    goToSleep();
  }
  else
  {
    wakeUp();
  }
}

void goToSleep()
{
  sleep_mode_status = true;
#ifdef DEBUG
  Serial.println("Going to sleep");
  delay(50);  //Подождем, пока сериал завершится
  Serial.end(); //Выключение UART(ов)
#endif
  // выключаем светодиод.
  digitalWrite(LED_BUILTIN, LOW);

  // Остановить рекламу BLE.
  BLE.stopAdvertise() ;

  powerControlADC(false);
  
  for(int x = 0; x < 50; x++)
  {
    if(x != 4)
    {
      am_hal_gpio_pinconfig(x, g_AM_HAL_GPIO_DISABLE);
    }
  }
  //Выключение Flash, SRAM, кэша
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_CACHE); //Отключаем КЭШ
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_FLASH_512K); //Выключаем все, кроме понижения 512k
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_SRAM_64K_DTCM); //Выключаем все, кроме понижения 64к
  //am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); //Выключаем всю память (не восстанавливается)
  
  // // Включаем прерывания ядра.
  am_hal_interrupt_master_enable();
  
  // //Включаем прерывание таймера в NVIC.
  // NVIC_EnableIRQ(STIMER_CMPR6_IRQn);

  //Перейти в режим глубокого сна.
  am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}

void wakeUp()
{
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_MAX);
  
  // Снова включаем контакты UART0
  am_hal_gpio_pinconfig(48, g_AM_BSP_GPIO_COM_UART_TX);
  am_hal_gpio_pinconfig(49, g_AM_BSP_GPIO_COM_UART_RX);

  am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_UART0);

  initializeADC();

#ifdef DEBUG
  Serial.begin(115200);
  Serial.println("Waking up! Hello world!");
#endif
  deepSleepTimer = millis() ;
  sleep_mode_status = false;
}

Основываясь на моих исследованиях, решение этой проблемы — просто очистить флаг прерывания вручную, прежде чем прикреплять прерывание к нужному контакту. К сожалению, пока методы, которые я нашел, работают только для плат AVR, и я не уверен, где искать дополнительную информацию о том, как получить доступ к флагу прерывания в эскизе для стороннего ядра Arduino. . Есть ли у кого-нибудь предложения, с чего начать?

, 👍1

Обсуждение

Не уверен, что понимаю проблему, но похоже, что вы могли бы объявить изменчивое логическое значение isReady=false, а в верхней части обработчика сказать что-то вроде if(!isReady)return; и добавить isReady=true; после вашего вызова AttachInterrupt. Или, может быть, просто заглушить первый вызов с помощью if(!isReady){ isReady=true;return;} в обработчике., @dandavis

Можете ли вы исключить следующую возможную причину вашей проблемы? https://github.com/sparkfun/Arduino_Apollo3/issues/416, @6v6gt

@ 6v6gt Может ли подтягивающий резистор на 10 кОм устранить эту проблему?, @E.HP.S

Из этого отчета о проблеме следует, что, если это имеет отношение к вашему случаю, его решит внешнее подтягивание. Если вы вызываете AttachInterrupt() только в setup(), вы также можете сделать трюк (обходной путь) с глобальной переменной, скажем, endOfSetup и игнорировать любые вызовы ISR, где она не была установлена. Очистка, очистка флагов и т. д. перед использованием AttachInterrupt() очень распространена, поэтому, ИМХО, неправильно, что вам нужно идти под уровень абстракции, чтобы сделать это., @6v6gt

@ 6v6gt Я последовал совету из других источников (и от Дандависа) и сделал программное устранение дребезга с помощью функции millis(), чтобы прерывание не зашло слишком далеко, если оно вызывается слишком часто. Я также говорил об этом с кем-то на форуме Sparkfun, и мы, возможно, это исправили. Кажется, проблема была в файле commonInterrupt.cpp ядра. Не уверен, но я, по крайней мере, предотвратил это преждевременное прерывание, чтобы оно не испортило устройство, даже если я не уверен, что вообще остановил его работу. Все еще экспериментирую, @E.HP.S


1 ответ


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

1

Флаг нарастающего или спадающего фронта срабатывает до того, как технически возникает нарастающий или спадающий фронт перед тем, как штифт перейдет в высокий/низкий уровень, и микроконтроллер «запомнит»; это событие произошло, прерывание запускается в тот момент, когда оно прикрепляется к выводу

Не существует «технически» об этом. Это то, что должно произойти. Как только вы настроите прерывание (как вы это делаете в setup), процессор запомнит, что условие произошло, независимо от того, разрешены прерывания или нет.

Если вы хотите, чтобы прерывание обрабатывалось только после определенного момента, тогда да, вам следует очистить поле «прерывание произошло». флаг в MCU перед разрешением прерываний.

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

Я не уверен, где искать дополнительную информацию о том, как получить доступ к флагу прерывания в скетче для стороннего ядра Arduino

Техническое описание устройства на этом конкретном ядре?


Судя по техническим данным для Apollo3 Blue SoC :

6.3.2.15 Регистр INTLR

Прерывания мастера ввода-вывода: очищены

СМЕЩ: 0x00000228

АДРЕС ЭКЗЕМПЛЯРА 0: 0x5000C228

Запишите в этот регистр бит от 1, чтобы очистить статус прерывания, связанный с этим битом.

Однако у меня нет под рукой такого процессора, чтобы его протестировать.

,

Добавил ссылку на устройство и ссылку на даташит микроконтроллера, который в нем содержится. В данном случае это модуль Artemis от Sparkfun, содержащий SoC Apollo3 Blue SoC от Ambiq. И вы правы, я спрашивал об этом в более общем плане, намереваясь в целом узнать, где научиться очищать эти флаги, когда я работаю с другим микроконтроллером, с которым разбираюсь., @E.HP.S

@E.HP.S См. исправленный ответ., @Nick Gammon