xref: /btstack/port/stm32-l451-miromico-sx1280/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_exti.c (revision 2fd737d36a1de5d778cacc671d4b4d8c4f3fed82)
1 /**
2   ******************************************************************************
3   * @file    stm32l4xx_hal_exti.c
4   * @author  MCD Application Team
5   * @brief   EXTI HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Extended Interrupts and events controller (EXTI) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   *
11   @verbatim
12   ==============================================================================
13                     ##### EXTI Peripheral features #####
14   ==============================================================================
15   [..]
16     (+) Each Exti line can be configured within this driver.
17 
18     (+) Exti line can be configured in 3 different modes
19         (++) Interrupt
20         (++) Event
21         (++) Both of them
22 
23     (+) Configurable Exti lines can be configured with 3 different triggers
24         (++) Rising
25         (++) Falling
26         (++) Both of them
27 
28     (+) When set in interrupt mode, configurable Exti lines have two different
29         interrupts pending registers which allow to distinguish which transition
30         occurs:
31         (++) Rising edge pending interrupt
32         (++) Falling
33 
34     (+) Exti lines 0 to 15 are linked to gpio pin number 0 to 15. Gpio port can
35         be selected through multiplexer.
36 
37                      ##### How to use this driver #####
38   ==============================================================================
39   [..]
40 
41     (#) Configure the EXTI line using HAL_EXTI_SetConfigLine().
42         (++) Choose the interrupt line number by setting "Line" member from
43              EXTI_ConfigTypeDef structure.
44         (++) Configure the interrupt and/or event mode using "Mode" member from
45              EXTI_ConfigTypeDef structure.
46         (++) For configurable lines, configure rising and/or falling trigger
47              "Trigger" member from EXTI_ConfigTypeDef structure.
48         (++) For Exti lines linked to gpio, choose gpio port using "GPIOSel"
49              member from GPIO_InitTypeDef structure.
50 
51     (#) Get current Exti configuration of a dedicated line using
52         HAL_EXTI_GetConfigLine().
53         (++) Provide exiting handle as parameter.
54         (++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
55 
56     (#) Clear Exti configuration of a dedicated line using HAL_EXTI_GetConfigLine().
57         (++) Provide exiting handle as parameter.
58 
59     (#) Register callback to treat Exti interrupts using HAL_EXTI_RegisterCallback().
60         (++) Provide exiting handle as first parameter.
61         (++) Provide which callback will be registered using one value from
62              EXTI_CallbackIDTypeDef.
63         (++) Provide callback function pointer.
64 
65     (#) Get interrupt pending bit using HAL_EXTI_GetPending().
66 
67     (#) Clear interrupt pending bit using HAL_EXTI_GetPending().
68 
69     (#) Generate software interrupt using HAL_EXTI_GenerateSWI().
70 
71   @endverbatim
72   ******************************************************************************
73   * @attention
74   *
75   * <h2><center>&copy; Copyright (c) 2018 STMicroelectronics.
76   * All rights reserved.</center></h2>
77   *
78   * This software component is licensed by ST under BSD 3-Clause license,
79   * the "License"; You may not use this file except in compliance with the
80   * License. You may obtain a copy of the License at:
81   *                        opensource.org/licenses/BSD-3-Clause
82   *
83   ******************************************************************************
84   */
85 
86 /* Includes ------------------------------------------------------------------*/
87 #include "stm32l4xx_hal.h"
88 
89 /** @addtogroup STM32L4xx_HAL_Driver
90   * @{
91   */
92 
93 /** @addtogroup EXTI
94   * @{
95   */
96 /** MISRA C:2012 deviation rule has been granted for following rule:
97   * Rule-18.1_b - Medium: Array `EXTICR' 1st subscript interval [0,7] may be out
98   * of bounds [0,3] in following API :
99   * HAL_EXTI_SetConfigLine
100   * HAL_EXTI_GetConfigLine
101   * HAL_EXTI_ClearConfigLine
102   */
103 
104 #ifdef HAL_EXTI_MODULE_ENABLED
105 
106 /* Private typedef -----------------------------------------------------------*/
107 /* Private defines ------------------------------------------------------------*/
108 /** @defgroup EXTI_Private_Constants EXTI Private Constants
109   * @{
110   */
111 #define EXTI_MODE_OFFSET                    0x08u   /* 0x20: offset between MCU IMR/EMR registers */
112 #define EXTI_CONFIG_OFFSET                  0x08u   /* 0x20: offset between MCU Rising/Falling configuration registers */
113 /**
114   * @}
115   */
116 
117 /* Private macros ------------------------------------------------------------*/
118 /* Private variables ---------------------------------------------------------*/
119 /* Private function prototypes -----------------------------------------------*/
120 /* Exported functions --------------------------------------------------------*/
121 
122 /** @addtogroup EXTI_Exported_Functions
123   * @{
124   */
125 
126 /** @addtogroup EXTI_Exported_Functions_Group1
127  *  @brief    Configuration functions
128  *
129 @verbatim
130  ===============================================================================
131               ##### Configuration functions #####
132  ===============================================================================
133 
134 @endverbatim
135   * @{
136   */
137 
138 /**
139   * @brief  Set configuration of a dedicated Exti line.
140   * @param  hexti Exti handle.
141   * @param  pExtiConfig Pointer on EXTI configuration to be set.
142   * @retval HAL Status.
143   */
HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef * hexti,EXTI_ConfigTypeDef * pExtiConfig)144 HAL_StatusTypeDef HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
145 {
146   __IO uint32_t *regaddr;
147   uint32_t regval;
148   uint32_t linepos;
149   uint32_t maskline;
150   uint32_t offset;
151 
152   /* Check null pointer */
153   if ((hexti == NULL) || (pExtiConfig == NULL))
154   {
155     return HAL_ERROR;
156   }
157 
158   /* Check parameters */
159   assert_param(IS_EXTI_LINE(pExtiConfig->Line));
160   assert_param(IS_EXTI_MODE(pExtiConfig->Mode));
161 
162   /* Assign line number to handle */
163   hexti->Line = pExtiConfig->Line;
164 
165   /* Compute line register offset and line mask */
166   offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
167   linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
168   maskline = (1uL << linepos);
169 
170   /* Configure triggers for configurable lines */
171   if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
172   {
173     assert_param(IS_EXTI_TRIGGER(pExtiConfig->Trigger));
174 
175     /* Configure rising trigger */
176     regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
177     regval = *regaddr;
178 
179     /* Mask or set line */
180     if ((pExtiConfig->Trigger & EXTI_TRIGGER_RISING) != 0x00u)
181     {
182       regval |= maskline;
183     }
184     else
185     {
186       regval &= ~maskline;
187     }
188 
189     /* Store rising trigger mode */
190     *regaddr = regval;
191 
192     /* Configure falling trigger */
193     regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
194     regval = *regaddr;
195 
196     /* Mask or set line */
197     if ((pExtiConfig->Trigger & EXTI_TRIGGER_FALLING) != 0x00u)
198     {
199       regval |= maskline;
200     }
201     else
202     {
203       regval &= ~maskline;
204     }
205 
206     /* Store falling trigger mode */
207     *regaddr = regval;
208 
209     /* Configure gpio port selection in case of gpio exti line */
210     if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
211     {
212       assert_param(IS_EXTI_GPIO_PORT(pExtiConfig->GPIOSel));
213       assert_param(IS_EXTI_GPIO_PIN(linepos));
214 
215       regval = SYSCFG->EXTICR[linepos >> 2u];
216       regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
217       regval |= (pExtiConfig->GPIOSel << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
218       SYSCFG->EXTICR[linepos >> 2u] = regval;
219     }
220   }
221 
222   /* Configure interrupt mode : read current mode */
223   regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
224   regval = *regaddr;
225 
226   /* Mask or set line */
227   if ((pExtiConfig->Mode & EXTI_MODE_INTERRUPT) != 0x00u)
228   {
229     regval |= maskline;
230   }
231   else
232   {
233     regval &= ~maskline;
234   }
235 
236   /* Store interrupt mode */
237   *regaddr = regval;
238 
239   /* The event mode cannot be configured if the line does not support it */
240   assert_param(((pExtiConfig->Line & EXTI_EVENT) == EXTI_EVENT) || ((pExtiConfig->Mode & EXTI_MODE_EVENT) != EXTI_MODE_EVENT));
241 
242   /* Configure event mode : read current mode */
243   regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
244   regval = *regaddr;
245 
246   /* Mask or set line */
247   if ((pExtiConfig->Mode & EXTI_MODE_EVENT) != 0x00u)
248   {
249     regval |= maskline;
250   }
251   else
252   {
253     regval &= ~maskline;
254   }
255 
256   /* Store event mode */
257   *regaddr = regval;
258 
259   return HAL_OK;
260 }
261 
262 
263 /**
264   * @brief  Get configuration of a dedicated Exti line.
265   * @param  hexti Exti handle.
266   * @param  pExtiConfig Pointer on structure to store Exti configuration.
267   * @retval HAL Status.
268   */
HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef * hexti,EXTI_ConfigTypeDef * pExtiConfig)269 HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
270 {
271   __IO uint32_t *regaddr;
272   uint32_t regval;
273   uint32_t linepos;
274   uint32_t maskline;
275   uint32_t offset;
276 
277   /* Check null pointer */
278   if ((hexti == NULL) || (pExtiConfig == NULL))
279   {
280     return HAL_ERROR;
281   }
282 
283   /* Check the parameter */
284   assert_param(IS_EXTI_LINE(hexti->Line));
285 
286   /* Store handle line number to configuration structure */
287   pExtiConfig->Line = hexti->Line;
288 
289   /* Compute line register offset and line mask */
290   offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
291   linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
292   maskline = (1uL << linepos);
293 
294   /* 1] Get core mode : interrupt */
295   regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
296   regval = *regaddr;
297 
298   /* Check if selected line is enable */
299   if ((regval & maskline) != 0x00u)
300   {
301     pExtiConfig->Mode = EXTI_MODE_INTERRUPT;
302   }
303   else
304   {
305     pExtiConfig->Mode = EXTI_MODE_NONE;
306   }
307 
308   /* Get event mode */
309   regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
310   regval = *regaddr;
311 
312   /* Check if selected line is enable */
313   if ((regval & maskline) != 0x00u)
314   {
315     pExtiConfig->Mode |= EXTI_MODE_EVENT;
316   }
317 
318   /* 2] Get trigger for configurable lines : rising */
319   if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
320   {
321     regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
322     regval = *regaddr;
323 
324     /* Check if configuration of selected line is enable */
325     if ((regval & maskline) != 0x00u)
326     {
327       pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
328     }
329     else
330     {
331       pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
332     }
333 
334     /* Get falling configuration */
335     regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
336     regval = *regaddr;
337 
338     /* Check if configuration of selected line is enable */
339     if ((regval & maskline) != 0x00u)
340     {
341       pExtiConfig->Trigger |= EXTI_TRIGGER_FALLING;
342     }
343 
344     /* Get Gpio port selection for gpio lines */
345     if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
346     {
347       assert_param(IS_EXTI_GPIO_PIN(linepos));
348 
349       regval = SYSCFG->EXTICR[linepos >> 2u];
350       pExtiConfig->GPIOSel = ((regval << (SYSCFG_EXTICR1_EXTI1_Pos * (3uL - (linepos & 0x03u)))) >> 24);
351     }
352     else
353     {
354       pExtiConfig->GPIOSel = 0x00u;
355     }
356   }
357   else
358   {
359     pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
360     pExtiConfig->GPIOSel = 0x00u;
361   }
362 
363   return HAL_OK;
364 }
365 
366 
367 /**
368   * @brief  Clear whole configuration of a dedicated Exti line.
369   * @param  hexti Exti handle.
370   * @retval HAL Status.
371   */
HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef * hexti)372 HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
373 {
374   __IO uint32_t *regaddr;
375   uint32_t regval;
376   uint32_t linepos;
377   uint32_t maskline;
378   uint32_t offset;
379 
380   /* Check null pointer */
381   if (hexti == NULL)
382   {
383     return HAL_ERROR;
384   }
385 
386   /* Check the parameter */
387   assert_param(IS_EXTI_LINE(hexti->Line));
388 
389   /* compute line register offset and line mask */
390   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
391   linepos = (hexti->Line & EXTI_PIN_MASK);
392   maskline = (1uL << linepos);
393 
394   /* 1] Clear interrupt mode */
395   regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
396   regval = (*regaddr & ~maskline);
397   *regaddr = regval;
398 
399   /* 2] Clear event mode */
400   regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
401   regval = (*regaddr & ~maskline);
402   *regaddr = regval;
403 
404   /* 3] Clear triggers in case of configurable lines */
405   if ((hexti->Line & EXTI_CONFIG) != 0x00u)
406   {
407     regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
408     regval = (*regaddr & ~maskline);
409     *regaddr = regval;
410 
411     regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
412     regval = (*regaddr & ~maskline);
413     *regaddr = regval;
414 
415     /* Get Gpio port selection for gpio lines */
416     if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
417     {
418       assert_param(IS_EXTI_GPIO_PIN(linepos));
419 
420       regval = SYSCFG->EXTICR[linepos >> 2u];
421       regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
422       SYSCFG->EXTICR[linepos >> 2u] = regval;
423     }
424   }
425 
426   return HAL_OK;
427 }
428 
429 
430 /**
431   * @brief  Register callback for a dedicated Exti line.
432   * @param  hexti Exti handle.
433   * @param  CallbackID User callback identifier.
434   *         This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
435   * @param  pPendingCbfn function pointer to be stored as callback.
436   * @retval HAL Status.
437   */
HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef * hexti,EXTI_CallbackIDTypeDef CallbackID,void (* pPendingCbfn)(void))438 HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID, void (*pPendingCbfn)(void))
439 {
440   HAL_StatusTypeDef status = HAL_OK;
441 
442   switch (CallbackID)
443   {
444     case  HAL_EXTI_COMMON_CB_ID:
445       hexti->PendingCallback = pPendingCbfn;
446       break;
447 
448     default:
449       status = HAL_ERROR;
450       break;
451   }
452 
453   return status;
454 }
455 
456 
457 /**
458   * @brief  Store line number as handle private field.
459   * @param  hexti Exti handle.
460   * @param  ExtiLine Exti line number.
461   *         This parameter can be from 0 to @ref EXTI_LINE_NB.
462   * @retval HAL Status.
463   */
HAL_EXTI_GetHandle(EXTI_HandleTypeDef * hexti,uint32_t ExtiLine)464 HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
465 {
466   /* Check the parameters */
467   assert_param(IS_EXTI_LINE(ExtiLine));
468 
469   /* Check null pointer */
470   if (hexti == NULL)
471   {
472     return HAL_ERROR;
473   }
474   else
475   {
476     /* Store line number as handle private field */
477     hexti->Line = ExtiLine;
478 
479     return HAL_OK;
480   }
481 }
482 
483 
484 /**
485   * @}
486   */
487 
488 /** @addtogroup EXTI_Exported_Functions_Group2
489  *  @brief EXTI IO functions.
490  *
491 @verbatim
492  ===============================================================================
493                        ##### IO operation functions #####
494  ===============================================================================
495 
496 @endverbatim
497   * @{
498   */
499 
500 /**
501   * @brief  Handle EXTI interrupt request.
502   * @param  hexti Exti handle.
503   * @retval none.
504   */
HAL_EXTI_IRQHandler(EXTI_HandleTypeDef * hexti)505 void HAL_EXTI_IRQHandler(EXTI_HandleTypeDef *hexti)
506 {
507   __IO uint32_t *regaddr;
508   uint32_t regval;
509   uint32_t maskline;
510   uint32_t offset;
511 
512   /* Compute line register offset and line mask */
513   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
514   maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
515 
516   /* Get pending bit  */
517   regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
518   regval = (*regaddr & maskline);
519 
520   if (regval != 0x00u)
521   {
522     /* Clear pending bit */
523     *regaddr = maskline;
524 
525     /* Call callback */
526     if (hexti->PendingCallback != NULL)
527     {
528       hexti->PendingCallback();
529     }
530   }
531 }
532 
533 
534 /**
535   * @brief  Get interrupt pending bit of a dedicated line.
536   * @param  hexti Exti handle.
537   * @param  Edge Specify which pending edge as to be checked.
538   *         This parameter can be one of the following values:
539   *           @arg @ref EXTI_TRIGGER_RISING_FALLING
540   *         This parameter is kept for compatibility with other series.
541   * @retval 1 if interrupt is pending else 0.
542   */
HAL_EXTI_GetPending(EXTI_HandleTypeDef * hexti,uint32_t Edge)543 uint32_t HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
544 {
545   __IO uint32_t *regaddr;
546   uint32_t regval;
547   uint32_t linepos;
548   uint32_t maskline;
549   uint32_t offset;
550 
551   /* Check parameters */
552   assert_param(IS_EXTI_LINE(hexti->Line));
553   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
554   assert_param(IS_EXTI_PENDING_EDGE(Edge));
555 
556   /* Compute line register offset and line mask */
557   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
558   linepos = (hexti->Line & EXTI_PIN_MASK);
559   maskline = (1uL << linepos);
560 
561   /* Get pending bit */
562   regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
563 
564   /* return 1 if bit is set else 0 */
565   regval = ((*regaddr & maskline) >> linepos);
566   return regval;
567 }
568 
569 
570 /**
571   * @brief  Clear interrupt pending bit of a dedicated line.
572   * @param  hexti Exti handle.
573   * @param  Edge Specify which pending edge as to be clear.
574   *         This parameter can be one of the following values:
575   *           @arg @ref EXTI_TRIGGER_RISING_FALLING
576   *         This parameter is kept for compatibility with other series.
577   * @retval None.
578   */
HAL_EXTI_ClearPending(EXTI_HandleTypeDef * hexti,uint32_t Edge)579 void HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
580 {
581   __IO uint32_t *regaddr;
582   uint32_t maskline;
583   uint32_t offset;
584 
585   /* Check parameters */
586   assert_param(IS_EXTI_LINE(hexti->Line));
587   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
588   assert_param(IS_EXTI_PENDING_EDGE(Edge));
589 
590   /* compute line register offset and line mask */
591   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
592   maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
593 
594   /* Get pending register address */
595   regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
596 
597   /* Clear Pending bit */
598   *regaddr =  maskline;
599 }
600 
601 
602 /**
603   * @brief  Generate a software interrupt for a dedicated line.
604   * @param  hexti Exti handle.
605   * @retval None.
606   */
HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef * hexti)607 void HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef *hexti)
608 {
609   __IO uint32_t *regaddr;
610   uint32_t maskline;
611   uint32_t offset;
612 
613   /* Check parameters */
614   assert_param(IS_EXTI_LINE(hexti->Line));
615   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
616 
617   /* compute line register offset and line mask */
618   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
619   maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
620 
621   regaddr = (&EXTI->SWIER1 + (EXTI_CONFIG_OFFSET * offset));
622   *regaddr = maskline;
623 }
624 
625 
626 /**
627   * @}
628   */
629 
630 /**
631   * @}
632   */
633 
634 #endif /* HAL_EXTI_MODULE_ENABLED */
635 /**
636   * @}
637   */
638 
639 /**
640   * @}
641   */
642 
643 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
644