1 /**
2   ******************************************************************************
3   * @file    stm32h5xx_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 General Purpose Input/Output (EXTI) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   *
11   ******************************************************************************
12   * @attention
13   *
14   * Copyright (c) 2022 STMicroelectronics.
15   * All rights reserved.
16   *
17   * This software is licensed under terms that can be found in the LICENSE file
18   * in the root directory of this software component.
19   * If no LICENSE file comes with this software, it is provided AS-IS.
20   *
21   ******************************************************************************
22   @verbatim
23   ==============================================================================
24                     ##### EXTI Peripheral features #####
25   ==============================================================================
26   [..]
27     (+) Each Exti line can be configured within this driver.
28 
29     (+) Exti line can be configured in 3 different modes
30         (++) Interrupt
31         (++) Event
32         (++) Both of them
33 
34     (+) Configurable Exti lines can be configured with 3 different triggers
35         (++) Rising
36         (++) Falling
37         (++) Both of them
38 
39     (+) When set in interrupt mode, configurable Exti lines have two diffenrents
40         interrupt pending registers which allow to distinguish which transition
41         occurs:
42         (++) Rising edge pending interrupt
43         (++) Falling
44 
45     (+) Exti lines 0 to 15 are linked to gpio pin number 0 to 15. Gpio port can
46         be selected through multiplexer.
47 
48                      ##### How to use this driver #####
49   ==============================================================================
50   [..]
51 
52     (#) Configure the EXTI line using HAL_EXTI_SetConfigLine().
53         (++) Choose the interrupt line number by setting "Line" member from
54              EXTI_ConfigTypeDef structure.
55         (++) Configure the interrupt and/or event mode using "Mode" member from
56              EXTI_ConfigTypeDef structure.
57         (++) For configurable lines, configure rising and/or falling trigger
58              "Trigger" member from EXTI_ConfigTypeDef structure.
59         (++) For Exti lines linked to gpio, choose gpio port using "GPIOSel"
60              member from GPIO_InitTypeDef structure.
61 
62     (#) Get current Exti configuration of a dedicated line using
63         HAL_EXTI_GetConfigLine().
64         (++) Provide exiting handle as parameter.
65         (++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
66 
67     (#) Clear Exti configuration of a dedicated line using HAL_EXTI_GetConfigLine().
68         (++) Provide exiting handle as parameter.
69 
70     (#) Register callback to treat Exti interrupts using HAL_EXTI_RegisterCallback().
71         (++) Provide exiting handle as first parameter.
72         (++) Provide which callback will be registered using one value from
73              EXTI_CallbackIDTypeDef.
74         (++) Provide callback function pointer.
75 
76     (#) Get interrupt pending bit using HAL_EXTI_GetPending().
77 
78     (#) Clear interrupt pending bit using HAL_EXTI_GetPending().
79 
80     (#) Generate software interrupt using HAL_EXTI_GenerateSWI().
81 
82   @endverbatim
83   */
84 
85 /* Includes ------------------------------------------------------------------*/
86 #include "stm32h5xx_hal.h"
87 
88 /** @addtogroup STM32H5xx_HAL_Driver
89   * @{
90   */
91 
92 /** @addtogroup EXTI
93   * @{
94   */
95 
96 #ifdef HAL_EXTI_MODULE_ENABLED
97 
98 /* Private typedef -----------------------------------------------------------*/
99 /* Private defines ------------------------------------------------------------*/
100 /** @defgroup EXTI_Private_Constants EXTI Private Constants
101   * @{
102   */
103 #define EXTI_MODE_OFFSET                    0x04U   /* 0x10: byte offset between: IMR1/EMR1 and IMR2/EMR2 registers */
104 #define EXTI_CONFIG_OFFSET                  0x08U   /* 0x20: byte offset between Rising1/Falling1 and Rising2/Falling2
105                                                              configuration registers */
106 #define EXTI_PRIVCFGR_OFFSET                0x08U   /* 0x20: byte offset between PRIVCFGR1 and PRIVCFGR2 registers */
107 #define EXTI_SECCFGR_OFFSET                 0x08U   /* 0x20: byte offset between SECCFGR1 and SECCFGR2 registers */
108 /**
109   * @}
110   */
111 
112 /* Private macros ------------------------------------------------------------*/
113 /* Private variables ---------------------------------------------------------*/
114 /* Private function prototypes -----------------------------------------------*/
115 /* Exported functions --------------------------------------------------------*/
116 
117 /** @addtogroup EXTI_Exported_Functions
118   * @{
119   */
120 
121 /** @addtogroup EXTI_Exported_Functions_Group1
122   *  @brief    Configuration functions
123   *
124 @verbatim
125  ===============================================================================
126               ##### Configuration functions #####
127  ===============================================================================
128 
129 @endverbatim
130   * @{
131   */
132 
133 /**
134   * @brief  Set configuration of a dedicated Exti line.
135   * @param  hexti Exti handle.
136   * @param  pExtiConfig Pointer on EXTI configuration to be set.
137   * @retval HAL Status.
138   */
HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef * hexti,EXTI_ConfigTypeDef * pExtiConfig)139 HAL_StatusTypeDef HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
140 {
141   __IO uint32_t *regaddr;
142   uint32_t regval;
143   uint32_t linepos;
144   uint32_t maskline;
145   uint32_t offset;
146 
147   /* Check null pointer */
148   if ((hexti == NULL) || (pExtiConfig == NULL))
149   {
150     return HAL_ERROR;
151   }
152 
153   /* Check the parameters */
154   assert_param(IS_EXTI_LINE(pExtiConfig->Line));
155   assert_param(IS_EXTI_MODE(pExtiConfig->Mode));
156 
157   /* Assign line number to handle */
158   hexti->Line = pExtiConfig->Line;
159 
160   /* compute line register offset and line mask */
161   offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
162   linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
163   maskline = (1UL << linepos);
164 
165   /* Configure triggers for configurable lines */
166   if ((pExtiConfig->Line & EXTI_CONFIG) != 0U)
167   {
168     assert_param(IS_EXTI_TRIGGER(pExtiConfig->Trigger));
169 
170     /* Configure rising trigger */
171     regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
172     regval = *regaddr;
173 
174     /* Mask or set line */
175     if ((pExtiConfig->Trigger & EXTI_TRIGGER_RISING) != 0U)
176     {
177       regval |= maskline;
178     }
179     else
180     {
181       regval &= ~maskline;
182     }
183 
184     /* Store rising trigger mode */
185     *regaddr = regval;
186 
187     /* Configure falling trigger */
188     regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
189     regval = *regaddr;
190 
191     /* Mask or set line */
192     if ((pExtiConfig->Trigger & EXTI_TRIGGER_FALLING) != 0U)
193     {
194       regval |= maskline;
195     }
196     else
197     {
198       regval &= ~maskline;
199     }
200 
201     /* Store falling trigger mode */
202     *regaddr = regval;
203 
204     /* Configure gpio port selection in case of gpio exti line */
205     if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
206     {
207       assert_param(IS_EXTI_GPIO_PORT(pExtiConfig->GPIOSel));
208       assert_param(IS_EXTI_GPIO_PIN(linepos));
209 
210       regval = EXTI->EXTICR[(linepos >> 2U) & 0x03UL];
211       regval &= ~(EXTI_EXTICR1_EXTI0 << (EXTI_EXTICR1_EXTI1_Pos * (linepos & 0x03U)));
212       regval |= (pExtiConfig->GPIOSel << (EXTI_EXTICR1_EXTI1_Pos * (linepos & 0x03U)));
213       EXTI->EXTICR[(linepos >> 2U) & 0x03UL] = regval;
214     }
215   }
216 
217   /* Configure interrupt mode : read current mode */
218   regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
219   regval = *regaddr;
220 
221   /* Mask or set line */
222   if ((pExtiConfig->Mode & EXTI_MODE_INTERRUPT) != 0U)
223   {
224     regval |= maskline;
225   }
226   else
227   {
228     regval &= ~maskline;
229   }
230 
231   /* Store interrupt mode */
232   *regaddr = regval;
233 
234   /* Configure event mode : read current mode */
235   regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
236   regval = *regaddr;
237 
238   /* Mask or set line */
239   if ((pExtiConfig->Mode & EXTI_MODE_EVENT) != 0U)
240   {
241     regval |= maskline;
242   }
243   else
244   {
245     regval &= ~maskline;
246   }
247 
248   /* Store event mode */
249   *regaddr = regval;
250 
251   return HAL_OK;
252 }
253 
254 
255 /**
256   * @brief  Get configuration of a dedicated Exti line.
257   * @param  hexti Exti handle.
258   * @param  pExtiConfig Pointer on structure to store Exti configuration.
259   * @retval HAL Status.
260   */
HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef * hexti,EXTI_ConfigTypeDef * pExtiConfig)261 HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
262 {
263   __IO uint32_t *regaddr;
264   uint32_t regval;
265   uint32_t linepos;
266   uint32_t maskline;
267   uint32_t offset;
268 
269   /* Check null pointer */
270   if ((hexti == NULL) || (pExtiConfig == NULL))
271   {
272     return HAL_ERROR;
273   }
274 
275   /* Check the parameter */
276   assert_param(IS_EXTI_LINE(hexti->Line));
277 
278   /* Store handle line number to configiguration structure */
279   pExtiConfig->Line = hexti->Line;
280 
281   /* compute line register offset and line mask */
282   offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
283   linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
284   maskline = (1UL << linepos);
285 
286   /* 1] Get core mode : interrupt */
287   regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
288   regval = *regaddr;
289 
290   /* Check if selected line is enable */
291   if ((regval & maskline) != 0U)
292   {
293     pExtiConfig->Mode = EXTI_MODE_INTERRUPT;
294   }
295   else
296   {
297     pExtiConfig->Mode = EXTI_MODE_NONE;
298   }
299 
300   /* Get event mode */
301   regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
302   regval = *regaddr;
303 
304   /* Check if selected line is enable */
305   if ((regval & maskline) != 0U)
306   {
307     pExtiConfig->Mode |= EXTI_MODE_EVENT;
308   }
309 
310   /* 2] Get trigger for configurable lines : rising */
311   if ((pExtiConfig->Line & EXTI_CONFIG) != 0U)
312   {
313     regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
314     regval = *regaddr;
315 
316     /* Get default Trigger and GPIOSel configuration */
317     pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
318     pExtiConfig->GPIOSel = 0x00u;
319 
320     /* Check if configuration of selected line is enable */
321     if ((regval & maskline) != 0U)
322     {
323       pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
324     }
325 
326     /* Get falling configuration */
327     regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
328     regval = *regaddr;
329 
330     /* Check if configuration of selected line is enable */
331     if ((regval & maskline) != 0U)
332     {
333       pExtiConfig->Trigger |= EXTI_TRIGGER_FALLING;
334     }
335 
336     /* Get Gpio port selection for gpio lines */
337     if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
338     {
339       assert_param(IS_EXTI_GPIO_PIN(linepos));
340 
341       regval = EXTI->EXTICR[(linepos >> 2U) & 0x03UL];
342       pExtiConfig->GPIOSel = (regval >> (EXTI_EXTICR1_EXTI1_Pos * (linepos & 0x03u))) & EXTI_EXTICR1_EXTI0;
343     }
344   }
345 
346   return HAL_OK;
347 }
348 
349 
350 /**
351   * @brief  Clear whole configuration of a dedicated Exti line.
352   * @param  hexti Exti handle.
353   * @retval HAL Status.
354   */
HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef * hexti)355 HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
356 {
357   __IO uint32_t *regaddr;
358   uint32_t regval;
359   uint32_t linepos;
360   uint32_t maskline;
361   uint32_t offset;
362 
363   /* Check null pointer */
364   if (hexti == NULL)
365   {
366     return HAL_ERROR;
367   }
368 
369   /* Check the parameter */
370   assert_param(IS_EXTI_LINE(hexti->Line));
371 
372   /* compute line register offset and line mask */
373   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
374   linepos = (hexti->Line & EXTI_PIN_MASK);
375   maskline = (1UL << linepos);
376 
377   /* 1] Clear interrupt mode */
378   regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
379   regval = (*regaddr & ~maskline);
380   *regaddr = regval;
381 
382   /* 2] Clear event mode */
383   regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
384   regval = (*regaddr & ~maskline);
385   *regaddr = regval;
386 
387   /* 3] Clear triggers in case of configurable lines */
388   if ((hexti->Line & EXTI_CONFIG) != 0U)
389   {
390     regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
391     regval = (*regaddr & ~maskline);
392     *regaddr = regval;
393 
394     regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
395     regval = (*regaddr & ~maskline);
396     *regaddr = regval;
397 
398     /* Get Gpio port selection for gpio lines */
399     if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
400     {
401       assert_param(IS_EXTI_GPIO_PIN(linepos));
402 
403       regval = EXTI->EXTICR[(linepos >> 2U) & 0x03UL];
404       regval &= ~(EXTI_EXTICR1_EXTI0 << (EXTI_EXTICR1_EXTI1_Pos * (linepos & 0x03U)));
405       EXTI->EXTICR[(linepos >> 2U) & 0x03UL] = regval;
406     }
407   }
408 
409   return HAL_OK;
410 }
411 
412 
413 /**
414   * @brief  Register callback for a dedicaated Exti line.
415   * @param  hexti Exti handle.
416   * @param  CallbackID User callback identifier.
417   *         This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
418   * @param  pPendingCbfn function pointer to be stored as callback.
419   * @retval HAL Status.
420   */
HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef * hexti,EXTI_CallbackIDTypeDef CallbackID,void (* pPendingCbfn)(void))421 HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID,
422                                             void (*pPendingCbfn)(void))
423 {
424   HAL_StatusTypeDef status = HAL_OK;
425 
426   switch (CallbackID)
427   {
428     case  HAL_EXTI_COMMON_CB_ID:
429       hexti->RisingCallback = pPendingCbfn;
430       hexti->FallingCallback = pPendingCbfn;
431       break;
432 
433     case  HAL_EXTI_RISING_CB_ID:
434       hexti->RisingCallback = pPendingCbfn;
435       break;
436 
437     case  HAL_EXTI_FALLING_CB_ID:
438       hexti->FallingCallback = pPendingCbfn;
439       break;
440 
441     default:
442       status = HAL_ERROR;
443       break;
444   }
445 
446   return status;
447 }
448 
449 
450 /**
451   * @brief  Store line number as handle private field.
452   * @param  hexti Exti handle.
453   * @param  ExtiLine Exti line number.
454   *         This parameter can be from 0 to @ref EXTI_LINE_NB.
455   * @retval HAL Status.
456   */
HAL_EXTI_GetHandle(EXTI_HandleTypeDef * hexti,uint32_t ExtiLine)457 HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
458 {
459   /* Check the parameters */
460   assert_param(IS_EXTI_LINE(ExtiLine));
461 
462   /* Check null pointer */
463   if (hexti == NULL)
464   {
465     return HAL_ERROR;
466   }
467   else
468   {
469     /* Store line number as handle private field */
470     hexti->Line = ExtiLine;
471 
472     return HAL_OK;
473   }
474 }
475 
476 
477 /**
478   * @}
479   */
480 
481 /** @addtogroup EXTI_Exported_Functions_Group2
482   *  @brief EXTI IO functions.
483   *
484 @verbatim
485  ===============================================================================
486                        ##### IO operation functions #####
487  ===============================================================================
488 
489 @endverbatim
490   * @{
491   */
492 
493 /**
494   * @brief  Handle EXTI interrupt request.
495   * @param  hexti Exti handle.
496   * @retval none.
497   */
HAL_EXTI_IRQHandler(EXTI_HandleTypeDef * hexti)498 void HAL_EXTI_IRQHandler(EXTI_HandleTypeDef *hexti)
499 {
500   __IO uint32_t *regaddr;
501   uint32_t regval;
502   uint32_t maskline;
503   uint32_t offset;
504 
505   /* Compute line register offset and line mask */
506   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
507   maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
508 
509   /* Get rising edge pending bit  */
510   regaddr = (__IO uint32_t *)(&EXTI->RPR1 + (EXTI_CONFIG_OFFSET * offset));
511   regval = (*regaddr & maskline);
512 
513   if (regval != 0U)
514   {
515     /* Clear pending bit */
516     *regaddr = maskline;
517 
518     /* Call rising callback */
519     if (hexti->RisingCallback != NULL)
520     {
521       hexti->RisingCallback();
522     }
523   }
524 
525   /* Get falling edge pending bit  */
526   regaddr = (__IO uint32_t *)(&EXTI->FPR1 + (EXTI_CONFIG_OFFSET * offset));
527   regval = (*regaddr & maskline);
528 
529   if (regval != 0U)
530   {
531     /* Clear pending bit */
532     *regaddr = maskline;
533 
534     /* Call rising callback */
535     if (hexti->FallingCallback != NULL)
536     {
537       hexti->FallingCallback();
538     }
539   }
540 }
541 
542 
543 /**
544   * @brief  Get interrupt pending bit of a dedicated line.
545   * @param  hexti Exti handle.
546   * @param  Edge Specify which pending edge as to be checked.
547   *         This parameter can be one of the following values:
548   *           @arg @ref EXTI_TRIGGER_RISING
549   *           @arg @ref EXTI_TRIGGER_FALLING
550   * @retval 1 if interrupt is pending else 0.
551   */
HAL_EXTI_GetPending(EXTI_HandleTypeDef * hexti,uint32_t Edge)552 uint32_t HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
553 {
554   __IO uint32_t *regaddr;
555   uint32_t regval;
556   uint32_t linepos;
557   uint32_t maskline;
558   uint32_t offset;
559 
560   /* Check the parameters */
561   assert_param(IS_EXTI_LINE(hexti->Line));
562   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
563   assert_param(IS_EXTI_PENDING_EDGE(Edge));
564 
565   /* compute line register offset and line mask */
566   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
567   linepos = (hexti->Line & EXTI_PIN_MASK);
568   maskline = (1UL << linepos);
569 
570   if (Edge != EXTI_TRIGGER_RISING)
571   {
572     /* Get falling edge pending bit */
573     regaddr = (__IO uint32_t *)(&EXTI->FPR1 + (EXTI_CONFIG_OFFSET * offset));
574   }
575   else
576   {
577     /* Get rising edge pending bit */
578     regaddr = (__IO uint32_t *)(&EXTI->RPR1 + (EXTI_CONFIG_OFFSET * offset));
579   }
580 
581   /* return 1 if bit is set else 0 */
582   regval = ((*regaddr & maskline) >> linepos);
583   return regval;
584 }
585 
586 
587 /**
588   * @brief  Clear interrupt pending bit of a dedicated line.
589   * @param  hexti Exti handle.
590   * @param  Edge Specify which pending edge as to be clear.
591   *         This parameter can be one of the following values:
592   *           @arg @ref EXTI_TRIGGER_RISING
593   *           @arg @ref EXTI_TRIGGER_FALLING
594   * @retval None.
595   */
HAL_EXTI_ClearPending(EXTI_HandleTypeDef * hexti,uint32_t Edge)596 void HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
597 {
598   __IO uint32_t *regaddr;
599   uint32_t maskline;
600   uint32_t offset;
601 
602   /* Check the parameters */
603   assert_param(IS_EXTI_LINE(hexti->Line));
604   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
605   assert_param(IS_EXTI_PENDING_EDGE(Edge));
606 
607   /* compute line register offset and line mask */
608   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
609   maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
610 
611   if (Edge != EXTI_TRIGGER_RISING)
612   {
613     /* Get falling edge pending register address */
614     regaddr = (__IO uint32_t *)(&EXTI->FPR1 + (EXTI_CONFIG_OFFSET * offset));
615   }
616   else
617   {
618     /* Get falling edge pending register address */
619     regaddr = (__IO uint32_t *)(&EXTI->RPR1 + (EXTI_CONFIG_OFFSET * offset));
620   }
621 
622   /* Clear Pending bit */
623   *regaddr =  maskline;
624 }
625 
626 
627 /**
628   * @brief  Generate a software interrupt for a dedicated line.
629   * @param  hexti Exti handle.
630   * @retval None.
631   */
HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef * hexti)632 void HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef *hexti)
633 {
634   __IO uint32_t *regaddr;
635   uint32_t maskline;
636   uint32_t offset;
637 
638   /* Check the parameters */
639   assert_param(IS_EXTI_LINE(hexti->Line));
640   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
641 
642   /* compute line register offset and line mask */
643   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
644   maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
645 
646   regaddr = (__IO uint32_t *)(&EXTI->SWIER1 + (EXTI_CONFIG_OFFSET * offset));
647   *regaddr = maskline;
648 }
649 
650 
651 /**
652   * @}
653   */
654 
655 /** @defgroup EXTI_Exported_Functions_Group3 EXTI line attributes management functions
656   *  @brief EXTI attributes management functions.
657   *
658 @verbatim
659  ===============================================================================
660                        ##### EXTI attributes functions #####
661  ===============================================================================
662 
663 @endverbatim
664   * @{
665   */
666 
667 /**
668   * @brief  Configure the EXTI line attribute(s).
669   * @note   Available attributes are to secure EXTI line and set EXT line as privileged.
670   *         Default state is not secure and unprivileged access allowed.
671   * @note   Secure and non-secure attributes can only be set from the secure
672   *         state when the system implements the security (TZEN=1).
673   * @note   Security and privilege attributes can be set independently.
674   * @param  ExtiLine Exti line number.
675   *         This parameter can be from 0 to @ref EXTI_LINE_NB.
676   * @param  LineAttributes can be one or a combination of the following values:
677   *            @arg @ref EXTI_LINE_PRIV         Privileged-only access
678   *            @arg @ref EXTI_LINE_NPRIV        Privileged/Non-privileged access
679   *            @arg @ref EXTI_LINE_SEC          Secure-only access
680   *            @arg @ref EXTI_LINE_NSEC         Secure/Non-secure access
681   * @retval None
682   */
HAL_EXTI_ConfigLineAttributes(uint32_t ExtiLine,uint32_t LineAttributes)683 void HAL_EXTI_ConfigLineAttributes(uint32_t ExtiLine, uint32_t LineAttributes)
684 {
685   __IO uint32_t *regaddr;
686   uint32_t regval;
687   uint32_t linepos;
688   uint32_t maskline;
689   uint32_t offset;
690 
691   /* Check the parameters */
692   assert_param(IS_EXTI_LINE(ExtiLine));
693   assert_param(IS_EXTI_LINE_ATTRIBUTES(LineAttributes));
694 
695   /* compute line register offset and line mask */
696   offset = ((ExtiLine & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
697   linepos = (ExtiLine & EXTI_PIN_MASK);
698   maskline = (1UL << linepos);
699 
700   /* Configure privilege or non-privilege attributes */
701   regaddr = (__IO uint32_t *)(&EXTI->PRIVCFGR1 + (EXTI_PRIVCFGR_OFFSET * offset));
702   regval = *regaddr;
703 
704   /* Mask or set line */
705   if ((LineAttributes & EXTI_LINE_PRIV) == EXTI_LINE_PRIV)
706   {
707     regval |= maskline;
708   }
709   else if ((LineAttributes & EXTI_LINE_NPRIV) == EXTI_LINE_NPRIV)
710   {
711     regval &= ~maskline;
712   }
713   else
714   {
715     /* do nothing */
716   }
717 
718   /* Store privilege or non-privilege attribute */
719   *regaddr = regval;
720 
721 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
722 
723   /* Configure secure or non-secure attributes */
724   regaddr = (__IO uint32_t *)(&EXTI->SECCFGR1 + (EXTI_SECCFGR_OFFSET * offset));
725   regval = *regaddr;
726 
727   /* Mask or set line */
728   if ((LineAttributes & EXTI_LINE_SEC) == EXTI_LINE_SEC)
729   {
730     regval |= maskline;
731   }
732   else if ((LineAttributes & EXTI_LINE_NSEC) == EXTI_LINE_NSEC)
733   {
734     regval &= ~maskline;
735   }
736   else
737   {
738     /* do nothing */
739   }
740 
741   /* Store secure or non-secure attribute */
742   *regaddr = regval;
743 
744 #endif /* __ARM_FEATURE_CMSE */
745 }
746 
747 /**
748   * @brief  Get the EXTI line attribute(s).
749   * @note   Secure and non-secure attributes are only available from secure state
750   *         when the system implements the security (TZEN=1)
751   * @param  ExtiLine Exti line number.
752   *         This parameter can be from 0 to @ref EXTI_LINE_NB.
753   * @param  pLineAttributes: pointer to return line attributes.
754   * @retval HAL Status.
755   */
HAL_EXTI_GetConfigLineAttributes(uint32_t ExtiLine,uint32_t * pLineAttributes)756 HAL_StatusTypeDef HAL_EXTI_GetConfigLineAttributes(uint32_t ExtiLine, uint32_t *pLineAttributes)
757 {
758   __IO uint32_t *regaddr;
759   uint32_t linepos;
760   uint32_t maskline;
761   uint32_t offset;
762   uint32_t attributes;
763 
764   /* Check null pointer */
765   if (pLineAttributes == NULL)
766   {
767     return HAL_ERROR;
768   }
769 
770   /* Check the parameters */
771   assert_param(IS_EXTI_LINE(ExtiLine));
772 
773   /* Compute line register offset and line mask */
774   offset = ((ExtiLine & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
775   linepos = (ExtiLine & EXTI_PIN_MASK);
776   maskline = (1UL << linepos);
777 
778   /* Get privilege or non-privilege attribute */
779   regaddr = (__IO uint32_t *)(&EXTI->PRIVCFGR1 + (EXTI_PRIVCFGR_OFFSET * offset));
780 
781   if ((*regaddr & maskline) != 0U)
782   {
783     attributes = EXTI_LINE_PRIV;
784   }
785   else
786   {
787     attributes = EXTI_LINE_NPRIV;
788   }
789 
790 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
791 
792   /* Get secure or non-secure attribute */
793   regaddr = (__IO uint32_t *)(&EXTI->SECCFGR1 + (EXTI_SECCFGR_OFFSET * offset));
794 
795   if ((*regaddr & maskline) != 0U)
796   {
797     attributes |= EXTI_LINE_SEC;
798   }
799   else
800   {
801     attributes |= EXTI_LINE_NSEC;
802   }
803 
804 #endif /* __ARM_FEATURE_CMSE */
805 
806   /* return value */
807   *pLineAttributes = attributes;
808 
809   return HAL_OK;
810 }
811 #if defined (EXTI_LOCKR_LOCK)
812 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
813 /**
814   * @brief  Lock the global EXTI security and privilege configuration.
815   * @retval HAL Status.
816   */
HAL_EXTI_LockConfigAttributes(void)817 HAL_StatusTypeDef HAL_EXTI_LockConfigAttributes(void)
818 {
819   EXTI->LOCKR = EXTI_ATTRIBUTES_LOCKED;
820 
821   return HAL_OK;
822 }
823 
824 /**
825   * @brief  Get the global EXTI security and privilege lock configuration.
826   * @param  pLockState : Pointer to returned security and privilege configuration
827   * @retval HAL Status.
828   */
HAL_EXTI_GetLockConfigAttributes(uint32_t * const pLockState)829 HAL_StatusTypeDef HAL_EXTI_GetLockConfigAttributes(uint32_t *const pLockState)
830 {
831   uint32_t attributes;
832   __IO uint32_t *regaddr;
833 
834   /* Check null pointer */
835   if (pLockState == NULL)
836   {
837     return HAL_ERROR;
838   }
839 
840   /* Get security and privilege configuration */
841   regaddr = (__IO uint32_t *)(&EXTI->LOCKR);
842 
843   if ((*regaddr & EXTI_LOCKR_LOCK) != 0U)
844   {
845     attributes = EXTI_ATTRIBUTES_LOCKED;
846   }
847   else
848   {
849     attributes = EXTI_ATTRIBUTES_UNLOCKED;
850   }
851 
852   /* return value */
853   *pLockState = attributes;
854 
855   return HAL_OK;
856 }
857 #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
858 #endif /* defined (EXTI_LOCKR_LOCK) */
859 /**
860   * @}
861   */
862 
863 /**
864   * @}
865   */
866 
867 #endif /* HAL_EXTI_MODULE_ENABLED */
868 /**
869   * @}
870   */
871 
872 /**
873   * @}
874   */
875