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