1 /**
2   ******************************************************************************
3   * @file    stm32u5xx_hal_gpio.c
4   * @author  MCD Application Team
5   * @brief   GPIO HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the General Purpose Input/Output (GPIO) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   ******************************************************************************
11   * @attention
12   *
13   * Copyright (c) 2021 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                     ##### GPIO Peripheral features #####
24   ==============================================================================
25   [..]
26     (+) Each port bit of the general-purpose I/O (GPIO) ports can be individually
27         configured by software in several modes:
28         (++) Input mode
29         (++) Analog mode
30         (++) Output mode
31         (++) Alternate function mode
32         (++) External interrupt/event lines
33 
34     (+) During and just after reset, the alternate functions and external interrupt
35         lines are not active and the I/O ports are configured in input floating mode.
36 
37     (+) All GPIO pins have weak internal pull-up and pull-down resistors, which can be
38         activated or not.
39 
40     (+) In Output or Alternate mode, each IO can be configured on open-drain or push-pull
41         type and the IO speed can be selected depending on the VDD value.
42 
43     (+) The microcontroller IO pins are connected to onboard peripherals/modules through a
44         multiplexer that allows only one peripheral alternate function (AF) connected
45        to an IO pin at a time. In this way, there can be no conflict between peripherals
46        sharing the same IO pin.
47 
48     (+) All ports have external interrupt/event capability. To use external interrupt
49         lines, the port must be configured in input mode. All available GPIO pins are
50         connected to the 16 external interrupt/event lines from EXTI0 to EXTI15.
51 
52     (+) The external interrupt/event controller consists of up to 39 edge detectors
53         (16 lines are connected to GPIO) for generating event/interrupt requests (each
54         input line can be independently configured to select the type (interrupt or event)
55         and the corresponding trigger event (rising or falling or both). Each line can
56         also be masked independently.
57 
58                      ##### How to use this driver #####
59   ==============================================================================
60   [..]
61     (#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE().
62 
63     (#) Configure the GPIO pin(s) using HAL_GPIO_Init().
64         (++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
65         (++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef
66              structure.
67         (++) In case of Output or alternate function mode selection: the speed is
68              configured through "Speed" member from GPIO_InitTypeDef structure.
69         (++) In alternate mode is selection, the alternate function connected to the IO
70              is configured through "Alternate" member from GPIO_InitTypeDef structure.
71         (++) Analog mode is required when a pin is to be used as ADC channel
72              or DAC output.
73         (++) In case of external interrupt/event selection the "Mode" member from
74              GPIO_InitTypeDef structure select the type (interrupt or event) and
75              the corresponding trigger event (rising or falling or both).
76 
77     (#) In case of external interrupt/event mode selection, configure NVIC IRQ priority
78         mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using
79         HAL_NVIC_EnableIRQ().
80 
81     (#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
82 
83     (#) To set/reset the level of a pin configured in output mode use
84         HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
85 
86     (#) To set the level of several pins and reset level of several other pins in
87         same cycle, use HAL_GPIO_WriteMultipleStatePin().
88 
89     (#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
90 
91     (#) During and just after reset, the alternate functions are not
92         active and the GPIO pins are configured in input floating mode (except JTAG
93         pins).
94 
95     (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose
96         (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has
97         priority over the GPIO function.
98 
99     (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as
100         general purpose PH0 and PH1, respectively, when the HSE oscillator is off.
101         The HSE has priority over the GPIO function.
102 
103   @endverbatim
104   ******************************************************************************
105   */
106 
107 /* Includes ------------------------------------------------------------------*/
108 #include "stm32u5xx_hal.h"
109 
110 /** @addtogroup STM32U5xx_HAL_Driver
111   * @{
112   */
113 
114 /** @addtogroup GPIO
115   * @{
116   */
117 
118 #ifdef HAL_GPIO_MODULE_ENABLED
119 
120 /* Private typedef -----------------------------------------------------------*/
121 /* Private defines -----------------------------------------------------------*/
122 /** @defgroup GPIO_Private_Defines GPIO Private Defines
123   * @{
124   */
125 #define GPIO_MODE             (0x00000003U)
126 #define EXTI_MODE             (0x10000000U)
127 #define GPIO_MODE_IT          (0x00010000U)
128 #define GPIO_MODE_EVT         (0x00020000U)
129 #define RISING_EDGE           (0x00100000U)
130 #define FALLING_EDGE          (0x00200000U)
131 #define GPIO_OUTPUT_TYPE      (0x00000010U)
132 #define GPIO_NUMBER           (16U)
133 
134 /**
135   * @}
136   */
137 
138 /* Private macros ------------------------------------------------------------*/
139 /* Private variables ---------------------------------------------------------*/
140 /** @defgroup GPIO_Private_Variables GPIO Private Variables
141   * @{
142   */
143 
144 /* LPGPIO Mapping */
145 static const LPGPIO_MapTypeDef LPGPIO_Map[GPIO_NUMBER] =
146 {
147   /* LPGPIO Pins Port    Pin */
148   /* Pin 0:*/    {GPIOA,   1},
149   /* Pin 1:*/    {GPIOA,   3},
150   /* Pin 2:*/    {GPIOA,   6},
151   /* Pin 3:*/    {GPIOB,   1},
152   /* Pin 4:*/    {GPIOB,  10},
153   /* Pin 5:*/    {GPIOC,   2},
154   /* Pin 6:*/    {GPIOD,  13},
155   /* Pin 7:*/    {GPIOD,   2},
156   /* Pin 8:*/    {GPIOC,  10},
157   /* Pin 9:*/    {GPIOB,   0},
158   /* Pin 10:*/   {GPIOC,  12},
159   /* Pin 11:*/   {GPIOB,   3},
160   /* Pin 12:*/   {GPIOB,   4},
161   /* Pin 13:*/   {GPIOE,   0},
162   /* Pin 14:*/   {GPIOE,   2},
163   /* Pin 15:*/   {GPIOE,   3},
164 };
165 
166 /**
167   * @}
168   */
169 
170 /* Private function prototypes -----------------------------------------------*/
171 /* Exported functions --------------------------------------------------------*/
172 
173 /** @addtogroup GPIO_Exported_Functions
174   * @{
175   */
176 
177 /** @defgroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions
178   *  @brief    Initialization and Configuration functions
179   *
180 @verbatim
181  ===============================================================================
182               ##### Initialization and de-initialization functions #####
183  ===============================================================================
184 
185 @endverbatim
186   * @{
187   */
188 
189 /**
190   * @brief  Initialize the GPIOx/LPGPIOx peripheral according to the specified parameters in the pGPIO_Init.
191   * @note   If GPIOx/LPGPIOx peripheral pin is used in EXTI_MODE and the pin is secure in case
192   *         the system implements the security (TZEN=1), it is up to the secure application to
193   *         insure that the corresponding EXTI line is set secure.
194   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the corresponding
195   *         peripheral for STM32U5 family
196   * @param  pGPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
197   *         the configuration information for the specified GPIO peripheral.
198   * @retval None
199   */
HAL_GPIO_Init(GPIO_TypeDef * GPIOx,const GPIO_InitTypeDef * pGPIO_Init)200 void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, const GPIO_InitTypeDef *pGPIO_Init)
201 {
202   uint32_t tmp;
203   uint32_t iocurrent;
204   uint32_t pin_position;
205   uint32_t position = 0U;
206   GPIO_TypeDef  *p_gpio;
207 
208   /* Check the parameters */
209   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
210   assert_param(IS_GPIO_PIN(pGPIO_Init->Pin));
211   assert_param(IS_GPIO_MODE(pGPIO_Init->Mode));
212 
213   /* Save GPIO port address */
214   p_gpio = GPIOx;
215 
216   /* Configure the port pins */
217   while (((pGPIO_Init->Pin) >> position) != 0U)
218   {
219     /* Get current io position */
220     iocurrent = (pGPIO_Init->Pin) & (1UL << position);
221 
222     /* Save Pin Position */
223     pin_position = position;
224 
225     if (iocurrent != 0U)
226     {
227       /*--------------------- GPIO Mode Configuration ------------------------*/
228       /* In case of Alternate function mode selection */
229       if (GPIOx == LPGPIO1)
230       {
231         /* MODER configuration */
232         tmp = GPIOx->MODER;
233         tmp &= ~(LPGPIO_MODER_MOD0 << position);
234         tmp |= ((pGPIO_Init->Mode & GPIO_MODE_OUTPUT_PP) << position);
235         GPIOx->MODER = tmp;
236 
237         /* Save GPIO Port and pin index */
238         p_gpio = LPGPIO_Map[position].GPIO_PORT;
239         pin_position = LPGPIO_Map[position].Pin_Pos;
240 
241         /* Configure Alternate function mapped with the current IO */
242         tmp = p_gpio->AFR[(pin_position) >> 3U];
243         tmp &= ~(0x0FUL << (((pin_position) & 0x07U) * 4U));
244         tmp |= ((GPIO_AF11_LPGPIO1 & 0x0FUL) << (((pin_position) & 0x07U) * 4U));
245         p_gpio->AFR[(pin_position) >> 3U] = tmp;
246 
247         /* Configure IO Direction mode (Alternate) */
248         tmp = p_gpio->MODER;
249         tmp &= ~(GPIO_MODER_MODE0 << (pin_position * 2U));
250         tmp |= ((GPIO_MODE_AF_PP & 0x0FUL) << (pin_position * 2U));
251         p_gpio->MODER = tmp;
252       }
253       else if ((pGPIO_Init->Mode == GPIO_MODE_AF_PP) || (pGPIO_Init->Mode == GPIO_MODE_AF_OD))
254       {
255         /* Check the parameters */
256         assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
257         assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
258         assert_param(IS_GPIO_AF(pGPIO_Init->Alternate));
259 
260         /* Configure Alternate function mapped with the current IO */
261         tmp = GPIOx->AFR[position >> 3U];
262         tmp &= ~(0x0FUL << ((position & 0x07U) * 4U));
263         tmp |= ((pGPIO_Init->Alternate & 0x0FUL) << ((position & 0x07U) * 4U));
264         GPIOx->AFR[position >> 3U] = tmp;
265 
266         /* Configure IO Direction mode (Alternate) */
267         tmp = p_gpio->MODER;
268         tmp &= ~(GPIO_MODER_MODE0 << (pin_position * 2U));
269         tmp |= ((pGPIO_Init->Mode & GPIO_MODE) << (pin_position * 2U));
270         p_gpio->MODER = tmp;
271       }
272       else
273       {
274         /* Check the parameters */
275         assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
276 
277         /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
278         tmp = p_gpio->MODER;
279         tmp &= ~(GPIO_MODER_MODE0 << (pin_position * 2U));
280         tmp |= ((pGPIO_Init->Mode & GPIO_MODE) << (pin_position * 2U));
281         p_gpio->MODER = tmp;
282       }
283 
284       /* In case of Output or Alternate function mode selection */
285       if ((pGPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (pGPIO_Init->Mode == GPIO_MODE_AF_PP) ||
286           (pGPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (pGPIO_Init->Mode == GPIO_MODE_AF_OD))
287       {
288         /* Check the Speed parameter */
289         assert_param(IS_GPIO_SPEED(pGPIO_Init->Speed));
290 
291         /* Configure the IO Speed */
292         tmp = p_gpio->OSPEEDR;
293         tmp &= ~(GPIO_OSPEEDR_OSPEED0 << (pin_position * 2U));
294         tmp |= (pGPIO_Init->Speed << (pin_position * 2U));
295         p_gpio->OSPEEDR = tmp;
296 
297         /* Configure the IO Output Type */
298         tmp = p_gpio->OTYPER;
299         tmp &= ~(GPIO_OTYPER_OT0 << pin_position);
300         tmp |= (((pGPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4U) << pin_position);
301         p_gpio->OTYPER = tmp;
302       }
303 
304       if (pGPIO_Init->Mode != GPIO_MODE_ANALOG)
305       {
306         /* Check the Pull parameters */
307         assert_param(IS_GPIO_PULL(pGPIO_Init->Pull));
308 
309         /* Activate the Pull-up or Pull down resistor for the current IO */
310         tmp = p_gpio->PUPDR;
311         tmp &= ~(GPIO_PUPDR_PUPD0 << (pin_position * 2U));
312         tmp |= ((pGPIO_Init->Pull) << (pin_position * 2U));
313         p_gpio->PUPDR = tmp;
314       }
315 
316       /*--------------------- EXTI Mode Configuration ------------------------*/
317       /* Configure the External Interrupt or event for the current IO */
318       if ((pGPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
319       {
320         tmp = EXTI->EXTICR[position >> 2U];
321         tmp &= ~((0x0FUL) << (8U * (position & 0x03U)));
322         tmp |= (GPIO_GET_INDEX(GPIOx) << (8U * (position & 0x03U)));
323         EXTI->EXTICR[position >> 2U] = tmp;
324 
325         /* Clear Rising Falling edge configuration */
326         tmp = EXTI->RTSR1;
327         tmp &= ~((uint32_t)iocurrent);
328         if ((pGPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
329         {
330           tmp |= iocurrent;
331         }
332         EXTI->RTSR1 = tmp;
333 
334         tmp = EXTI->FTSR1;
335         tmp &= ~((uint32_t)iocurrent);
336         if ((pGPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
337         {
338           tmp |= iocurrent;
339         }
340         EXTI->FTSR1 = tmp;
341 
342         /* Clear EXTI line configuration */
343         tmp = EXTI->EMR1;
344         tmp &= ~((uint32_t)iocurrent);
345         if ((pGPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
346         {
347           tmp |= iocurrent;
348         }
349         EXTI->EMR1 = tmp;
350 
351         tmp = EXTI->IMR1;
352         tmp &= ~((uint32_t)iocurrent);
353         if ((pGPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
354         {
355           tmp |= iocurrent;
356         }
357         EXTI->IMR1 = tmp;
358       }
359     }
360     position++;
361   }
362 }
363 
364 /**
365   * @brief  De-initialize the GPIOx peripheral registers to their default reset values.
366   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
367   *         peripheral for STM32U5 family
368   * @param  GPIO_Pin: specifies the port bit to be written.
369   *         This parameter can be one of GPIO_PIN_x where x can be (0..15).
370   * @retval None
371   */
HAL_GPIO_DeInit(GPIO_TypeDef * GPIOx,uint32_t GPIO_Pin)372 void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)
373 {
374   uint32_t tmp;
375   uint32_t iocurrent;
376   uint32_t pin_position;
377   uint32_t position = 0U;
378   GPIO_TypeDef   *p_gpio;
379 
380   /* Check the parameters */
381   assert_param(IS_GPIO_PIN(GPIO_Pin));
382 
383   /* Save GPIO port address */
384   p_gpio = GPIOx;
385 
386   /* Configure the port pins */
387   while ((GPIO_Pin >> position) != 0U)
388   {
389     /* Get current io position */
390     iocurrent = (GPIO_Pin) & (1UL << position);
391 
392     /*Save Pin Position */
393     pin_position = position;
394 
395     if (iocurrent != 0U)
396     {
397       /* In case of LPGPIO port selected */
398       if (GPIOx == LPGPIO1)
399       {
400         /* Configure LP/IO in Input Mode */
401         p_gpio  = LPGPIO_Map[pin_position].GPIO_PORT;
402         pin_position = LPGPIO_Map[position].Pin_Pos;
403         LPGPIO1->MODER &= ~(1U << pin_position);
404       }
405       else
406       {
407         /* Check the parameters */
408         assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
409 
410         /*------------------------- EXTI Mode Configuration --------------------*/
411         /* Clear the External Interrupt or Event for the current IO */
412         tmp = EXTI->EXTICR[position >> 2U];
413         tmp &= ((0x0FUL) << (8U * (position & 0x03U)));
414         if (tmp == (GPIO_GET_INDEX(GPIOx) << (8U * (position & 0x03U))))
415         {
416           /* Clear EXTI line configuration */
417           EXTI->IMR1 &= ~(iocurrent);
418           EXTI->EMR1 &= ~(iocurrent);
419 
420           /* Clear Rising Falling edge configuration */
421           EXTI->RTSR1 &= ~(iocurrent);
422           EXTI->FTSR1 &= ~(iocurrent);
423 
424           tmp = (0x0FUL) << (8U * (position & 0x03U));
425           EXTI->EXTICR[position >> 2U] &= ~tmp;
426         }
427       }
428 
429       /*------------------------- GPIO Mode Configuration --------------------*/
430       /* Configure IO in Analog Mode */
431       p_gpio->MODER |= (GPIO_MODER_MODE0 << (pin_position * 2U));
432 
433       /* Configure the default Alternate Function in current IO */
434       p_gpio->AFR[pin_position >> 3U] &= ~(0x0FUL << ((pin_position & 0x07U) * 4U));
435 
436       /* Configure the default value for IO Speed */
437       p_gpio->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (pin_position * 2U));
438 
439       /* Configure the default value IO Output Type */
440       p_gpio->OTYPER  &= ~(GPIO_OTYPER_OT0 << pin_position);
441 
442       /* Deactivate the Pull-up and Pull-down resistor for the current IO */
443       p_gpio->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (pin_position * 2U));
444     }
445 
446     position++;
447   }
448 }
449 
450 /**
451   * @}
452   */
453 
454 /** @addtogroup GPIO_Exported_Functions_Group2
455   *  @brief GPIO/LPGPIO Read, Write, Toggle, Lock and EXTI management functions.
456   *
457 @verbatim
458  ===============================================================================
459                        ##### IO operation functions #####
460  ===============================================================================
461 
462 @endverbatim
463   * @{
464   */
465 
466 /**
467   * @brief  Read the specified input port pin.
468   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
469   *         peripheral for STM32U5 family
470   * @param  GPIO_Pin: specifies the port bit to read.
471   *         This parameter can be GPIO_PIN_x where x can be (0..15).
472   * @retval The input port pin value.
473   */
HAL_GPIO_ReadPin(const GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)474 GPIO_PinState HAL_GPIO_ReadPin(const GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
475 {
476   GPIO_PinState bitstatus;
477 
478   /* Check the parameters */
479   assert_param(IS_GPIO_PIN(GPIO_Pin));
480 
481   if ((GPIOx->IDR & GPIO_Pin) != 0U)
482   {
483     bitstatus = GPIO_PIN_SET;
484   }
485   else
486   {
487     bitstatus = GPIO_PIN_RESET;
488   }
489 
490   return bitstatus;
491 }
492 
493 /**
494   * @brief  Set or clear the selected data port bit.
495   * @note   This function uses GPIOx_BSRR/LPGPIOx_BSRR and GPIOx_BRR/LPGPIOx_BRR registers to allow atomic read/modify
496   *         accesses. In this way, there is no risk of an IRQ occurring between
497   *         the read and the modify access.
498   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
499   *         peripheral for STM32U5 family
500   * @param  GPIO_Pin: specifies the port bit to be written.
501   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
502   * @param  PinState: specifies the value to be written to the selected bit.
503   *         This parameter can be one of the GPIO_PinState enum values:
504   *            @arg GPIO_PIN_RESET: to clear the port pin
505   *            @arg GPIO_PIN_SET: to set the port pin
506   * @retval None
507   */
HAL_GPIO_WritePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin,GPIO_PinState PinState)508 void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
509 {
510   /* Check the parameters */
511   assert_param(IS_GPIO_PIN(GPIO_Pin));
512   assert_param(IS_GPIO_PIN_ACTION(PinState));
513 
514   if (PinState != GPIO_PIN_RESET)
515   {
516     GPIOx->BSRR = (uint32_t)GPIO_Pin;
517   }
518   else
519   {
520     GPIOx->BRR  = (uint32_t)GPIO_Pin;
521   }
522 }
523 
524 /**
525   * @brief  Set and clear several pins of a dedicated port in same cycle.
526   * @note   This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify
527   *         accesses.
528   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
529   *         peripheral for STM32U5 family
530   * @param  PinReset specifies the port bits to be reset
531   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15) or zero.
532   * @param  PinSet specifies the port bits to be set
533   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15) or zero.
534   * @note   Both PinReset and PinSet combinations shall not get any common bit, else
535   *         assert would be triggered.
536   * @note   At least one of the two parameters used to set or reset shall be different from zero.
537   * @retval None
538   */
HAL_GPIO_WriteMultipleStatePin(GPIO_TypeDef * GPIOx,uint16_t PinReset,uint16_t PinSet)539 void HAL_GPIO_WriteMultipleStatePin(GPIO_TypeDef *GPIOx, uint16_t PinReset, uint16_t PinSet)
540 {
541   uint32_t tmp;
542 
543   /* Check the parameters */
544   /* Make sure at least one parameter is different from zero and that there is no common pin */
545   assert_param(IS_GPIO_PIN((uint32_t)PinReset | (uint32_t)PinSet));
546   assert_param(IS_GPIO_COMMON_PIN(PinReset, PinSet));
547 
548   tmp = (((uint32_t)PinReset << 16) | PinSet);
549   GPIOx->BSRR = tmp;
550 }
551 
552 /**
553   * @brief  Toggle the specified GPIO pin.
554   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
555   *         peripheral for STM32U5 family
556   * @param  GPIO_Pin specifies the pin to be toggled.
557   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
558   * @retval None
559   */
HAL_GPIO_TogglePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)560 void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
561 {
562   uint32_t odr;
563 
564   /* Check the parameters */
565   assert_param(IS_GPIO_PIN(GPIO_Pin));
566 
567   /* get current Output Data Register value */
568   odr = GPIOx->ODR;
569 
570   /* Set selected pins that were at low level, and reset ones that were high */
571   GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
572 }
573 
574 /**
575   * @brief  Lock GPIO Pins configuration registers.
576   * @note   The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
577   *         GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
578   * @note   The configuration of the locked GPIO pins can no longer be modified
579   *         until the next reset.
580   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
581   *         peripheral for STM32U5 family
582   * @param  GPIO_Pin: specifies the port bits to be locked.
583   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
584   * @retval None
585   */
HAL_GPIO_LockPin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)586 HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
587 {
588   uint32_t iocurrent;
589   uint32_t pin_locked;
590   uint32_t pin_position;
591   uint32_t position = 0U;
592   GPIO_TypeDef  *p_gpio;
593   __IO uint32_t tmp = GPIO_LCKR_LCKK;
594 
595   /* Check the parameters */
596   assert_param(IS_GPIO_PIN(GPIO_Pin));
597 
598   /* Save GPIO port address */
599   p_gpio = GPIOx;
600 
601   /* Configure the port pins */
602   while ((GPIO_Pin >> position) != 0U)
603   {
604     /* Get current io position */
605     iocurrent = GPIO_Pin & (1UL << position);
606 
607     if (iocurrent != 0U)
608     {
609 
610       /* In case of LPGPIO Port */
611       if (GPIOx == LPGPIO1)
612       {
613         /* Save GPIO Port and pin index */
614         p_gpio = LPGPIO_Map[position].GPIO_PORT;
615         pin_position = (1UL << (LPGPIO_Map[position].Pin_Pos));
616 
617         /* Save gpio pin locked */
618         pin_locked = p_gpio->LCKR;
619 
620         /* Apply lock key write sequence */
621         tmp |= (pin_locked | pin_position);
622       }
623       else
624       {
625         /* Check the parameters */
626         assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
627 
628         /* Save GPIO Pin pos*/
629         pin_position = (1UL << position);
630 
631         /* Save gpio pin locked */
632         pin_locked = p_gpio->LCKR;
633 
634         /* Apply lock key write sequence */
635         tmp |= (pin_locked | pin_position);
636       }
637 
638       /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
639       p_gpio->LCKR = tmp;
640       /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
641       p_gpio->LCKR = pin_position;
642       /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
643       p_gpio->LCKR = tmp;
644       /* Read LCKK register. This read is mandatory to complete key lock sequence */
645       tmp = p_gpio->LCKR;
646 
647       /* read again in order to confirm lock is active */
648       if ((p_gpio->LCKR & GPIO_LCKR_LCKK) != GPIO_LCKR_LCKK)
649       {
650         return HAL_ERROR;
651       }
652     }
653     position++;
654   }
655   return HAL_OK;
656 }
657 
658 /**
659   * @brief  Enable speed optimization for several pin of dedicated port.
660   * @note   Not all I/Os support the HSLV mode. Refer to the I/O structure in the corresponding
661   *         datasheet for the list of I/Os supporting this feature. Other I/Os HSLV configuration must
662   *         be kept at reset value.
663   * @note   It must be used only if the I/O supply voltage is below 2.7 V.
664   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
665   *         peripheral for STM32U5 family
666   * @param  GPIO_Pin: specifies the port bit to be written.
667   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
668   * @retval None
669   */
HAL_GPIO_EnableHighSPeedLowVoltage(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)670 void HAL_GPIO_EnableHighSPeedLowVoltage(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
671 {
672   uint32_t iocurrent;
673   uint32_t pin_position;
674   uint32_t position = 0U;
675   GPIO_TypeDef  *p_gpio;
676 
677   /* Check the parameters */
678   assert_param(IS_GPIO_PIN(GPIO_Pin));
679 
680   /* Save GPIO port address */
681   p_gpio = GPIOx;
682 
683   /* Configure the port pins */
684   while ((GPIO_Pin >> position) != 0U)
685   {
686     /* Get current io position */
687     iocurrent = GPIO_Pin & (1UL << position);
688 
689     if (iocurrent != 0U)
690     {
691       /* In case of LPGPIO Port */
692       if (GPIOx == LPGPIO1)
693       {
694         /* Get GPIO pin position */
695         position = POSITION_VAL(GPIO_Pin);
696 
697         /* Save GPIO Port and pin index */
698         p_gpio = LPGPIO_Map[position].GPIO_PORT;
699         pin_position = (1UL << (LPGPIO_Map[position].Pin_Pos));
700       }
701       else
702       {
703         /* Check the parameters */
704         assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
705 
706         /* Save GPIO pin pos */
707         pin_position = (1UL << position);
708       }
709       /* Set HSLVR gpio pin */
710       SET_BIT(p_gpio->HSLVR, pin_position);
711     }
712     position++;
713   }
714 }
715 
716 /**
717   * @brief  Disable speed optimization for several pin of dedicated port.
718   * @note   Not all I/Os support the HSLV mode. Refer to the I/O structure in the corresponding
719   *         datasheet for the list of I/Os supporting this feature. Other I/Os HSLV configuration must
720   *         be kept at reset value.
721   * @note   It must be used only if the I/O supply voltage is below 2.7 V.
722   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
723   *         peripheral for STM32U5 family
724   * @param  GPIO_Pin: specifies the port bit to be written.
725   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
726   * @retval None
727   */
HAL_GPIO_DisableHighSPeedLowVoltage(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)728 void HAL_GPIO_DisableHighSPeedLowVoltage(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
729 {
730   uint32_t iocurrent;
731   uint32_t pin_position;
732   uint32_t position = 0U;
733   GPIO_TypeDef  *p_gpio;
734 
735   /* Check the parameters */
736   assert_param(IS_GPIO_PIN(GPIO_Pin));
737 
738   /* Save GPIO port address */
739   p_gpio = GPIOx;
740 
741   /* Configure the port pins */
742   while ((GPIO_Pin >> position) != 0U)
743   {
744     /* Get current io position */
745     iocurrent = GPIO_Pin & (1UL << position);
746 
747     if (iocurrent != 0U)
748     {
749       /* In case of LPGPIO Port */
750       if (GPIOx == LPGPIO1)
751       {
752         /* Get GPIO pin position */
753         position = POSITION_VAL(GPIO_Pin);
754 
755         /* Save GPIO Port and pin index */
756         p_gpio = LPGPIO_Map[position].GPIO_PORT;
757         pin_position = (1UL << (LPGPIO_Map[position].Pin_Pos));
758       }
759       else
760       {
761         /* Check the parameters */
762         assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
763 
764         /* Save GPIO pin pos */
765         pin_position = (1UL << position);
766       }
767       /* Clear HSLVR gpio pin */
768       CLEAR_BIT(p_gpio->HSLVR, pin_position);
769     }
770     position++;
771   }
772 }
773 
774 /**
775   * @brief  Handle EXTI interrupt request.
776   * @param  GPIO_Pin: Specifies the port pin connected to corresponding EXTI line.
777   * @retval None
778   */
HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)779 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
780 {
781   /* EXTI line interrupt detected */
782   if (__HAL_GPIO_EXTI_GET_RISING_IT(GPIO_Pin) != 0U)
783   {
784     __HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_Pin);
785     HAL_GPIO_EXTI_Rising_Callback(GPIO_Pin);
786   }
787 
788   if (__HAL_GPIO_EXTI_GET_FALLING_IT(GPIO_Pin) != 0U)
789   {
790     __HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_Pin);
791     HAL_GPIO_EXTI_Falling_Callback(GPIO_Pin);
792   }
793 }
794 
795 /**
796   * @brief  EXTI line rising detection callback.
797   * @param  GPIO_Pin: Specifies the port pin connected to corresponding EXTI line.
798   * @retval None
799   */
HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)800 __weak void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
801 {
802   /* Prevent unused argument(s) compilation warning */
803   UNUSED(GPIO_Pin);
804 
805   /* NOTE: This function should not be modified, when the callback is needed,
806            the HAL_GPIO_EXTI_Rising_Callback could be implemented in the user file
807    */
808 }
809 
810 /**
811   * @brief  EXTI line falling detection callback.
812   * @param  GPIO_Pin: Specifies the port pin connected to corresponding EXTI line.
813   * @retval None
814   */
HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)815 __weak void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
816 {
817   /* Prevent unused argument(s) compilation warning */
818   UNUSED(GPIO_Pin);
819 
820   /* NOTE: This function should not be modified, when the callback is needed,
821            the HAL_GPIO_EXTI_Falling_Callback could be implemented in the user file
822    */
823 }
824 
825 /**
826   * @}
827   */
828 
829 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
830 
831 /** @defgroup GPIO_Exported_Functions_Group3 IO attributes management functions
832   *  @brief GPIO attributes management functions.
833   *
834 @verbatim
835  ===============================================================================
836                        ##### IO attributes functions #####
837  ===============================================================================
838 
839 @endverbatim
840   * @{
841   */
842 
843 /**
844   * @brief  Configure the GPIO pins attributes.
845   * @note   Available attributes are to secure GPIO pin(s), so this function is
846   *         only available in secure
847   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
848   *         peripheral for STM32U5 family
849   * @param  GPIO_Pin: specifies the pin(s) to configure the secure attribute
850   * @param  PinAttributes: specifies the pin(s) to be set in secure mode, other being set non secured.
851   * @retval None
852   */
HAL_GPIO_ConfigPinAttributes(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin,uint32_t PinAttributes)853 void HAL_GPIO_ConfigPinAttributes(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, uint32_t PinAttributes)
854 {
855   uint32_t iocurrent;
856   uint32_t pin_position;
857   uint32_t position = 0U;
858   GPIO_TypeDef  *p_gpio;
859 
860   /* Check the parameters */
861   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
862   assert_param(IS_GPIO_PIN(GPIO_Pin));
863   assert_param(IS_GPIO_PIN_ATTRIBUTES(PinAttributes));
864 
865   /* Save GPIO port address */
866   p_gpio = GPIOx;
867 
868   /* Configure the port pins */
869   while ((GPIO_Pin >> position) != 0U)
870   {
871     /* Get current io position */
872     iocurrent = GPIO_Pin & (1UL << position);
873 
874     /* Save pin position */
875     pin_position = position;
876 
877     if (iocurrent != 0U)
878     {
879       /* In case of LPGPIO Port */
880       if (GPIOx == LPGPIO1)
881       {
882         /* Save GPIO Port and pin index */
883         p_gpio = LPGPIO_Map[position].GPIO_PORT;
884         pin_position = LPGPIO_Map[position].Pin_Pos;
885       }
886       else
887       {
888         /* Check the parameters */
889         assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
890       }
891 
892       /* Configure the IO secure attribute */
893       MODIFY_REG(p_gpio->SECCFGR, (GPIO_SECCFGR_SEC0 << pin_position), (PinAttributes << pin_position));
894     }
895     position++;
896   }
897 }
898 
899 /**
900   * @brief  Get the GPIO pins attributes.
901   * @note   Available attributes are to secure GPIO pin(s), so this function is
902   *         only available in secure
903   * @param  GPIOx or LPGPIOx: where x can be (A..I) for the GPIO and (1) for LPGPIO to select the the corresponding
904   *         peripheral for STM32U5 family
905   * @param  GPIO_Pin: specifies the single pin to get the secure attribute from
906   * @param  pPinAttributes: pointer to return the pin attributes.
907   * @retval HAL Status.
908   */
HAL_GPIO_GetConfigPinAttributes(const GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin,uint32_t * pPinAttributes)909 HAL_StatusTypeDef HAL_GPIO_GetConfigPinAttributes(const GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin,
910                                                   uint32_t *pPinAttributes)
911 {
912   uint32_t iocurrent;
913   uint32_t pin_position;
914   uint32_t position = 0U;
915   const GPIO_TypeDef  *p_gpio;
916 
917   /* Check the parameters */
918   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
919   assert_param(IS_GPIO_PIN(GPIO_Pin) && (GPIO_Pin != GPIO_PIN_ALL));
920 
921   /* Check null pointer */
922   if (pPinAttributes == NULL)
923   {
924     return HAL_ERROR;
925   }
926 
927   /* Get secure attribute of the port pin */
928   while ((GPIO_Pin >> position) != 0U)
929   {
930     /* Get current io position */
931     iocurrent = GPIO_Pin & (1UL << position);
932 
933     if (iocurrent != 0U)
934     {
935       /* In case of LPGPIO Port */
936       if (GPIOx == LPGPIO1)
937       {
938         /* Save  GPIO Port and pin index */
939         p_gpio = LPGPIO_Map[position].GPIO_PORT;
940         pin_position = LPGPIO_Map[position].Pin_Pos;
941       }
942       else
943       {
944         /* Check the parameters */
945         assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
946 
947         /* Save GPIO port address */
948         p_gpio = GPIOx;
949 
950         pin_position = (1UL << position);
951       }
952 
953       /* Get the IO secure attribute */
954       if ((p_gpio->SECCFGR & (GPIO_SECCFGR_SEC0 << pin_position)) != 0U)
955       {
956         *pPinAttributes = GPIO_PIN_SEC;
957       }
958       else
959       {
960         *pPinAttributes = GPIO_PIN_NSEC;
961       }
962 
963       break;
964     }
965     position++;
966   }
967 
968   return HAL_OK;
969 }
970 
971 /**
972   * @}
973   */
974 
975 #endif /* __ARM_FEATURE_CMSE */
976 
977 
978 /**
979   * @}
980   */
981 
982 #endif /* HAL_GPIO_MODULE_ENABLED */
983 /**
984   * @}
985   */
986 
987 /**
988   * @}
989   */
990