STM32L443xx HAL User Manual
stm32l4xx_hal_exti.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_exti.c
00004   * @author  MCD Application Team
00005   * @brief   EXTI HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the Extended Interrupts and events controller (EXTI) peripheral:
00008   *           + Initialization and de-initialization functions
00009   *           + IO operation functions
00010   *
00011   ******************************************************************************
00012   * @attention
00013   *
00014   * Copyright (c) 2018 STMicroelectronics.
00015   * All rights reserved.
00016   *
00017   * This software is licensed under terms that can be found in the LICENSE file
00018   * in the root directory of this software component.
00019   * If no LICENSE file comes with this software, it is provided AS-IS.
00020   *
00021   ******************************************************************************
00022   @verbatim
00023   ==============================================================================
00024                     ##### EXTI Peripheral features #####
00025   ==============================================================================
00026   [..]
00027     (+) Each Exti line can be configured within this driver.
00028 
00029     (+) Exti line can be configured in 3 different modes
00030         (++) Interrupt
00031         (++) Event
00032         (++) Both of them
00033 
00034     (+) Configurable Exti lines can be configured with 3 different triggers
00035         (++) Rising
00036         (++) Falling
00037         (++) Both of them
00038 
00039     (+) When set in interrupt mode, configurable Exti lines have two different
00040         interrupts pending registers which allow to distinguish which transition
00041         occurs:
00042         (++) Rising edge pending interrupt
00043         (++) Falling
00044 
00045     (+) Exti lines 0 to 15 are linked to gpio pin number 0 to 15. Gpio port can
00046         be selected through multiplexer.
00047 
00048                      ##### How to use this driver #####
00049   ==============================================================================
00050   [..]
00051 
00052     (#) Configure the EXTI line using HAL_EXTI_SetConfigLine().
00053         (++) Choose the interrupt line number by setting "Line" member from
00054              EXTI_ConfigTypeDef structure.
00055         (++) Configure the interrupt and/or event mode using "Mode" member from
00056              EXTI_ConfigTypeDef structure.
00057         (++) For configurable lines, configure rising and/or falling trigger
00058              "Trigger" member from EXTI_ConfigTypeDef structure.
00059         (++) For Exti lines linked to gpio, choose gpio port using "GPIOSel"
00060              member from GPIO_InitTypeDef structure.
00061 
00062     (#) Get current Exti configuration of a dedicated line using
00063         HAL_EXTI_GetConfigLine().
00064         (++) Provide exiting handle as parameter.
00065         (++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
00066 
00067     (#) Clear Exti configuration of a dedicated line using HAL_EXTI_GetConfigLine().
00068         (++) Provide exiting handle as parameter.
00069 
00070     (#) Register callback to treat Exti interrupts using HAL_EXTI_RegisterCallback().
00071         (++) Provide exiting handle as first parameter.
00072         (++) Provide which callback will be registered using one value from
00073              EXTI_CallbackIDTypeDef.
00074         (++) Provide callback function pointer.
00075 
00076     (#) Get interrupt pending bit using HAL_EXTI_GetPending().
00077 
00078     (#) Clear interrupt pending bit using HAL_EXTI_GetPending().
00079 
00080     (#) Generate software interrupt using HAL_EXTI_GenerateSWI().
00081 
00082   @endverbatim
00083   */
00084 
00085 /* Includes ------------------------------------------------------------------*/
00086 #include "stm32l4xx_hal.h"
00087 
00088 /** @addtogroup STM32L4xx_HAL_Driver
00089   * @{
00090   */
00091 
00092 /** @addtogroup EXTI
00093   * @{
00094   */
00095 /** MISRA C:2012 deviation rule has been granted for following rule:
00096   * Rule-18.1_b - Medium: Array `EXTICR' 1st subscript interval [0,7] may be out
00097   * of bounds [0,3] in following API :
00098   * HAL_EXTI_SetConfigLine
00099   * HAL_EXTI_GetConfigLine
00100   * HAL_EXTI_ClearConfigLine
00101   */
00102 
00103 #ifdef HAL_EXTI_MODULE_ENABLED
00104 
00105 /* Private typedef -----------------------------------------------------------*/
00106 /* Private defines ------------------------------------------------------------*/
00107 /** @defgroup EXTI_Private_Constants EXTI Private Constants
00108   * @{
00109   */
00110 #define EXTI_MODE_OFFSET                    0x08u   /* 0x20: offset between MCU IMR/EMR registers */
00111 #define EXTI_CONFIG_OFFSET                  0x08u   /* 0x20: offset between MCU Rising/Falling configuration registers */
00112 /**
00113   * @}
00114   */
00115 
00116 /* Private macros ------------------------------------------------------------*/
00117 /* Private variables ---------------------------------------------------------*/
00118 /* Private function prototypes -----------------------------------------------*/
00119 /* Exported functions --------------------------------------------------------*/
00120 
00121 /** @addtogroup EXTI_Exported_Functions
00122   * @{
00123   */
00124 
00125 /** @addtogroup EXTI_Exported_Functions_Group1
00126  *  @brief    Configuration functions
00127  *
00128 @verbatim
00129  ===============================================================================
00130               ##### Configuration functions #####
00131  ===============================================================================
00132 
00133 @endverbatim
00134   * @{
00135   */
00136 
00137 /**
00138   * @brief  Set configuration of a dedicated Exti line.
00139   * @param  hexti Exti handle.
00140   * @param  pExtiConfig Pointer on EXTI configuration to be set.
00141   * @retval HAL Status.
00142   */
00143 HAL_StatusTypeDef HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
00144 {
00145   __IO uint32_t *regaddr;
00146   uint32_t regval;
00147   uint32_t linepos;
00148   uint32_t maskline;
00149   uint32_t offset;
00150 
00151   /* Check null pointer */
00152   if ((hexti == NULL) || (pExtiConfig == NULL))
00153   {
00154     return HAL_ERROR;
00155   }
00156 
00157   /* Check parameters */
00158   assert_param(IS_EXTI_LINE(pExtiConfig->Line));
00159   assert_param(IS_EXTI_MODE(pExtiConfig->Mode));
00160 
00161   /* Assign line number to handle */
00162   hexti->Line = pExtiConfig->Line;
00163 
00164   /* Compute line register offset and line mask */
00165   offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
00166   linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
00167   maskline = (1uL << linepos);
00168 
00169   /* Configure triggers for configurable lines */
00170   if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
00171   {
00172     assert_param(IS_EXTI_TRIGGER(pExtiConfig->Trigger));
00173 
00174     /* Configure rising trigger */
00175     regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
00176     regval = *regaddr;
00177 
00178     /* Mask or set line */
00179     if ((pExtiConfig->Trigger & EXTI_TRIGGER_RISING) != 0x00u)
00180     {
00181       regval |= maskline;
00182     }
00183     else
00184     {
00185       regval &= ~maskline;
00186     }
00187 
00188     /* Store rising trigger mode */
00189     *regaddr = regval;
00190 
00191     /* Configure falling trigger */
00192     regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
00193     regval = *regaddr;
00194 
00195     /* Mask or set line */
00196     if ((pExtiConfig->Trigger & EXTI_TRIGGER_FALLING) != 0x00u)
00197     {
00198       regval |= maskline;
00199     }
00200     else
00201     {
00202       regval &= ~maskline;
00203     }
00204 
00205     /* Store falling trigger mode */
00206     *regaddr = regval;
00207 
00208     /* Configure gpio port selection in case of gpio exti line */
00209     if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
00210     {
00211       assert_param(IS_EXTI_GPIO_PORT(pExtiConfig->GPIOSel));
00212       assert_param(IS_EXTI_GPIO_PIN(linepos));
00213 
00214       regval = SYSCFG->EXTICR[linepos >> 2u];
00215       regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
00216       regval |= (pExtiConfig->GPIOSel << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
00217       SYSCFG->EXTICR[linepos >> 2u] = regval;
00218     }
00219   }
00220 
00221   /* Configure interrupt mode : read current mode */
00222   regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
00223   regval = *regaddr;
00224 
00225   /* Mask or set line */
00226   if ((pExtiConfig->Mode & EXTI_MODE_INTERRUPT) != 0x00u)
00227   {
00228     regval |= maskline;
00229   }
00230   else
00231   {
00232     regval &= ~maskline;
00233   }
00234 
00235   /* Store interrupt mode */
00236   *regaddr = regval;
00237 
00238   /* The event mode cannot be configured if the line does not support it */
00239   assert_param(((pExtiConfig->Line & EXTI_EVENT) == EXTI_EVENT) || ((pExtiConfig->Mode & EXTI_MODE_EVENT) != EXTI_MODE_EVENT));
00240 
00241   /* Configure event mode : read current mode */
00242   regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
00243   regval = *regaddr;
00244 
00245   /* Mask or set line */
00246   if ((pExtiConfig->Mode & EXTI_MODE_EVENT) != 0x00u)
00247   {
00248     regval |= maskline;
00249   }
00250   else
00251   {
00252     regval &= ~maskline;
00253   }
00254 
00255   /* Store event mode */
00256   *regaddr = regval;
00257 
00258   return HAL_OK;
00259 }
00260 
00261 
00262 /**
00263   * @brief  Get configuration of a dedicated Exti line.
00264   * @param  hexti Exti handle.
00265   * @param  pExtiConfig Pointer on structure to store Exti configuration.
00266   * @retval HAL Status.
00267   */
00268 HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
00269 {
00270   __IO uint32_t *regaddr;
00271   uint32_t regval;
00272   uint32_t linepos;
00273   uint32_t maskline;
00274   uint32_t offset;
00275 
00276   /* Check null pointer */
00277   if ((hexti == NULL) || (pExtiConfig == NULL))
00278   {
00279     return HAL_ERROR;
00280   }
00281 
00282   /* Check the parameter */
00283   assert_param(IS_EXTI_LINE(hexti->Line));
00284 
00285   /* Store handle line number to configuration structure */
00286   pExtiConfig->Line = hexti->Line;
00287 
00288   /* Compute line register offset and line mask */
00289   offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
00290   linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
00291   maskline = (1uL << linepos);
00292 
00293   /* 1] Get core mode : interrupt */
00294   regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
00295   regval = *regaddr;
00296 
00297   /* Check if selected line is enable */
00298   if ((regval & maskline) != 0x00u)
00299   {
00300     pExtiConfig->Mode = EXTI_MODE_INTERRUPT;
00301   }
00302   else
00303   {
00304     pExtiConfig->Mode = EXTI_MODE_NONE;
00305   }
00306 
00307   /* Get event mode */
00308   regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
00309   regval = *regaddr;
00310 
00311   /* Check if selected line is enable */
00312   if ((regval & maskline) != 0x00u)
00313   {
00314     pExtiConfig->Mode |= EXTI_MODE_EVENT;
00315   }
00316 
00317   /* Get default Trigger and GPIOSel configuration */
00318   pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
00319   pExtiConfig->GPIOSel = 0x00u;
00320 
00321   /* 2] Get trigger for configurable lines : rising */
00322   if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
00323   {
00324     regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
00325     regval = *regaddr;
00326 
00327     /* Check if configuration of selected line is enable */
00328     if ((regval & maskline) != 0x00u)
00329     {
00330       pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
00331     }
00332 
00333     /* Get falling configuration */
00334     regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
00335     regval = *regaddr;
00336 
00337     /* Check if configuration of selected line is enable */
00338     if ((regval & maskline) != 0x00u)
00339     {
00340       pExtiConfig->Trigger |= EXTI_TRIGGER_FALLING;
00341     }
00342 
00343     /* Get Gpio port selection for gpio lines */
00344     if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
00345     {
00346       assert_param(IS_EXTI_GPIO_PIN(linepos));
00347 
00348       regval = SYSCFG->EXTICR[linepos >> 2u];
00349       pExtiConfig->GPIOSel = ((regval << (SYSCFG_EXTICR1_EXTI1_Pos * (3uL - (linepos & 0x03u)))) >> 24);
00350     }
00351   }
00352 
00353   return HAL_OK;
00354 }
00355 
00356 
00357 /**
00358   * @brief  Clear whole configuration of a dedicated Exti line.
00359   * @param  hexti Exti handle.
00360   * @retval HAL Status.
00361   */
00362 HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
00363 {
00364   __IO uint32_t *regaddr;
00365   uint32_t regval;
00366   uint32_t linepos;
00367   uint32_t maskline;
00368   uint32_t offset;
00369 
00370   /* Check null pointer */
00371   if (hexti == NULL)
00372   {
00373     return HAL_ERROR;
00374   }
00375 
00376   /* Check the parameter */
00377   assert_param(IS_EXTI_LINE(hexti->Line));
00378 
00379   /* compute line register offset and line mask */
00380   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
00381   linepos = (hexti->Line & EXTI_PIN_MASK);
00382   maskline = (1uL << linepos);
00383 
00384   /* 1] Clear interrupt mode */
00385   regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
00386   regval = (*regaddr & ~maskline);
00387   *regaddr = regval;
00388 
00389   /* 2] Clear event mode */
00390   regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
00391   regval = (*regaddr & ~maskline);
00392   *regaddr = regval;
00393 
00394   /* 3] Clear triggers in case of configurable lines */
00395   if ((hexti->Line & EXTI_CONFIG) != 0x00u)
00396   {
00397     regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
00398     regval = (*regaddr & ~maskline);
00399     *regaddr = regval;
00400 
00401     regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
00402     regval = (*regaddr & ~maskline);
00403     *regaddr = regval;
00404 
00405     /* Get Gpio port selection for gpio lines */
00406     if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
00407     {
00408       assert_param(IS_EXTI_GPIO_PIN(linepos));
00409 
00410       regval = SYSCFG->EXTICR[linepos >> 2u];
00411       regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
00412       SYSCFG->EXTICR[linepos >> 2u] = regval;
00413     }
00414   }
00415 
00416   return HAL_OK;
00417 }
00418 
00419 
00420 /**
00421   * @brief  Register callback for a dedicated Exti line.
00422   * @param  hexti Exti handle.
00423   * @param  CallbackID User callback identifier.
00424   *         This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
00425   * @param  pPendingCbfn function pointer to be stored as callback.
00426   * @retval HAL Status.
00427   */
00428 HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID, void (*pPendingCbfn)(void))
00429 {
00430   HAL_StatusTypeDef status = HAL_OK;
00431 
00432   switch (CallbackID)
00433   {
00434     case  HAL_EXTI_COMMON_CB_ID:
00435       hexti->PendingCallback = pPendingCbfn;
00436       break;
00437 
00438     default:
00439       status = HAL_ERROR;
00440       break;
00441   }
00442 
00443   return status;
00444 }
00445 
00446 
00447 /**
00448   * @brief  Store line number as handle private field.
00449   * @param  hexti Exti handle.
00450   * @param  ExtiLine Exti line number.
00451   *         This parameter can be from 0 to @ref EXTI_LINE_NB.
00452   * @retval HAL Status.
00453   */
00454 HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
00455 {
00456   /* Check the parameters */
00457   assert_param(IS_EXTI_LINE(ExtiLine));
00458 
00459   /* Check null pointer */
00460   if (hexti == NULL)
00461   {
00462     return HAL_ERROR;
00463   }
00464   else
00465   {
00466     /* Store line number as handle private field */
00467     hexti->Line = ExtiLine;
00468 
00469     return HAL_OK;
00470   }
00471 }
00472 
00473 
00474 /**
00475   * @}
00476   */
00477 
00478 /** @addtogroup EXTI_Exported_Functions_Group2
00479  *  @brief EXTI IO functions.
00480  *
00481 @verbatim
00482  ===============================================================================
00483                        ##### IO operation functions #####
00484  ===============================================================================
00485 
00486 @endverbatim
00487   * @{
00488   */
00489 
00490 /**
00491   * @brief  Handle EXTI interrupt request.
00492   * @param  hexti Exti handle.
00493   * @retval none.
00494   */
00495 void HAL_EXTI_IRQHandler(EXTI_HandleTypeDef *hexti)
00496 {
00497   __IO uint32_t *regaddr;
00498   uint32_t regval;
00499   uint32_t maskline;
00500   uint32_t offset;
00501 
00502   /* Compute line register offset and line mask */
00503   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
00504   maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
00505 
00506   /* Get pending bit  */
00507   regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
00508   regval = (*regaddr & maskline);
00509 
00510   if (regval != 0x00u)
00511   {
00512     /* Clear pending bit */
00513     *regaddr = maskline;
00514 
00515     /* Call callback */
00516     if (hexti->PendingCallback != NULL)
00517     {
00518       hexti->PendingCallback();
00519     }
00520   }
00521 }
00522 
00523 
00524 /**
00525   * @brief  Get interrupt pending bit of a dedicated line.
00526   * @param  hexti Exti handle.
00527   * @param  Edge Specify which pending edge as to be checked.
00528   *         This parameter can be one of the following values:
00529   *           @arg @ref EXTI_TRIGGER_RISING_FALLING
00530   *         This parameter is kept for compatibility with other series.
00531   * @retval 1 if interrupt is pending else 0.
00532   */
00533 uint32_t HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
00534 {
00535   __IO uint32_t *regaddr;
00536   uint32_t regval;
00537   uint32_t linepos;
00538   uint32_t maskline;
00539   uint32_t offset;
00540 
00541   /* Check parameters */
00542   assert_param(IS_EXTI_LINE(hexti->Line));
00543   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
00544   assert_param(IS_EXTI_PENDING_EDGE(Edge));
00545 
00546   /* Compute line register offset and line mask */
00547   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
00548   linepos = (hexti->Line & EXTI_PIN_MASK);
00549   maskline = (1uL << linepos);
00550 
00551   /* Get pending bit */
00552   regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
00553 
00554   /* return 1 if bit is set else 0 */
00555   regval = ((*regaddr & maskline) >> linepos);
00556   return regval;
00557 }
00558 
00559 
00560 /**
00561   * @brief  Clear interrupt pending bit of a dedicated line.
00562   * @param  hexti Exti handle.
00563   * @param  Edge Specify which pending edge as to be clear.
00564   *         This parameter can be one of the following values:
00565   *           @arg @ref EXTI_TRIGGER_RISING_FALLING
00566   *         This parameter is kept for compatibility with other series.
00567   * @retval None.
00568   */
00569 void HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
00570 {
00571   __IO uint32_t *regaddr;
00572   uint32_t maskline;
00573   uint32_t offset;
00574 
00575   /* Check parameters */
00576   assert_param(IS_EXTI_LINE(hexti->Line));
00577   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
00578   assert_param(IS_EXTI_PENDING_EDGE(Edge));
00579 
00580   /* compute line register offset and line mask */
00581   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
00582   maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
00583 
00584   /* Get pending register address */
00585   regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
00586 
00587   /* Clear Pending bit */
00588   *regaddr =  maskline;
00589 }
00590 
00591 
00592 /**
00593   * @brief  Generate a software interrupt for a dedicated line.
00594   * @param  hexti Exti handle.
00595   * @retval None.
00596   */
00597 void HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef *hexti)
00598 {
00599   __IO uint32_t *regaddr;
00600   uint32_t maskline;
00601   uint32_t offset;
00602 
00603   /* Check parameters */
00604   assert_param(IS_EXTI_LINE(hexti->Line));
00605   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
00606 
00607   /* compute line register offset and line mask */
00608   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
00609   maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
00610 
00611   regaddr = (&EXTI->SWIER1 + (EXTI_CONFIG_OFFSET * offset));
00612   *regaddr = maskline;
00613 }
00614 
00615 
00616 /**
00617   * @}
00618   */
00619 
00620 /**
00621   * @}
00622   */
00623 
00624 #endif /* HAL_EXTI_MODULE_ENABLED */
00625 /**
00626   * @}
00627   */
00628 
00629 /**
00630   * @}
00631   */
00632