2 ******************************************************************************
\r
3 * @file stm32l4xx_hal_exti.c
\r
4 * @author MCD Application Team
\r
5 * @brief EXTI HAL module driver.
\r
6 * This file provides firmware functions to manage the following
\r
7 * functionalities of the Extended Interrupts and events controller (EXTI) peripheral:
\r
8 * + Initialization and de-initialization functions
\r
9 * + IO operation functions
\r
12 ==============================================================================
\r
13 ##### EXTI Peripheral features #####
\r
14 ==============================================================================
\r
16 (+) Each Exti line can be configured within this driver.
\r
18 (+) Exti line can be configured in 3 different modes
\r
23 (+) Configurable Exti lines can be configured with 3 different triggers
\r
28 (+) When set in interrupt mode, configurable Exti lines have two different
\r
29 interrupts pending registers which allow to distinguish which transition
\r
31 (++) Rising edge pending interrupt
\r
34 (+) Exti lines 0 to 15 are linked to gpio pin number 0 to 15. Gpio port can
\r
35 be selected through multiplexer.
\r
37 ##### How to use this driver #####
\r
38 ==============================================================================
\r
41 (#) Configure the EXTI line using HAL_EXTI_SetConfigLine().
\r
42 (++) Choose the interrupt line number by setting "Line" member from
\r
43 EXTI_ConfigTypeDef structure.
\r
44 (++) Configure the interrupt and/or event mode using "Mode" member from
\r
45 EXTI_ConfigTypeDef structure.
\r
46 (++) For configurable lines, configure rising and/or falling trigger
\r
47 "Trigger" member from EXTI_ConfigTypeDef structure.
\r
48 (++) For Exti lines linked to gpio, choose gpio port using "GPIOSel"
\r
49 member from GPIO_InitTypeDef structure.
\r
51 (#) Get current Exti configuration of a dedicated line using
\r
52 HAL_EXTI_GetConfigLine().
\r
53 (++) Provide exiting handle as parameter.
\r
54 (++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
\r
56 (#) Clear Exti configuration of a dedicated line using HAL_EXTI_GetConfigLine().
\r
57 (++) Provide exiting handle as parameter.
\r
59 (#) Register callback to treat Exti interrupts using HAL_EXTI_RegisterCallback().
\r
60 (++) Provide exiting handle as first parameter.
\r
61 (++) Provide which callback will be registered using one value from
\r
62 EXTI_CallbackIDTypeDef.
\r
63 (++) Provide callback function pointer.
\r
65 (#) Get interrupt pending bit using HAL_EXTI_GetPending().
\r
67 (#) Clear interrupt pending bit using HAL_EXTI_GetPending().
\r
69 (#) Generate software interrupt using HAL_EXTI_GenerateSWI().
\r
72 ******************************************************************************
\r
75 * <h2><center>© Copyright (c) 2018 STMicroelectronics.
\r
76 * All rights reserved.</center></h2>
\r
78 * This software component is licensed by ST under BSD 3-Clause license,
\r
79 * the "License"; You may not use this file except in compliance with the
\r
80 * License. You may obtain a copy of the License at:
\r
81 * opensource.org/licenses/BSD-3-Clause
\r
83 ******************************************************************************
\r
86 /* Includes ------------------------------------------------------------------*/
\r
87 #include "stm32l4xx_hal.h"
\r
89 /** @addtogroup STM32L4xx_HAL_Driver
\r
93 /** @addtogroup EXTI
\r
96 /** MISRA C:2012 deviation rule has been granted for following rule:
\r
97 * Rule-18.1_b - Medium: Array `EXTICR' 1st subscript interval [0,7] may be out
\r
98 * of bounds [0,3] in following API :
\r
99 * HAL_EXTI_SetConfigLine
\r
100 * HAL_EXTI_GetConfigLine
\r
101 * HAL_EXTI_ClearConfigLine
\r
104 #ifdef HAL_EXTI_MODULE_ENABLED
\r
106 /* Private typedef -----------------------------------------------------------*/
\r
107 /* Private defines ------------------------------------------------------------*/
\r
108 /** @defgroup EXTI_Private_Constants EXTI Private Constants
\r
111 #define EXTI_MODE_OFFSET 0x08u /* 0x20: offset between MCU IMR/EMR registers */
\r
112 #define EXTI_CONFIG_OFFSET 0x08u /* 0x20: offset between MCU Rising/Falling configuration registers */
\r
117 /* Private macros ------------------------------------------------------------*/
\r
118 /* Private variables ---------------------------------------------------------*/
\r
119 /* Private function prototypes -----------------------------------------------*/
\r
120 /* Exported functions --------------------------------------------------------*/
\r
122 /** @addtogroup EXTI_Exported_Functions
\r
126 /** @addtogroup EXTI_Exported_Functions_Group1
\r
127 * @brief Configuration functions
\r
130 ===============================================================================
\r
131 ##### Configuration functions #####
\r
132 ===============================================================================
\r
139 * @brief Set configuration of a dedicated Exti line.
\r
140 * @param hexti Exti handle.
\r
141 * @param pExtiConfig Pointer on EXTI configuration to be set.
\r
142 * @retval HAL Status.
\r
144 HAL_StatusTypeDef HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
\r
146 __IO uint32_t *regaddr;
\r
152 /* Check null pointer */
\r
153 if ((hexti == NULL) || (pExtiConfig == NULL))
\r
158 /* Check parameters */
\r
159 assert_param(IS_EXTI_LINE(pExtiConfig->Line));
\r
160 assert_param(IS_EXTI_MODE(pExtiConfig->Mode));
\r
162 /* Assign line number to handle */
\r
163 hexti->Line = pExtiConfig->Line;
\r
165 /* Compute line register offset and line mask */
\r
166 offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
\r
167 linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
\r
168 maskline = (1uL << linepos);
\r
170 /* Configure triggers for configurable lines */
\r
171 if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
\r
173 assert_param(IS_EXTI_TRIGGER(pExtiConfig->Trigger));
\r
175 /* Configure rising trigger */
\r
176 regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
\r
179 /* Mask or set line */
\r
180 if ((pExtiConfig->Trigger & EXTI_TRIGGER_RISING) != 0x00u)
\r
182 regval |= maskline;
\r
186 regval &= ~maskline;
\r
189 /* Store rising trigger mode */
\r
192 /* Configure falling trigger */
\r
193 regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
\r
196 /* Mask or set line */
\r
197 if ((pExtiConfig->Trigger & EXTI_TRIGGER_FALLING) != 0x00u)
\r
199 regval |= maskline;
\r
203 regval &= ~maskline;
\r
206 /* Store falling trigger mode */
\r
209 /* Configure gpio port selection in case of gpio exti line */
\r
210 if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
\r
212 assert_param(IS_EXTI_GPIO_PORT(pExtiConfig->GPIOSel));
\r
213 assert_param(IS_EXTI_GPIO_PIN(linepos));
\r
215 regval = SYSCFG->EXTICR[linepos >> 2u];
\r
216 regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
\r
217 regval |= (pExtiConfig->GPIOSel << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
\r
218 SYSCFG->EXTICR[linepos >> 2u] = regval;
\r
222 /* Configure interrupt mode : read current mode */
\r
223 regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
\r
226 /* Mask or set line */
\r
227 if ((pExtiConfig->Mode & EXTI_MODE_INTERRUPT) != 0x00u)
\r
229 regval |= maskline;
\r
233 regval &= ~maskline;
\r
236 /* Store interrupt mode */
\r
239 /* The event mode cannot be configured if the line does not support it */
\r
240 assert_param(((pExtiConfig->Line & EXTI_EVENT) == EXTI_EVENT) || ((pExtiConfig->Mode & EXTI_MODE_EVENT) != EXTI_MODE_EVENT));
\r
242 /* Configure event mode : read current mode */
\r
243 regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
\r
246 /* Mask or set line */
\r
247 if ((pExtiConfig->Mode & EXTI_MODE_EVENT) != 0x00u)
\r
249 regval |= maskline;
\r
253 regval &= ~maskline;
\r
256 /* Store event mode */
\r
264 * @brief Get configuration of a dedicated Exti line.
\r
265 * @param hexti Exti handle.
\r
266 * @param pExtiConfig Pointer on structure to store Exti configuration.
\r
267 * @retval HAL Status.
\r
269 HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
\r
271 __IO uint32_t *regaddr;
\r
277 /* Check null pointer */
\r
278 if ((hexti == NULL) || (pExtiConfig == NULL))
\r
283 /* Check the parameter */
\r
284 assert_param(IS_EXTI_LINE(hexti->Line));
\r
286 /* Store handle line number to configuration structure */
\r
287 pExtiConfig->Line = hexti->Line;
\r
289 /* Compute line register offset and line mask */
\r
290 offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
\r
291 linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
\r
292 maskline = (1uL << linepos);
\r
294 /* 1] Get core mode : interrupt */
\r
295 regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
\r
298 /* Check if selected line is enable */
\r
299 if ((regval & maskline) != 0x00u)
\r
301 pExtiConfig->Mode = EXTI_MODE_INTERRUPT;
\r
305 pExtiConfig->Mode = EXTI_MODE_NONE;
\r
308 /* Get event mode */
\r
309 regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
\r
312 /* Check if selected line is enable */
\r
313 if ((regval & maskline) != 0x00u)
\r
315 pExtiConfig->Mode |= EXTI_MODE_EVENT;
\r
318 /* 2] Get trigger for configurable lines : rising */
\r
319 if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
\r
321 regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
\r
324 /* Check if configuration of selected line is enable */
\r
325 if ((regval & maskline) != 0x00u)
\r
327 pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
\r
331 pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
\r
334 /* Get falling configuration */
\r
335 regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
\r
338 /* Check if configuration of selected line is enable */
\r
339 if ((regval & maskline) != 0x00u)
\r
341 pExtiConfig->Trigger |= EXTI_TRIGGER_FALLING;
\r
344 /* Get Gpio port selection for gpio lines */
\r
345 if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
\r
347 assert_param(IS_EXTI_GPIO_PIN(linepos));
\r
349 regval = SYSCFG->EXTICR[linepos >> 2u];
\r
350 pExtiConfig->GPIOSel = ((regval << (SYSCFG_EXTICR1_EXTI1_Pos * (3uL - (linepos & 0x03u)))) >> 24);
\r
354 pExtiConfig->GPIOSel = 0x00u;
\r
359 pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
\r
360 pExtiConfig->GPIOSel = 0x00u;
\r
368 * @brief Clear whole configuration of a dedicated Exti line.
\r
369 * @param hexti Exti handle.
\r
370 * @retval HAL Status.
\r
372 HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
\r
374 __IO uint32_t *regaddr;
\r
380 /* Check null pointer */
\r
386 /* Check the parameter */
\r
387 assert_param(IS_EXTI_LINE(hexti->Line));
\r
389 /* compute line register offset and line mask */
\r
390 offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
\r
391 linepos = (hexti->Line & EXTI_PIN_MASK);
\r
392 maskline = (1uL << linepos);
\r
394 /* 1] Clear interrupt mode */
\r
395 regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
\r
396 regval = (*regaddr & ~maskline);
\r
399 /* 2] Clear event mode */
\r
400 regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
\r
401 regval = (*regaddr & ~maskline);
\r
404 /* 3] Clear triggers in case of configurable lines */
\r
405 if ((hexti->Line & EXTI_CONFIG) != 0x00u)
\r
407 regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
\r
408 regval = (*regaddr & ~maskline);
\r
411 regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
\r
412 regval = (*regaddr & ~maskline);
\r
415 /* Get Gpio port selection for gpio lines */
\r
416 if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
\r
418 assert_param(IS_EXTI_GPIO_PIN(linepos));
\r
420 regval = SYSCFG->EXTICR[linepos >> 2u];
\r
421 regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
\r
422 SYSCFG->EXTICR[linepos >> 2u] = regval;
\r
431 * @brief Register callback for a dedicated Exti line.
\r
432 * @param hexti Exti handle.
\r
433 * @param CallbackID User callback identifier.
\r
434 * This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
\r
435 * @param pPendingCbfn function pointer to be stored as callback.
\r
436 * @retval HAL Status.
\r
438 HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID, void (*pPendingCbfn)(void))
\r
440 HAL_StatusTypeDef status = HAL_OK;
\r
442 switch (CallbackID)
\r
444 case HAL_EXTI_COMMON_CB_ID:
\r
445 hexti->PendingCallback = pPendingCbfn;
\r
449 status = HAL_ERROR;
\r
458 * @brief Store line number as handle private field.
\r
459 * @param hexti Exti handle.
\r
460 * @param ExtiLine Exti line number.
\r
461 * This parameter can be from 0 to @ref EXTI_LINE_NB.
\r
462 * @retval HAL Status.
\r
464 HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
\r
466 /* Check the parameters */
\r
467 assert_param(IS_EXTI_LINE(ExtiLine));
\r
469 /* Check null pointer */
\r
476 /* Store line number as handle private field */
\r
477 hexti->Line = ExtiLine;
\r
488 /** @addtogroup EXTI_Exported_Functions_Group2
\r
489 * @brief EXTI IO functions.
\r
492 ===============================================================================
\r
493 ##### IO operation functions #####
\r
494 ===============================================================================
\r
501 * @brief Handle EXTI interrupt request.
\r
502 * @param hexti Exti handle.
\r
505 void HAL_EXTI_IRQHandler(EXTI_HandleTypeDef *hexti)
\r
507 __IO uint32_t *regaddr;
\r
512 /* Compute line register offset and line mask */
\r
513 offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
\r
514 maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
\r
516 /* Get pending bit */
\r
517 regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
\r
518 regval = (*regaddr & maskline);
\r
520 if (regval != 0x00u)
\r
522 /* Clear pending bit */
\r
523 *regaddr = maskline;
\r
525 /* Call callback */
\r
526 if (hexti->PendingCallback != NULL)
\r
528 hexti->PendingCallback();
\r
535 * @brief Get interrupt pending bit of a dedicated line.
\r
536 * @param hexti Exti handle.
\r
537 * @param Edge Specify which pending edge as to be checked.
\r
538 * This parameter can be one of the following values:
\r
539 * @arg @ref EXTI_TRIGGER_RISING_FALLING
\r
540 * This parameter is kept for compatibility with other series.
\r
541 * @retval 1 if interrupt is pending else 0.
\r
543 uint32_t HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
\r
545 __IO uint32_t *regaddr;
\r
551 /* Check parameters */
\r
552 assert_param(IS_EXTI_LINE(hexti->Line));
\r
553 assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
\r
554 assert_param(IS_EXTI_PENDING_EDGE(Edge));
\r
556 /* Compute line register offset and line mask */
\r
557 offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
\r
558 linepos = (hexti->Line & EXTI_PIN_MASK);
\r
559 maskline = (1uL << linepos);
\r
561 /* Get pending bit */
\r
562 regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
\r
564 /* return 1 if bit is set else 0 */
\r
565 regval = ((*regaddr & maskline) >> linepos);
\r
571 * @brief Clear interrupt pending bit of a dedicated line.
\r
572 * @param hexti Exti handle.
\r
573 * @param Edge Specify which pending edge as to be clear.
\r
574 * This parameter can be one of the following values:
\r
575 * @arg @ref EXTI_TRIGGER_RISING_FALLING
\r
576 * This parameter is kept for compatibility with other series.
\r
579 void HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
\r
581 __IO uint32_t *regaddr;
\r
585 /* Check parameters */
\r
586 assert_param(IS_EXTI_LINE(hexti->Line));
\r
587 assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
\r
588 assert_param(IS_EXTI_PENDING_EDGE(Edge));
\r
590 /* compute line register offset and line mask */
\r
591 offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
\r
592 maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
\r
594 /* Get pending register address */
\r
595 regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
\r
597 /* Clear Pending bit */
\r
598 *regaddr = maskline;
\r
603 * @brief Generate a software interrupt for a dedicated line.
\r
604 * @param hexti Exti handle.
\r
607 void HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef *hexti)
\r
609 __IO uint32_t *regaddr;
\r
613 /* Check parameters */
\r
614 assert_param(IS_EXTI_LINE(hexti->Line));
\r
615 assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
\r
617 /* compute line register offset and line mask */
\r
618 offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
\r
619 maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
\r
621 regaddr = (&EXTI->SWIER1 + (EXTI_CONFIG_OFFSET * offset));
\r
622 *regaddr = maskline;
\r
634 #endif /* HAL_EXTI_MODULE_ENABLED */
\r
643 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\r