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