1 /**
2   ******************************************************************************
3   * @file    stm32h7xx_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) 2017 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 (CORE1 or CORE2 in case of dual core line )
31         (++) Event (CORE1 or CORE2 in case of dual core line )
32         (++) a combination of the previous
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     (+) PendClearSource used to set the D3 Smart Run Domain autoamtic pend clear source.
49         It is applicable for line with wkaeup target is Any (CPU1 , CPU2 and D3 smart run domain).
50         Value can be one of the following:
51         (++)  EXTI_D3_PENDCLR_SRC_NONE : no pend clear source is selected :
52               In this case corresponding bit of D2PMRx register is set to 0
53                 (+++) On a configurable Line : the D3 domain wakeup signal is
54                       automatically cleared after after the Delay + Rising Edge detect
55                 (+++) On a direct Line : the D3 domain wakeup signal is
56                       cleared after the direct event input signal is cleared
57 
58         (++)  EXTI_D3_PENDCLR_SRC_DMACH6 : no pend clear source is selected :
59               In this case corresponding bit of D2PMRx register is set to 1
60               and corresponding bits(2) of D3PCRxL/H is set to b00 :
61                 DMA ch6 event selected as D3 domain pendclear source
62 
63         (++)  EXTI_D3_PENDCLR_SRC_DMACH7 : no pend clear source is selected :
64               In this case corresponding bit of D2PMRx register is set to 1
65               and corresponding bits(2) of D3PCRxL/H is set to b01 :
66                 DMA ch7 event selected as D3 domain pendclear source
67 
68         (++)  EXTI_D3_PENDCLR_SRC_LPTIM4 : no pend clear source is selected :
69               In this case corresponding bit of D2PMRx register is set to 1
70               and corresponding bits(2) of D3PCRxL/H is set to b10 :
71                 LPTIM4 out selected as D3 domain pendclear source
72 
73         (++)  EXTI_D3_PENDCLR_SRC_LPTIM5 : no pend clear source is selected :
74               In this case corresponding bit of D2PMRx register is set to 1
75               and corresponding bits(2) of D3PCRxL/H is set to b11 :
76                 LPTIM5 out selected as D3 domain pendclear source
77 
78 
79                      ##### How to use this driver #####
80   ==============================================================================
81   [..]
82 
83     (#) Configure the EXTI line using HAL_EXTI_SetConfigLine().
84         (++) Choose the interrupt line number by setting "Line" member from
85              EXTI_ConfigTypeDef structure.
86         (++) Configure the interrupt and/or event mode using "Mode" member from
87              EXTI_ConfigTypeDef structure.
88         (++) For configurable lines, configure rising and/or falling trigger
89              "Trigger" member from EXTI_ConfigTypeDef structure.
90         (++) For Exti lines linked to gpio, choose gpio port using "GPIOSel"
91              member from GPIO_InitTypeDef structure.
92         (++) For Exti lines with wkaeup target is Any (CPU1 , CPU2 and D3 smart run domain),
93              choose gpio D3 PendClearSource using PendClearSource
94              member from EXTI_PendClear_Source structure.
95 
96     (#) Get current Exti configuration of a dedicated line using
97         HAL_EXTI_GetConfigLine().
98         (++) Provide exiting handle as parameter.
99         (++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
100 
101     (#) Clear Exti configuration of a dedicated line using HAL_EXTI_GetConfigLine().
102         (++) Provide exiting handle as parameter.
103 
104     (#) Register callback to treat Exti interrupts using HAL_EXTI_RegisterCallback().
105         (++) Provide exiting handle as first parameter.
106         (++) Provide which callback will be registered using one value from
107              EXTI_CallbackIDTypeDef.
108         (++) Provide callback function pointer.
109 
110     (#) Get interrupt pending bit using HAL_EXTI_GetPending().
111 
112     (#) Clear interrupt pending bit using HAL_EXTI_GetPending().
113 
114     (#) Generate software interrupt using HAL_EXTI_GenerateSWI().
115 
116   @endverbatim
117   */
118 
119 /* Includes ------------------------------------------------------------------*/
120 #include "stm32h7xx_hal.h"
121 
122 /** @addtogroup STM32H7xx_HAL_Driver
123   * @{
124   */
125 
126 /** @addtogroup EXTI
127   * @{
128   */
129 
130 #ifdef HAL_EXTI_MODULE_ENABLED
131 
132 /* Private typedef -----------------------------------------------------------*/
133 /* Private defines ------------------------------------------------------------*/
134 /** @defgroup EXTI_Private_Constants EXTI Private Constants
135   * @{
136   */
137 #define EXTI_MODE_OFFSET                    0x04U   /* 0x10: offset between CPU IMR/EMR registers */
138 #define EXTI_CONFIG_OFFSET                  0x08U   /* 0x20: offset between CPU Rising/Falling configuration registers */
139 /**
140   * @}
141   */
142 
143 /* Private macros ------------------------------------------------------------*/
144 /* Private variables ---------------------------------------------------------*/
145 /* Private function prototypes -----------------------------------------------*/
146 /* Exported functions --------------------------------------------------------*/
147 
148 /** @addtogroup EXTI_Exported_Functions
149   * @{
150   */
151 
152 /** @addtogroup EXTI_Exported_Functions_Group1
153  *  @brief    Configuration functions
154  *
155 @verbatim
156  ===============================================================================
157               ##### Configuration functions #####
158  ===============================================================================
159 
160 @endverbatim
161   * @{
162   */
163 
164 /**
165   * @brief  Set configuration of a dedicated Exti line.
166   * @param  hexti Exti handle.
167   * @param  pExtiConfig Pointer on EXTI configuration to be set.
168   * @retval HAL Status.
169   */
HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef * hexti,EXTI_ConfigTypeDef * pExtiConfig)170 HAL_StatusTypeDef HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
171 {
172   __IO uint32_t *regaddr;
173   uint32_t regval;
174   uint32_t linepos;
175   uint32_t maskline;
176   uint32_t offset;
177   uint32_t pcrlinepos;
178 
179   /* Check null pointer */
180   if ((hexti == NULL) || (pExtiConfig == NULL))
181   {
182     return HAL_ERROR;
183   }
184 
185   /* Check the parameters */
186   assert_param(IS_EXTI_LINE(pExtiConfig->Line));
187   assert_param(IS_EXTI_MODE(pExtiConfig->Mode));
188 
189   /* Assign line number to handle */
190   hexti->Line = pExtiConfig->Line;
191 
192   /* compute line register offset and line mask */
193   offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
194   linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
195   maskline = (1UL << linepos);
196 
197   /* Configure triggers for configurable lines */
198   if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00U)
199   {
200     assert_param(IS_EXTI_TRIGGER(pExtiConfig->Trigger));
201 
202     /* Configure rising trigger */
203     regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
204     regval = *regaddr;
205 
206     /* Mask or set line */
207     if ((pExtiConfig->Trigger & EXTI_TRIGGER_RISING) != 0x00U)
208     {
209       regval |= maskline;
210     }
211     else
212     {
213       regval &= ~maskline;
214     }
215 
216     /* Store rising trigger mode */
217     *regaddr = regval;
218 
219     /* Configure falling trigger */
220     regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
221     regval = *regaddr;
222 
223     /* Mask or set line */
224     if ((pExtiConfig->Trigger & EXTI_TRIGGER_FALLING) != 0x00U)
225     {
226       regval |= maskline;
227     }
228     else
229     {
230       regval &= ~maskline;
231     }
232 
233     /* Store falling trigger mode */
234     *regaddr = regval;
235 
236     /* Configure gpio port selection in case of gpio exti line */
237     if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
238     {
239       assert_param(IS_EXTI_GPIO_PORT(pExtiConfig->GPIOSel));
240       assert_param(IS_EXTI_GPIO_PIN(linepos));
241 
242       regval = SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL];
243       regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03U)));
244       regval |= (pExtiConfig->GPIOSel << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03U)));
245       SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL] = regval;
246     }
247   }
248 
249   /* Configure interrupt mode : read current mode */
250   regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
251   regval = *regaddr;
252 
253   /* Mask or set line */
254   if ((pExtiConfig->Mode & EXTI_MODE_INTERRUPT) != 0x00U)
255   {
256     regval |= maskline;
257   }
258   else
259   {
260     regval &= ~maskline;
261   }
262 
263   /* Store interrupt mode */
264   *regaddr = regval;
265 
266   /* The event mode cannot be configured if the line does not support it */
267   assert_param(((pExtiConfig->Line & EXTI_EVENT) == EXTI_EVENT) || ((pExtiConfig->Mode & EXTI_MODE_EVENT) != EXTI_MODE_EVENT));
268 
269   /* Configure event mode : read current mode */
270   regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
271   regval = *regaddr;
272 
273   /* Mask or set line */
274   if ((pExtiConfig->Mode & EXTI_MODE_EVENT) != 0x00U)
275   {
276     regval |= maskline;
277   }
278   else
279   {
280     regval &= ~maskline;
281   }
282 
283   /* Store event mode */
284   *regaddr = regval;
285 
286 #if defined (DUAL_CORE)
287   /* Configure interrupt mode for Core2 : read current mode */
288   regaddr = (__IO uint32_t *)(&EXTI->C2IMR1 + (EXTI_MODE_OFFSET * offset));
289   regval = *regaddr;
290 
291   /* Mask or set line */
292   if ((pExtiConfig->Mode & EXTI_MODE_CORE2_INTERRUPT) != 0x00U)
293   {
294     regval |= maskline;
295   }
296   else
297   {
298     regval &= ~maskline;
299   }
300 
301   /* Store interrupt mode */
302   *regaddr = regval;
303 
304   /* The event mode cannot be configured if the line does not support it */
305   assert_param(((pExtiConfig->Line & EXTI_EVENT) == EXTI_EVENT) || ((pExtiConfig->Mode & EXTI_MODE_CORE2_EVENT) != EXTI_MODE_CORE2_EVENT));
306 
307   /* Configure event mode : read current mode */
308   regaddr = (__IO uint32_t *)(&EXTI->C2EMR1 + (EXTI_MODE_OFFSET * offset));
309   regval = *regaddr;
310 
311   /* Mask or set line */
312   if ((pExtiConfig->Mode & EXTI_MODE_CORE2_EVENT) != 0x00U)
313   {
314     regval |= maskline;
315   }
316   else
317   {
318     regval &= ~maskline;
319   }
320 
321   /* Store event mode */
322   *regaddr = regval;
323 #endif /* DUAL_CORE */
324 
325   /* Configure the D3 PendClear source in case of Wakeup target is Any */
326   if ((pExtiConfig->Line & EXTI_TARGET_MASK) == EXTI_TARGET_MSK_ALL)
327   {
328     assert_param(IS_EXTI_D3_PENDCLR_SRC(pExtiConfig->PendClearSource));
329 
330     /*Calc the PMR register address for the given line */
331     regaddr = (__IO uint32_t *)(&EXTI->D3PMR1 + (EXTI_CONFIG_OFFSET * offset));
332     regval = *regaddr;
333 
334     if(pExtiConfig->PendClearSource == EXTI_D3_PENDCLR_SRC_NONE)
335     {
336       /* Clear D3PMRx register for the given line */
337       regval &= ~maskline;
338       /* Store D3PMRx register value */
339       *regaddr = regval;
340     }
341     else
342     {
343       /* Set D3PMRx register to 1 for the given line */
344       regval |= maskline;
345       /* Store D3PMRx register value */
346       *regaddr = regval;
347 
348       if(linepos < 16UL)
349       {
350         regaddr = (__IO uint32_t *)(&EXTI->D3PCR1L + (EXTI_CONFIG_OFFSET * offset));
351         pcrlinepos = 1UL << linepos;
352       }
353       else
354       {
355         regaddr = (__IO uint32_t *)(&EXTI->D3PCR1H + (EXTI_CONFIG_OFFSET * offset));
356         pcrlinepos = 1UL << (linepos - 16UL);
357       }
358 
359       regval = (*regaddr & (~(pcrlinepos * pcrlinepos * 3UL))) | (pcrlinepos * pcrlinepos * (pExtiConfig->PendClearSource - 1UL));
360       *regaddr = regval;
361     }
362   }
363 
364   return HAL_OK;
365 }
366 
367 
368 /**
369   * @brief  Get configuration of a dedicated Exti line.
370   * @param  hexti Exti handle.
371   * @param  pExtiConfig Pointer on structure to store Exti configuration.
372   * @retval HAL Status.
373   */
HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef * hexti,EXTI_ConfigTypeDef * pExtiConfig)374 HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
375 {
376   __IO uint32_t *regaddr;
377   uint32_t regval;
378   uint32_t linepos;
379   uint32_t maskline;
380   uint32_t offset;
381   uint32_t pcrlinepos;
382 
383   /* Check null pointer */
384   if ((hexti == NULL) || (pExtiConfig == NULL))
385   {
386     return HAL_ERROR;
387   }
388 
389   /* Check the parameter */
390   assert_param(IS_EXTI_LINE(hexti->Line));
391 
392   /* Store handle line number to configuration structure */
393   pExtiConfig->Line = hexti->Line;
394 
395   /* compute line register offset and line mask */
396   offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
397   linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
398   maskline = (1UL << linepos);
399 
400   /* 1] Get core mode : interrupt */
401   regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
402   regval = *regaddr;
403 
404   pExtiConfig->Mode = EXTI_MODE_NONE;
405 
406   /* Check if selected line is enable */
407   if ((regval & maskline) != 0x00U)
408   {
409     pExtiConfig->Mode = EXTI_MODE_INTERRUPT;
410   }
411 
412   /* Get event mode */
413   regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
414   regval = *regaddr;
415 
416   /* Check if selected line is enable */
417   if ((regval & maskline) != 0x00U)
418   {
419     pExtiConfig->Mode |= EXTI_MODE_EVENT;
420   }
421 #if defined (DUAL_CORE)
422   regaddr = (__IO uint32_t *)(&EXTI->C2IMR1 + (EXTI_MODE_OFFSET * offset));
423   regval = *regaddr;
424 
425   /* Check if selected line is enable */
426   if ((regval & maskline) != 0x00U)
427   {
428     pExtiConfig->Mode = EXTI_MODE_CORE2_INTERRUPT;
429   }
430 
431   /* Get event mode */
432   regaddr = (__IO uint32_t *)(&EXTI->C2EMR1 + (EXTI_MODE_OFFSET * offset));
433   regval = *regaddr;
434 
435   /* Check if selected line is enable */
436   if ((regval & maskline) != 0x00U)
437   {
438     pExtiConfig->Mode |= EXTI_MODE_CORE2_EVENT;
439   }
440 #endif /*DUAL_CORE*/
441 
442   /* Get default Trigger and GPIOSel configuration */
443   pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
444   pExtiConfig->GPIOSel = 0x00U;
445 
446   /* 2] Get trigger for configurable lines : rising */
447   if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00U)
448   {
449     regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
450     regval = *regaddr;
451 
452     /* Check if configuration of selected line is enable */
453     if ((regval & maskline) != 0x00U)
454     {
455       pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
456     }
457 
458     /* Get falling configuration */
459     regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
460     regval = *regaddr;
461 
462     /* Check if configuration of selected line is enable */
463     if ((regval & maskline) != 0x00U)
464     {
465       pExtiConfig->Trigger |= EXTI_TRIGGER_FALLING;
466     }
467 
468     /* Get Gpio port selection for gpio lines */
469     if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
470     {
471       assert_param(IS_EXTI_GPIO_PIN(linepos));
472 
473       regval = SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL];
474       pExtiConfig->GPIOSel = (regval >> (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u))) & SYSCFG_EXTICR1_EXTI0;
475     }
476   }
477 
478   /* Get default Pend Clear Source */
479   pExtiConfig->PendClearSource = EXTI_D3_PENDCLR_SRC_NONE;
480 
481   /* 3] Get D3 Pend Clear source */
482   if ((pExtiConfig->Line & EXTI_TARGET_MASK) == EXTI_TARGET_MSK_ALL)
483   {
484     regaddr = (__IO uint32_t *)(&EXTI->D3PMR1 + (EXTI_CONFIG_OFFSET * offset));
485     if(((*regaddr) & linepos) != 0UL)
486     {
487       /* if wakeup target is any and PMR set, the read pend clear source from  D3PCRxL/H */
488       if(linepos < 16UL)
489       {
490         regaddr = (__IO uint32_t *)(&EXTI->D3PCR1L + (EXTI_CONFIG_OFFSET * offset));
491         pcrlinepos = 1UL << linepos;
492       }
493       else
494       {
495         regaddr = (__IO uint32_t *)(&EXTI->D3PCR1H + (EXTI_CONFIG_OFFSET * offset));
496         pcrlinepos = 1UL << (linepos - 16UL);
497       }
498 
499       pExtiConfig->PendClearSource = 1UL + ((*regaddr & (pcrlinepos * pcrlinepos * 3UL)) / (pcrlinepos * pcrlinepos));
500     }
501   }
502 
503   return HAL_OK;
504 }
505 
506 
507 /**
508   * @brief  Clear whole configuration of a dedicated Exti line.
509   * @param  hexti Exti handle.
510   * @retval HAL Status.
511   */
HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef * hexti)512 HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
513 {
514   __IO uint32_t *regaddr;
515   uint32_t regval;
516   uint32_t linepos;
517   uint32_t maskline;
518   uint32_t offset;
519   uint32_t pcrlinepos;
520 
521   /* Check null pointer */
522   if (hexti == NULL)
523   {
524     return HAL_ERROR;
525   }
526 
527   /* Check the parameter */
528   assert_param(IS_EXTI_LINE(hexti->Line));
529 
530   /* compute line register offset and line mask */
531   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
532   linepos = (hexti->Line & EXTI_PIN_MASK);
533   maskline = (1UL << linepos);
534 
535   /* 1] Clear interrupt mode */
536   regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
537   regval = (*regaddr & ~maskline);
538   *regaddr = regval;
539 
540   /* 2] Clear event mode */
541   regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
542   regval = (*regaddr & ~maskline);
543   *regaddr = regval;
544 
545 #if defined (DUAL_CORE)
546     /* 1] Clear CM4 interrupt mode */
547   regaddr = (__IO uint32_t *)(&EXTI->C2IMR1 + (EXTI_MODE_OFFSET * offset));
548   regval = (*regaddr & ~maskline);
549   *regaddr = regval;
550 
551   /* 2] Clear CM4 event mode */
552   regaddr = (__IO uint32_t *)(&EXTI->C2EMR1 + (EXTI_MODE_OFFSET * offset));
553   regval = (*regaddr & ~maskline);
554   *regaddr = regval;
555 #endif /* DUAL_CORE */
556 
557   /* 3] Clear triggers in case of configurable lines */
558   if ((hexti->Line & EXTI_CONFIG) != 0x00U)
559   {
560     regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
561     regval = (*regaddr & ~maskline);
562     *regaddr = regval;
563 
564     regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
565     regval = (*regaddr & ~maskline);
566     *regaddr = regval;
567 
568     /* Get Gpio port selection for gpio lines */
569     if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
570     {
571       assert_param(IS_EXTI_GPIO_PIN(linepos));
572 
573       regval = SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL];
574       regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03UL)));
575       SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL] = regval;
576     }
577   }
578 
579   /* 4] Clear D3 Config lines */
580   if ((hexti->Line & EXTI_TARGET_MASK) == EXTI_TARGET_MSK_ALL)
581   {
582     regaddr = (__IO uint32_t *)(&EXTI->D3PMR1 + (EXTI_CONFIG_OFFSET * offset));
583     *regaddr = (*regaddr & ~maskline);
584 
585     if(linepos < 16UL)
586     {
587       regaddr = (__IO uint32_t *)(&EXTI->D3PCR1L + (EXTI_CONFIG_OFFSET * offset));
588       pcrlinepos = 1UL << linepos;
589     }
590     else
591     {
592       regaddr = (__IO uint32_t *)(&EXTI->D3PCR1H + (EXTI_CONFIG_OFFSET * offset));
593       pcrlinepos = 1UL << (linepos - 16UL);
594     }
595 
596     /*Clear D3 PendClear source */
597     *regaddr &= (~(pcrlinepos * pcrlinepos * 3UL));
598   }
599 
600   return HAL_OK;
601 }
602 
603 
604 /**
605   * @brief  Register callback for a dedicated Exti line.
606   * @param  hexti Exti handle.
607   * @param  CallbackID User callback identifier.
608   *         This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
609   * @param  pPendingCbfn function pointer to be stored as callback.
610   * @retval HAL Status.
611   */
HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef * hexti,EXTI_CallbackIDTypeDef CallbackID,void (* pPendingCbfn)(void))612 HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID, void (*pPendingCbfn)(void))
613 {
614   HAL_StatusTypeDef status = HAL_OK;
615 
616   /* Check null pointer */
617   if (hexti == NULL)
618   {
619     return HAL_ERROR;
620   }
621 
622   switch (CallbackID)
623   {
624     case  HAL_EXTI_COMMON_CB_ID:
625       hexti->PendingCallback = pPendingCbfn;
626       break;
627 
628     default:
629       status = HAL_ERROR;
630       break;
631   }
632 
633   return status;
634 }
635 
636 
637 /**
638   * @brief  Store line number as handle private field.
639   * @param  hexti Exti handle.
640   * @param  ExtiLine Exti line number.
641   *         This parameter can be from 0 to @ref EXTI_LINE_NB.
642   * @retval HAL Status.
643   */
HAL_EXTI_GetHandle(EXTI_HandleTypeDef * hexti,uint32_t ExtiLine)644 HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
645 {
646   /* Check the parameters */
647   assert_param(IS_EXTI_LINE(ExtiLine));
648 
649   /* Check null pointer */
650   if (hexti == NULL)
651   {
652     return HAL_ERROR;
653   }
654   else
655   {
656     /* Store line number as handle private field */
657     hexti->Line = ExtiLine;
658 
659     return HAL_OK;
660   }
661 }
662 
663 
664 /**
665   * @}
666   */
667 
668 /** @addtogroup EXTI_Exported_Functions_Group2
669  *  @brief EXTI IO functions.
670  *
671 @verbatim
672  ===============================================================================
673                        ##### IO operation functions #####
674  ===============================================================================
675 
676 @endverbatim
677   * @{
678   */
679 
680 /**
681   * @brief  Handle EXTI interrupt request.
682   * @param  hexti Exti handle.
683   * @retval none.
684   */
HAL_EXTI_IRQHandler(EXTI_HandleTypeDef * hexti)685 void HAL_EXTI_IRQHandler(EXTI_HandleTypeDef *hexti)
686 {
687   __IO uint32_t *regaddr;
688   uint32_t regval;
689   uint32_t maskline;
690   uint32_t offset;
691 
692   /* Compute line register offset and line mask */
693   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
694   maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
695 
696 #if defined(DUAL_CORE)
697   if (HAL_GetCurrentCPUID() == CM7_CPUID)
698   {
699     /* Get pending register address */
700     regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
701   }
702   else /* Cortex-M4*/
703   {
704     /* Get pending register address */
705     regaddr = (__IO uint32_t *)(&EXTI->C2PR1 + (EXTI_MODE_OFFSET * offset));
706   }
707 #else
708   regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
709 #endif /* DUAL_CORE */
710 
711   /* Get pending bit  */
712   regval = (*regaddr & maskline);
713 
714   if (regval != 0x00U)
715   {
716     /* Clear pending bit */
717     *regaddr = maskline;
718 
719     /* Call callback */
720     if (hexti->PendingCallback != NULL)
721     {
722       hexti->PendingCallback();
723     }
724   }
725 }
726 
727 
728 /**
729   * @brief  Get interrupt pending bit of a dedicated line.
730   * @param  hexti Exti handle.
731   * @param  Edge Specify which pending edge as to be checked.
732   *         This parameter can be one of the following values:
733   *           @arg @ref EXTI_TRIGGER_RISING_FALLING
734   *         This parameter is kept for compatibility with other series.
735   * @retval 1 if interrupt is pending else 0.
736   */
HAL_EXTI_GetPending(EXTI_HandleTypeDef * hexti,uint32_t Edge)737 uint32_t HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
738 {
739   __IO uint32_t *regaddr;
740   uint32_t regval;
741   uint32_t linepos;
742   uint32_t maskline;
743   uint32_t offset;
744 
745   /* Check parameters */
746   assert_param(IS_EXTI_LINE(hexti->Line));
747   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
748   assert_param(IS_EXTI_PENDING_EDGE(Edge));
749 
750   /* compute line register offset and line mask */
751   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
752   linepos = (hexti->Line & EXTI_PIN_MASK);
753   maskline = (1UL << linepos);
754 
755 #if defined(DUAL_CORE)
756   if (HAL_GetCurrentCPUID() == CM7_CPUID)
757   {
758     /* Get pending register address */
759     regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
760   }
761   else /* Cortex-M4 */
762   {
763     /* Get pending register address */
764     regaddr = (__IO uint32_t *)(&EXTI->C2PR1 + (EXTI_MODE_OFFSET * offset));
765   }
766 #else
767   regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
768 #endif /* DUAL_CORE */
769 
770   /* return 1 if bit is set else 0 */
771   regval = ((*regaddr & maskline) >> linepos);
772   return regval;
773 }
774 
775 
776 /**
777   * @brief  Clear interrupt pending bit of a dedicated line.
778   * @param  hexti Exti handle.
779   * @param  Edge Specify which pending edge as to be clear.
780   *         This parameter can be one of the following values:
781   *           @arg @ref EXTI_TRIGGER_RISING_FALLING
782   *         This parameter is kept for compatibility with other series.
783   * @retval None.
784   */
HAL_EXTI_ClearPending(EXTI_HandleTypeDef * hexti,uint32_t Edge)785 void HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
786 {
787   __IO uint32_t *regaddr;
788   uint32_t maskline;
789   uint32_t offset;
790 
791   /* Check parameters */
792   assert_param(IS_EXTI_LINE(hexti->Line));
793   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
794   assert_param(IS_EXTI_PENDING_EDGE(Edge));
795 
796   /* compute line register offset and line mask */
797   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
798   maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
799 
800 #if defined(DUAL_CORE)
801   if (HAL_GetCurrentCPUID() == CM7_CPUID)
802   {
803     /* Get pending register address */
804     regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
805   }
806   else /* Cortex-M4 */
807   {
808     /* Get pending register address */
809     regaddr = (__IO uint32_t *)(&EXTI->C2PR1 + (EXTI_MODE_OFFSET * offset));
810   }
811 #else
812   regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
813 #endif /* DUAL_CORE */
814 
815   /* Clear Pending bit */
816   *regaddr =  maskline;
817 }
818 
819 /**
820   * @brief  Generate a software interrupt for a dedicated line.
821   * @param  hexti Exti handle.
822   * @retval None.
823   */
HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef * hexti)824 void HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef *hexti)
825 {
826   __IO uint32_t *regaddr;
827   uint32_t maskline;
828   uint32_t offset;
829 
830   /* Check parameters */
831   assert_param(IS_EXTI_LINE(hexti->Line));
832   assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
833 
834   /* compute line register offset and line mask */
835   offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
836   maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
837 
838   regaddr = (__IO uint32_t *)(&EXTI->SWIER1 + (EXTI_CONFIG_OFFSET * offset));
839   *regaddr = maskline;
840 }
841 
842 
843 /**
844   * @}
845   */
846 
847 /**
848   * @}
849   */
850 
851 #endif /* HAL_EXTI_MODULE_ENABLED */
852 /**
853   * @}
854   */
855 
856 /**
857   * @}
858   */
859 
860