Прерывание STM32F030 GPIO

Попытка получить прерывание на A3, чтобы разбудить процессор от сна на символе rx, но он не срабатывает.

Что определяет, какое прерывание сработает на выводе GPIO? не могу найти в справочнике

static void EXTI0_1_IRQHandler_Config(void)
{
  GPIO_InitTypeDef   GPIO_InitStructure;

  /* Enable GPIOA clock */
  __HAL_RCC_GPIOA_CLK_ENABLE();

  GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStructure.Pull = GPIO_NOPULL;
  GPIO_InitStructure.Pin = GPIO_PIN_3;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Enable and set EXTI line 0 Interrupt to the lowest priority */
  HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
}

person OXO    schedule 18.04.2017    source источник


Ответы (1)


Функции прерывания (кратко) описаны в Главе 11 Прерывания и события, Раздел 11.1.3 Векторы прерываний и исключений.

введите здесь описание изображения

Итак, номер прерывания EXTI2HAL_GPIO_EXTI_IRQHandler()IRQn, и вы должны определить EXTI2HAL_GPIO_EXTI_IRQHandler()IRQHandler() для вызова HAL_GPIO_EXTI_IRQHandler().

Небольшая предыстория

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

Каждому запросу на прерывание присвоен номер прерывания, см. запись Position в таблице выше. Номер определяется аппаратно, символическое имя присваивается где-то в шапке машины.

typedef enum {
   [...]
   EXTI0_1_IRQn                = 5,      /*!< EXTI Line 0 and 1 Interrupt */
   EXTI2_3_IRQn                = 6,      /*!< EXTI Line 2 and 3 Interrupt */
   [...]
} IRQn_Type;

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

g_pfnVectors:
  .word  _estack
  .word  Reset_Handler
  .word  NMI_Handler
  .word  HardFault_Handler
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  SVC_Handler
  .word  0
  .word  0
  .word  PendSV_Handler
  .word  SysTick_Handler
  .word  WWDG_IRQHandler                   /* Window WatchDog              */
  .word  0                                 /* Reserved                     */
  .word  RTC_IRQHandler                    /* RTC through the EXTI line    */
  .word  FLASH_IRQHandler                  /* FLASH                        */
  .word  RCC_IRQHandler                    /* RCC                          */
  .word  EXTI0_1_IRQHandler                /* EXTI Line 0 and 1            */
  .word  EXTI2_3_IRQHandler                /* EXTI Line 2 and 3            */
...

Записи расположены в фиксированном порядке, так как аппаратное обеспечение заботится только о числовом адресе. Всякий раз, когда происходит событие EXTI2 или EXTI3 и включено IRQ6, происходит переход к адресу 0x00000058. Приведенная выше таблица гарантирует, что адрес EXTI2_3_IRQHandler() попадет в таблицу векторов 0x00000058.

Копая дальше в модуле запуска, мы находим это

.weak      EXTI0_1_IRQHandler
.thumb_set EXTI0_1_IRQHandler,Default_Handler

.weak      EXTI2_3_IRQHandler
.thumb_set EXTI2_3_IRQHandler,Default_Handler

и это

Default_Handler:
Infinite_Loop:
  b Infinite_Loop

Это означает, что если нет определения для EXTI0_1_IRQHandler() или EXTI2_3_IRQHandler(), то они вызывают бесконечный цикл, подходящий для отладки, но не более того. Чтобы использовать его, вы должны переопределить этот символ в своей программе. Если вы посмотрите на пример GPIO_EXTI, у него есть этот обработчик

void EXTI0_1_IRQHandler(void)
{
  HAL_GPIO_EXTI_IRQHandler(USER_BUTTON_PIN);
}

определено в stm32f0xx_it.c для вызова HAL_GPIO_EXTI_IRQHandler() при возникновении прерывания EXTI0. Если вы хотите воздействовать на EXTI3, у вас должна быть похожая функция

void EXTI2_3_IRQHandler(void)
{
  HAL_GPIO_EXTI_IRQHandler(3);
}

позвонить HAL_GPIO_EXTI_IRQHandler().

person followed Monica to Codidact    schedule 18.04.2017
comment
Не уверен насчет имени обработчика. HAL имеет следующее: - ` void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) { /* Обнаружено прерывание линии EXTI */ if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET) { __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); HAL_GPIO_EXTI_Callback(GPIO_Pin); } }` - person OXO; 18.04.2017
comment
Извините за форматирование предыдущего комментария. Я ошибаюсь, предполагая, что правильный способ - использовать обратный вызов прерывания? - person OXO; 18.04.2017
comment
Я почти уверен в имени обработчика. Вы должны установить соединение от аппаратного прерывания к функции обработчика HAL, см. расширенный ответ. - person followed Monica to Codidact; 18.04.2017