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