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