STM32 HAL 外部割り込みの基礎の基礎
おことわり・前提
- STM32CubeIDEを使った話をします.
- あくまで自分用のメモという目的が主.
- 逐次updateしたり追記したりがあるかもしれません.
本題
- 外部割り込みをするには
- GPIOをEXTI Interrupt modeにする.
- NVICで該当のEXTI Interruptをenableにする.
- これを忘れるとEXTIされないので注意.ハマりがち.
- 外部割り込みに限らずなんだけれども,割り込みの優先順位は適切につける.
- 例えば外部割り込みの中で
HAL_Delay()
を呼んだりしたいときはTime base: System tick timer
より外部割り込みの優先順位を下げないと処理が戻ってこなかったりする.
- 例えば外部割り込みの中で
実際のコードをみて割り込みの流れをみる
./Core/Src/stm32f0xx_it.c
/******************************************************************************/ /* STM32F0xx Peripheral Interrupt Handlers */ /* Add here the Interrupt Handlers for the used peripherals. */ /* For the available peripheral interrupt handler names, */ /* please refer to the startup file (startup_stm32f0xx.s). */ /******************************************************************************/ /** * @brief This function handles EXTI line 0 and 1 interrupts. */ void EXTI0_1_IRQHandler(void) { /* USER CODE BEGIN EXTI0_1_IRQn 0 */ /* USER CODE END EXTI0_1_IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); /* USER CODE BEGIN EXTI0_1_IRQn 1 */ /* USER CODE END EXTI0_1_IRQn 1 */ }
- 複数のEXTIピンを定義した場合でも同じ
HAL_GPIO_EXTI_IRQHandler()
がcallされる.
/******************************************************************************/ /* STM32F0xx Peripheral Interrupt Handlers */ /* Add here the Interrupt Handlers for the used peripherals. */ /* For the available peripheral interrupt handler names, */ /* please refer to the startup file (startup_stm32f0xx.s). */ /******************************************************************************/ /** * @brief This function handles EXTI line 0 and 1 interrupts. */ void EXTI0_1_IRQHandler(void) { /* USER CODE BEGIN EXTI0_1_IRQn 0 */ /* USER CODE END EXTI0_1_IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); /* USER CODE BEGIN EXTI0_1_IRQn 1 */ /* USER CODE END EXTI0_1_IRQn 1 */ } /** * @brief This function handles EXTI line 2 and 3 interrupts. */ void EXTI2_3_IRQHandler(void) { /* USER CODE BEGIN EXTI2_3_IRQn 0 */ /* USER CODE END EXTI2_3_IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); /* USER CODE BEGIN EXTI2_3_IRQn 1 */ /* USER CODE END EXTI2_3_IRQn 1 */ }
HAL_GPIO_EXTI_IRQHandler()
がcallされると割り込みビットの処理が実行され,HAL_GPIO_EXTI_Callback()
がcallされる.- これがユーザが実際に定義することを想定しているcallback functionである.
stm32f0xx_hal_gpio.c
ですでに__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
という形で定義されているが,__weak
指定子がついているので,ユーザがvoid HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
を別で定義した場合それが優先される.
./Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_gpio.c
/** * @brief Handle EXTI interrupt request. * @param GPIO_Pin Specifies the port pin connected to corresponding EXTI line. * @retval None */ void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) { /* EXTI line interrupt detected */ if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u) { __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); HAL_GPIO_EXTI_Callback(GPIO_Pin); } } /** * @brief EXTI line detection callback. * @param GPIO_Pin Specifies the port pin connected to corresponding EXTI line. * @retval None */ __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { /* Prevent unused argument(s) compilation warning */ UNUSED(GPIO_Pin); /* NOTE: This function should not be modified, when the callback is needed, the HAL_GPIO_EXTI_Callback could be implemented in the user file */ }
- ユーザは実際に
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
を定義して利用することができる.- 引数として
GPIO_PIN
が渡されるので,これを見てどのピンのEXTI割り込みかを判断する.
- 引数として
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ HAL_Delay(1); printf("EXTI callback called!\r\n"); if (GPIO_Pin == GPIO_PIN_3) printf("gpio3 pushed!\r\n"); if (GPIO_Pin == GPIO_PIN_1) printf("gpio1 released!\r\n"); }
- STM32 external interrupt and tick timer - Programmer Soughte
- EXTI内部で
HAL_Delay()
を叩くとすべての処理が停止することがあった. - これは割り込み優先度がすべて
0
となっていたため. HAL_Delay()
はsystick
を利用するためこの割り込みの優先度をあげ,EXTI
割り込みの優先度を下げる必要がある.- これにより無限ループによる処理停止が引き起こされない.
- EXTI内部で