1 /**
2   ******************************************************************************
3   * @file    stm32wbaxx_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 
86 /* Includes ------------------------------------------------------------------*/
87 #include "stm32wbaxx_hal.h"
88 
89 /** @addtogroup STM32WBAxx_HAL_Driver
90   * @{
91   */
92 
93 /** @addtogroup EXTI
94   * @{
95   */
96 
97 #ifdef HAL_EXTI_MODULE_ENABLED
98 
99 /* Private typedef -----------------------------------------------------------*/
100 /* Private defines ------------------------------------------------------------*/
101 /** @defgroup EXTI_Private_Constants EXTI Private Constants
102   * @{
103   */
104 #define EXTI_MODE_OFFSET                    0x04U   /* byte offset between IMR/EMR registers */
105 #define EXTI_CONFIG_OFFSET                  0x08U   /* byte offset between Rising/Falling configuration registers */
106 #define EXTI_PRIVCFGR_OFFSET                0x04U   /* byte offset between PRIVCFGR1/PRIVCFGR2 registers */
107 #define EXTI_SECCFGR_OFFSET                 0x04U   /* byte offset between SECCFGR1/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   const __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     /* Check if configuration of selected line is enable */
317     if ((regval & maskline) != 0U)
318     {
319       pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
320     }
321     else
322     {
323       pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
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_EXTI1_Pos;
343     }
344     else
345     {
346       pExtiConfig->GPIOSel = 0U;
347     }
348   }
349   else
350   {
351     pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
352     pExtiConfig->GPIOSel = 0U;
353   }
354 
355   return HAL_OK;
356 }
357 
358 
359 /**
360   * @brief  Clear whole configuration of a dedicated Exti line.
361   * @param  hexti Exti handle.
362   * @retval HAL Status.
363   */
HAL_EXTI_ClearConfigLine(const EXTI_HandleTypeDef * hexti)364 HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(const EXTI_HandleTypeDef *hexti)
365 {
366   __IO uint32_t *regaddr;
367   uint32_t regval;
368   uint32_t linepos;
369   uint32_t maskline;
370   uint32_t offset;
371 
372   /* Check null pointer */
373   if (hexti == NULL)
374   {
375     return HAL_ERROR;
376   }
377 
378   /* Check the parameter */
379   assert_param(IS_EXTI_LINE(hexti->Line));
380 
381   /* compute line register offset and line mask */
382   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
383   linepos = (hexti->Line & EXTI_PIN_MASK);
384   maskline = (1UL << linepos);
385 
386   /* 1] Clear interrupt mode */
387   regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
388   regval = (*regaddr & ~maskline);
389   *regaddr = regval;
390 
391   /* 2] Clear event mode */
392   regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
393   regval = (*regaddr & ~maskline);
394   *regaddr = regval;
395 
396   /* 3] Clear triggers in case of configurable lines */
397   if ((hexti->Line & EXTI_CONFIG) != 0U)
398   {
399     regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
400     regval = (*regaddr & ~maskline);
401     *regaddr = regval;
402 
403     regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
404     regval = (*regaddr & ~maskline);
405     *regaddr = regval;
406 
407     /* Get Gpio port selection for gpio lines */
408     if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
409     {
410       assert_param(IS_EXTI_GPIO_PIN(linepos));
411 
412       regval = EXTI->EXTICR[(linepos >> 2U) & 0x03UL];
413       regval &= ~(EXTI_EXTICR1_EXTI0 << (EXTI_EXTICR1_EXTI1_Pos * (linepos & 0x03U)));
414       EXTI->EXTICR[(linepos >> 2U) & 0x03UL] = regval;
415     }
416   }
417 
418   return HAL_OK;
419 }
420 
421 
422 /**
423   * @brief  Register callback for a dedicaated Exti line.
424   * @param  hexti Exti handle.
425   * @param  CallbackID User callback identifier.
426   *         This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
427   * @param  pPendingCbfn function pointer to be stored as callback.
428   * @retval HAL Status.
429   */
HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef * hexti,EXTI_CallbackIDTypeDef CallbackID,void (* pPendingCbfn)(void))430 HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID, void (*pPendingCbfn)(void))
431 {
432   HAL_StatusTypeDef status = HAL_OK;
433 
434   switch (CallbackID)
435   {
436     case  HAL_EXTI_COMMON_CB_ID:
437       hexti->RisingCallback = pPendingCbfn;
438       hexti->FallingCallback = pPendingCbfn;
439       break;
440 
441     case  HAL_EXTI_RISING_CB_ID:
442       hexti->RisingCallback = pPendingCbfn;
443       break;
444 
445     case  HAL_EXTI_FALLING_CB_ID:
446       hexti->FallingCallback = pPendingCbfn;
447       break;
448 
449     default:
450       status = HAL_ERROR;
451       break;
452   }
453 
454   return status;
455 }
456 
457 
458 /**
459   * @brief  Store line number as handle private field.
460   * @param  hexti Exti handle.
461   * @param  ExtiLine Exti line number.
462   *         This parameter can be from 0 to @ref EXTI_LINE_NB.
463   * @retval HAL Status.
464   */
HAL_EXTI_GetHandle(EXTI_HandleTypeDef * hexti,uint32_t ExtiLine)465 HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
466 {
467   /* Check the parameters */
468   assert_param(IS_EXTI_LINE(ExtiLine));
469 
470   /* Check null pointer */
471   if (hexti == NULL)
472   {
473     return HAL_ERROR;
474   }
475   else
476   {
477     /* Store line number as handle private field */
478     hexti->Line = ExtiLine;
479 
480     return HAL_OK;
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(const EXTI_HandleTypeDef * hexti)505 void HAL_EXTI_IRQHandler(const 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 rising edge pending bit  */
517   regaddr = (__IO uint32_t *)(&EXTI->RPR1 + (EXTI_CONFIG_OFFSET * offset));
518   regval = (*regaddr & maskline);
519 
520   if (regval != 0U)
521   {
522     /* Clear pending bit */
523     *regaddr = maskline;
524 
525     /* Call rising callback */
526     if (hexti->RisingCallback != NULL)
527     {
528       hexti->RisingCallback();
529     }
530   }
531 
532   /* Get falling edge pending bit  */
533   regaddr = (__IO uint32_t *)(&EXTI->FPR1 + (EXTI_CONFIG_OFFSET * offset));
534   regval = (*regaddr & maskline);
535 
536   if (regval != 0U)
537   {
538     /* Clear pending bit */
539     *regaddr = maskline;
540 
541     /* Call rising callback */
542     if (hexti->FallingCallback != NULL)
543     {
544       hexti->FallingCallback();
545     }
546   }
547 }
548 
549 
550 /**
551   * @brief  Get interrupt pending bit of a dedicated line.
552   * @param  hexti Exti handle.
553   * @param  Edge Specify which pending edge as to be checked.
554   *         This parameter can be one of the following values:
555   *           @arg @ref EXTI_TRIGGER_RISING
556   *           @arg @ref EXTI_TRIGGER_FALLING
557   * @retval 1 if interrupt is pending else 0.
558   */
HAL_EXTI_GetPending(const EXTI_HandleTypeDef * hexti,uint32_t Edge)559 uint32_t HAL_EXTI_GetPending(const EXTI_HandleTypeDef *hexti, uint32_t Edge)
560 {
561   const __IO uint32_t *regaddr;
562   uint32_t regval;
563   uint32_t linepos;
564   uint32_t maskline;
565   uint32_t offset;
566 
567   /* Check the parameters */
568   assert_param(IS_EXTI_LINE(hexti->Line));
569   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
570   assert_param(IS_EXTI_PENDING_EDGE(Edge));
571 
572   /* compute line register offset and line mask */
573   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
574   linepos = (hexti->Line & EXTI_PIN_MASK);
575   maskline = (1UL << linepos);
576 
577   if (Edge != EXTI_TRIGGER_RISING)
578   {
579     /* Get falling edge pending bit */
580     regaddr = (__IO uint32_t *)(&EXTI->FPR1 + (EXTI_CONFIG_OFFSET * offset));
581   }
582   else
583   {
584     /* Get rising edge pending bit */
585     regaddr = (__IO uint32_t *)(&EXTI->RPR1 + (EXTI_CONFIG_OFFSET * offset));
586   }
587 
588   /* return 1 if bit is set else 0 */
589   regval = ((*regaddr & maskline) >> linepos);
590   return regval;
591 }
592 
593 
594 /**
595   * @brief  Clear interrupt pending bit of a dedicated line.
596   * @param  hexti Exti handle.
597   * @param  Edge Specify which pending edge as to be clear.
598   *         This parameter can be one of the following values:
599   *           @arg @ref EXTI_TRIGGER_RISING
600   *           @arg @ref EXTI_TRIGGER_FALLING
601   * @retval None.
602   */
HAL_EXTI_ClearPending(const EXTI_HandleTypeDef * hexti,uint32_t Edge)603 void HAL_EXTI_ClearPending(const EXTI_HandleTypeDef *hexti, uint32_t Edge)
604 {
605   __IO uint32_t *regaddr;
606   uint32_t maskline;
607   uint32_t offset;
608 
609   /* Check the parameters */
610   assert_param(IS_EXTI_LINE(hexti->Line));
611   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
612   assert_param(IS_EXTI_PENDING_EDGE(Edge));
613 
614   /* compute line register offset and line mask */
615   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
616   maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
617 
618   if (Edge != EXTI_TRIGGER_RISING)
619   {
620     /* Get falling edge pending register address */
621     regaddr = (__IO uint32_t *)(&EXTI->FPR1 + (EXTI_CONFIG_OFFSET * offset));
622   }
623   else
624   {
625     /* Get falling edge pending register address */
626     regaddr = (__IO uint32_t *)(&EXTI->RPR1 + (EXTI_CONFIG_OFFSET * offset));
627   }
628 
629   /* Clear Pending bit */
630   *regaddr =  maskline;
631 }
632 
633 
634 /**
635   * @brief  Generate a software interrupt for a dedicated line.
636   * @param  hexti Exti handle.
637   * @retval None.
638   */
HAL_EXTI_GenerateSWI(const EXTI_HandleTypeDef * hexti)639 void HAL_EXTI_GenerateSWI(const EXTI_HandleTypeDef *hexti)
640 {
641   __IO uint32_t *regaddr;
642   uint32_t maskline;
643   uint32_t offset;
644 
645   /* Check the parameters */
646   assert_param(IS_EXTI_LINE(hexti->Line));
647   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
648 
649   /* compute line register offset and line mask */
650   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
651   maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
652 
653   regaddr = (__IO uint32_t *)(&EXTI->SWIER1 + (EXTI_CONFIG_OFFSET * offset));
654   *regaddr = maskline;
655 }
656 
657 
658 /**
659   * @}
660   */
661 
662 /** @defgroup EXTI_Exported_Functions_Group3 EXTI line attributes management functions
663   *  @brief EXTI attributes management functions.
664   *
665 @verbatim
666  ===============================================================================
667                        ##### EXTI attributes functions #####
668  ===============================================================================
669 
670 @endverbatim
671   * @{
672   */
673 
674 #if defined(EXTI_SECCFGR1_SEC0)
675 /**
676   * @brief  Configure the EXTI line attribute(s).
677   * @note   Available attributes are to secure EXTI line and set EXT line as privileged.
678   *         Default state is not secure and unprivileged access allowed.
679   * @note   Secure and non-secure attributes can only be set from the secure
680   *         state when the system implements the security (TZEN=1).
681   * @note   Security and privilege attributes can be set independently.
682   * @param  ExtiLine Exti line number.
683   *         This parameter can be from 0 to @ref EXTI_LINE_NB.
684   * @param  LineAttributes can be one or a combination of the following values:
685   *            @arg @ref EXTI_LINE_PRIV         Privileged-only access
686   *            @arg @ref EXTI_LINE_NPRIV        Privileged/Non-privileged access
687   *            @arg @ref EXTI_LINE_SEC          Secure-only access
688   *            @arg @ref EXTI_LINE_NSEC         Secure/Non-secure access
689   * @retval None
690   */
HAL_EXTI_ConfigLineAttributes(uint32_t ExtiLine,uint32_t LineAttributes)691 void HAL_EXTI_ConfigLineAttributes(uint32_t ExtiLine, uint32_t LineAttributes)
692 {
693   __IO uint32_t *regaddr;
694   uint32_t regval;
695   uint32_t linepos;
696   uint32_t maskline;
697   uint32_t offset;
698 
699   /* Check the parameters */
700   assert_param(IS_EXTI_LINE(ExtiLine));
701   assert_param(IS_EXTI_LINE_ATTRIBUTES(LineAttributes));
702 
703   /* compute line register offset and line mask */
704   offset = ((ExtiLine & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
705   linepos = (ExtiLine & EXTI_PIN_MASK);
706   maskline = (1UL << linepos);
707 
708   /* Configure privilege or non-privilege attributes */
709   regaddr = (__IO uint32_t *)(&EXTI->PRIVCFGR1 + (EXTI_PRIVCFGR_OFFSET * offset));
710   regval = *regaddr;
711 
712   /* Mask or set line */
713   if ((LineAttributes & EXTI_LINE_PRIV) == EXTI_LINE_PRIV)
714   {
715     regval |= maskline;
716   }
717   else if ((LineAttributes & EXTI_LINE_NPRIV) == EXTI_LINE_NPRIV)
718   {
719     regval &= ~maskline;
720   }
721   else
722   {
723     /* do nothing */
724   }
725 
726   /* Store privilege or non-privilege attribute */
727   *regaddr = regval;
728 
729 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
730 
731   /* Configure secure or non-secure attributes */
732   regaddr = (__IO uint32_t *)(&EXTI->SECCFGR1 + (EXTI_SECCFGR_OFFSET * offset));
733   regval = *regaddr;
734 
735   /* Mask or set line */
736   if ((LineAttributes & EXTI_LINE_SEC) == EXTI_LINE_SEC)
737   {
738     regval |= maskline;
739   }
740   else if ((LineAttributes & EXTI_LINE_NSEC) == EXTI_LINE_NSEC)
741   {
742     regval &= ~maskline;
743   }
744   else
745   {
746     /* do nothing */
747   }
748 
749   /* Store secure or non-secure attribute */
750   *regaddr = regval;
751 
752 #endif /* __ARM_FEATURE_CMSE */
753 }
754 
755 /**
756   * @brief  Get the EXTI line attribute(s).
757   * @note   Secure and non-secure attributes are only available from secure state
758   *         when the system implements the security (TZEN=1)
759   * @param  ExtiLine Exti line number.
760   *         This parameter can be from 0 to @ref EXTI_LINE_NB.
761   * @param  pLineAttributes: pointer to return line attributes.
762   * @retval HAL Status.
763   */
HAL_EXTI_GetConfigLineAttributes(uint32_t ExtiLine,uint32_t * pLineAttributes)764 HAL_StatusTypeDef HAL_EXTI_GetConfigLineAttributes(uint32_t ExtiLine, uint32_t *pLineAttributes)
765 {
766   const __IO uint32_t *regaddr;
767   uint32_t linepos;
768   uint32_t maskline;
769   uint32_t offset;
770   uint32_t attributes;
771 
772   /* Check null pointer */
773   if (pLineAttributes == NULL)
774   {
775     return HAL_ERROR;
776   }
777 
778   /* Check the parameters */
779   assert_param(IS_EXTI_LINE(ExtiLine));
780 
781   /* Compute line register offset and line mask */
782   offset = ((ExtiLine & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
783   linepos = (ExtiLine & EXTI_PIN_MASK);
784   maskline = (1UL << linepos);
785 
786   /* Get privilege or non-privilege attribute */
787   regaddr = (__IO uint32_t *)(&EXTI->PRIVCFGR1 + (EXTI_PRIVCFGR_OFFSET * offset));
788 
789   if ((*regaddr & maskline) != 0U)
790   {
791     attributes = EXTI_LINE_PRIV;
792   }
793   else
794   {
795     attributes = EXTI_LINE_NPRIV;
796   }
797 
798 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
799 
800   /* Get secure or non-secure attribute */
801   regaddr = (__IO uint32_t *)(&EXTI->SECCFGR1 + (EXTI_SECCFGR_OFFSET * offset));
802 
803   if ((*regaddr & maskline) != 0U)
804   {
805     attributes |= EXTI_LINE_SEC;
806   }
807   else
808   {
809     attributes |= EXTI_LINE_NSEC;
810   }
811 
812 #endif /* __ARM_FEATURE_CMSE */
813 
814   /* return value */
815   *pLineAttributes = attributes;
816 
817   return HAL_OK;
818 }
819 #endif /* #if defined(EXTI_SECCFGR1_SEC0) */
820 
821 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
822 /**
823   * @brief  Lock the secure and privilege configuration registers.
824   * @retval None
825   */
HAL_EXTI_LockAttributes(void)826 void HAL_EXTI_LockAttributes(void)
827 {
828   SET_BIT(EXTI->LOCKR, EXTI_LOCKR_LOCK);
829 }
830 
831 /**
832   * @brief  Return the secure and privilege configuration registers LOCK status
833   * @retval 1 if the secure and privilege configuration registers have been locked else 0.
834   */
HAL_EXTI_GetLockAttributes(void)835 uint32_t HAL_EXTI_GetLockAttributes(void)
836 {
837   return READ_BIT(EXTI->LOCKR, EXTI_LOCKR_LOCK);
838 }
839 #endif /* __ARM_FEATURE_CMSE */
840 
841 /**
842   * @}
843   */
844 
845 /**
846   * @}
847   */
848 
849 #endif /* HAL_EXTI_MODULE_ENABLED */
850 /**
851   * @}
852   */
853 
854 /**
855   * @}
856   */
857 
858