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