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