1 /**
2   ******************************************************************************
3   * @file    stm32u0xx_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   ******************************************************************************
12   * @attention
13   *
14   * Copyright (c) 2023 STMicroelectronics.
15   * All rights reserved.
16   *
17   * This software is licensed under terms that can be found in the LICENSE file
18   * in the root directory of this software component.
19   * If no LICENSE file comes with this software, it is provided AS-IS.
20   *
21   ******************************************************************************
22   @verbatim
23   ==============================================================================
24                     ##### 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 28 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 PF0 and PF1, 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 "stm32u0xx_hal.h"
107 
108 /** @addtogroup STM32U0xx_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 /** @addtogroup GPIO_Private_Constants
121   * @{
122   */
123 #define GPIO_NUMBER           (16u)
124 /**
125   * @}
126   */
127 
128 /* Private macros ------------------------------------------------------------*/
129 /* Private variables ---------------------------------------------------------*/
130 /* Private function prototypes -----------------------------------------------*/
131 /* Exported functions --------------------------------------------------------*/
132 
133 /** @addtogroup GPIO_Exported_Functions
134   * @{
135   */
136 
137 /** @addtogroup GPIO_Exported_Functions_Group1
138   *  @brief    Initialization and Configuration functions
139   *
140 @verbatim
141  ===============================================================================
142               ##### Initialization and de-initialization functions #####
143  ===============================================================================
144 
145 @endverbatim
146   * @{
147   */
148 
149 /**
150   * @brief  Initialize the GPIOx peripheral according to the specified parameters in the GPIO_Init.
151   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32U0xx family
152   * @param  GPIO_Init pointer to a GPIO_InitTypeDef structure that contains
153   *         the configuration information for the specified GPIO peripheral.
154   * @retval None
155   */
HAL_GPIO_Init(GPIO_TypeDef * GPIOx,const GPIO_InitTypeDef * GPIO_Init)156 void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, const GPIO_InitTypeDef *GPIO_Init)
157 {
158   uint32_t position = 0x00u;
159   uint32_t iocurrent;
160   uint32_t temp;
161 
162   /* Check the parameters */
163   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
164   assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
165   assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
166 
167   /* Configure the port pins */
168   while (((GPIO_Init->Pin) >> position) != 0x00u)
169   {
170     /* Get current io position */
171     iocurrent = (GPIO_Init->Pin) & (1uL << position);
172 
173     if (iocurrent != 0x00u)
174     {
175       /*--------------------- GPIO Mode Configuration ------------------------*/
176       /* In case of Output or Alternate function mode selection */
177       if (((GPIO_Init->Mode & GPIO_MODE) == MODE_OUTPUT) || ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF))
178       {
179         /* Check the Speed parameter */
180         assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
181 
182         /* Configure the IO Speed */
183         temp = GPIOx->OSPEEDR;
184         temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * GPIO_OSPEEDR_OSPEED1_Pos));
185         temp |= (GPIO_Init->Speed << (position * GPIO_OSPEEDR_OSPEED1_Pos));
186         GPIOx->OSPEEDR = temp;
187 
188         /* Configure the IO Output Type */
189         temp = GPIOx->OTYPER;
190         temp &= ~(GPIO_OTYPER_OT0 << position) ;
191         temp |= (((GPIO_Init->Mode & OUTPUT_TYPE) >> OUTPUT_TYPE_POS) << position);
192         GPIOx->OTYPER = temp;
193       }
194 
195       if ((GPIO_Init->Mode & GPIO_MODE) != MODE_ANALOG)
196       {
197         /* Check the Pull parameter */
198         assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
199 
200         /* Activate the Pull-up or Pull down resistor for the current IO */
201         temp = GPIOx->PUPDR;
202         temp &= ~(GPIO_PUPDR_PUPD0 << (position * GPIO_PUPDR_PUPD1_Pos));
203         temp |= ((GPIO_Init->Pull) << (position * GPIO_PUPDR_PUPD1_Pos));
204         GPIOx->PUPDR = temp;
205       }
206 
207       /* In case of Alternate function mode selection */
208       if ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
209       {
210         /* Check the Alternate function parameters */
211         assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
212         assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
213 
214         /* Configure Alternate function mapped with the current IO */
215         temp = GPIOx->AFR[position >> 3u];
216         temp &= ~(0xFu << ((position & 0x07u) * GPIO_AFRL_AFSEL1_Pos));
217         temp |= ((GPIO_Init->Alternate) << ((position & 0x07u) * GPIO_AFRL_AFSEL1_Pos));
218         GPIOx->AFR[position >> 3u] = temp;
219       }
220 
221       /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
222       temp = GPIOx->MODER;
223       temp &= ~(GPIO_MODER_MODE0 << (position * GPIO_MODER_MODE1_Pos));
224       temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * GPIO_MODER_MODE1_Pos));
225       GPIOx->MODER = temp;
226 
227       /*--------------------- EXTI Mode Configuration ------------------------*/
228       /* Configure the External Interrupt or event for the current IO */
229       if ((GPIO_Init->Mode & EXTI_MODE) != 0x00u)
230       {
231         temp = EXTI->EXTICR[position >> 2u];
232         temp &= ~(0x0FuL << (EXTI_EXTICR1_EXTI1_Pos * (position & 0x03u)));
233         temp |= (GPIO_GET_INDEX(GPIOx) << (EXTI_EXTICR1_EXTI1_Pos * (position & 0x03u)));
234         EXTI->EXTICR[position >> 2u] = temp;
235 
236         /* Clear Rising Falling edge configuration */
237         temp = EXTI->RTSR1;
238         temp &= ~(iocurrent);
239         if ((GPIO_Init->Mode & TRIGGER_RISING) != 0x00u)
240         {
241           temp |= iocurrent;
242         }
243         EXTI->RTSR1 = temp;
244 
245         temp = EXTI->FTSR1;
246         temp &= ~(iocurrent);
247         if ((GPIO_Init->Mode & TRIGGER_FALLING) != 0x00u)
248         {
249           temp |= iocurrent;
250         }
251         EXTI->FTSR1 = temp;
252 
253         /* Clear EXTI line configuration */
254         temp = EXTI->EMR1;
255         temp &= ~(iocurrent);
256         if ((GPIO_Init->Mode & EXTI_EVT) != 0x00u)
257         {
258           temp |= iocurrent;
259         }
260         EXTI->EMR1 = temp;
261 
262         temp = EXTI->IMR1;
263         temp &= ~(iocurrent);
264         if ((GPIO_Init->Mode & EXTI_IT) != 0x00u)
265         {
266           temp |= iocurrent;
267         }
268         EXTI->IMR1 = temp;
269       }
270     }
271 
272     position++;
273   }
274 }
275 
276 /**
277   * @brief  De-initialize the GPIOx peripheral registers to their default reset values.
278   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32U0xx family
279   * @param  GPIO_Pin specifies the port bit to be written.
280   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
281   * @retval None
282   */
HAL_GPIO_DeInit(GPIO_TypeDef * GPIOx,uint32_t GPIO_Pin)283 void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)
284 {
285   uint32_t position = 0x00u;
286   uint32_t iocurrent;
287   uint32_t tmp;
288 
289   /* Check the parameters */
290   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
291   assert_param(IS_GPIO_PIN(GPIO_Pin));
292 
293   /* Configure the port pins */
294   while ((GPIO_Pin >> position) != 0x00u)
295   {
296     /* Get current io position */
297     iocurrent = (GPIO_Pin) & (1uL << position);
298 
299     if (iocurrent != 0x00u)
300     {
301       /*------------------------- EXTI Mode Configuration --------------------*/
302       /* Clear the External Interrupt or Event for the current IO */
303 
304       tmp = EXTI->EXTICR[position >> 2u];
305       tmp &= (0x0FuL << (EXTI_EXTICR1_EXTI1_Pos * (position & 0x03u)));
306       if (tmp == (GPIO_GET_INDEX(GPIOx) << (EXTI_EXTICR1_EXTI1_Pos * (position & 0x03u))))
307       {
308         /* Clear EXTI line configuration */
309         EXTI->IMR1 &= ~(iocurrent);
310         EXTI->EMR1 &= ~(iocurrent);
311 
312         /* Clear Rising Falling edge configuration */
313         EXTI->FTSR1 &= ~(iocurrent);
314         EXTI->RTSR1 &= ~(iocurrent);
315 
316         tmp = 0x0FuL << (EXTI_EXTICR1_EXTI1_Pos * (position & 0x03u));
317         EXTI->EXTICR[position >> 2u] &= ~tmp;
318       }
319 
320       /*------------------------- GPIO Mode Configuration --------------------*/
321       /* Configure IO in Analog Mode */
322       GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * GPIO_MODER_MODE1_Pos));
323 
324       /* Configure the default Alternate Function in current IO */
325       GPIOx->AFR[position >> 3u] &= ~(0xFu << ((position & 0x07u) * GPIO_AFRL_AFSEL1_Pos)) ;
326 
327       /* Configure the default value for IO Speed */
328       GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * GPIO_OSPEEDR_OSPEED1_Pos));
329 
330       /* Configure the default value IO Output Type */
331       GPIOx->OTYPER  &= ~(GPIO_OTYPER_OT0 << position) ;
332 
333       /* Deactivate the Pull-up and Pull-down resistor for the current IO */
334       GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * GPIO_PUPDR_PUPD1_Pos));
335     }
336 
337     position++;
338   }
339 }
340 
341 /**
342   * @}
343   */
344 
345 /** @addtogroup GPIO_Exported_Functions_Group2
346   *  @brief GPIO Read, Write, Toggle, Lock and EXTI management functions.
347   *
348 @verbatim
349  ===============================================================================
350                        ##### IO operation functions #####
351  ===============================================================================
352 
353 @endverbatim
354   * @{
355   */
356 
357 /**
358   * @brief  Read the specified input port pin.
359   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32U0xx family
360   * @param  GPIO_Pin specifies the port bit to read.
361   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
362   * @retval The input port pin value.
363   */
HAL_GPIO_ReadPin(const GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)364 GPIO_PinState HAL_GPIO_ReadPin(const GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
365 {
366   GPIO_PinState bitstatus;
367 
368   /* Check the parameters */
369   assert_param(IS_GPIO_PIN(GPIO_Pin));
370 
371   if ((GPIOx->IDR & GPIO_Pin) != 0x00u)
372   {
373     bitstatus = GPIO_PIN_SET;
374   }
375   else
376   {
377     bitstatus = GPIO_PIN_RESET;
378   }
379   return bitstatus;
380 }
381 
382 /**
383   * @brief  Set or clear the selected data port bit.
384   *
385   * @note   This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify
386   *         accesses. In this way, there is no risk of an IRQ occurring between
387   *         the read and the modify access.
388   *
389   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32U0xx family
390   * @param  GPIO_Pin specifies the port bit to be written.
391   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
392   * @param  PinState specifies the value to be written to the selected bit.
393   *         This parameter can be one of the GPIO_PinState enum values:
394   *            @arg GPIO_PIN_RESET: to clear the port pin
395   *            @arg GPIO_PIN_SET: to set the port pin
396   * @retval None
397   */
HAL_GPIO_WritePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin,GPIO_PinState PinState)398 void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
399 {
400   /* Check the parameters */
401   assert_param(IS_GPIO_PIN(GPIO_Pin));
402   assert_param(IS_GPIO_PIN_ACTION(PinState));
403 
404   if (PinState != GPIO_PIN_RESET)
405   {
406     GPIOx->BSRR = (uint32_t)GPIO_Pin;
407   }
408   else
409   {
410     GPIOx->BRR = (uint32_t)GPIO_Pin;
411   }
412 }
413 
414 /**
415   * @brief  Toggle the specified GPIO pin.
416   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32U0xx family
417   * @param  GPIO_Pin specifies the pin to be toggled.
418   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
419   * @retval None
420   */
HAL_GPIO_TogglePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)421 void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
422 {
423   uint32_t odr;
424 
425   /* Check the parameters */
426   assert_param(IS_GPIO_PIN(GPIO_Pin));
427 
428   /* get current Output Data Register value */
429   odr = GPIOx->ODR;
430 
431   /* Set selected pins that were at low level, and reset ones that were high */
432   GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
433 }
434 
435 /**
436   * @brief  Lock GPIO Pins configuration registers.
437   * @note   The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
438   *         GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
439   * @note   The configuration of the locked GPIO pins can no longer be modified
440   *         until the next reset.
441   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32U0xx family
442   * @param  GPIO_Pin specifies the port bits to be locked.
443   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
444   * @retval None
445   */
HAL_GPIO_LockPin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)446 HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
447 {
448   __IO uint32_t tmp = GPIO_LCKR_LCKK;
449 
450   /* Check the parameters */
451   assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));
452   assert_param(IS_GPIO_PIN(GPIO_Pin));
453 
454   /* Apply lock key write sequence */
455   tmp |= GPIO_Pin;
456   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
457   GPIOx->LCKR = tmp;
458   /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
459   GPIOx->LCKR = GPIO_Pin;
460   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
461   GPIOx->LCKR = tmp;
462   /* Read LCKK register. This read is mandatory to complete key lock sequence */
463   tmp = GPIOx->LCKR;
464 
465   /* read again in order to confirm lock is active */
466   if ((GPIOx->LCKR & GPIO_LCKR_LCKK) != 0x00u)
467   {
468     return HAL_OK;
469   }
470   else
471   {
472     return HAL_ERROR;
473   }
474 }
475 
476 /**
477   * @brief  Handle EXTI interrupt request.
478   * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
479   * @retval None
480   */
HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)481 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
482 {
483   /* EXTI line interrupt detected */
484   if (__HAL_GPIO_EXTI_GET_RISING_IT(GPIO_Pin) != 0x00u)
485   {
486     __HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_Pin);
487     HAL_GPIO_EXTI_Rising_Callback(GPIO_Pin);
488   }
489 
490   if (__HAL_GPIO_EXTI_GET_FALLING_IT(GPIO_Pin) != 0x00u)
491   {
492     __HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_Pin);
493     HAL_GPIO_EXTI_Falling_Callback(GPIO_Pin);
494   }
495 }
496 
497 /**
498   * @brief  EXTI line detection callback.
499   * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
500   * @retval None
501   */
HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)502 __weak void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
503 {
504   /* Prevent unused argument(s) compilation warning */
505   UNUSED(GPIO_Pin);
506 
507   /* NOTE: This function should not be modified, when the callback is needed,
508            the HAL_GPIO_EXTI_Rising_Callback could be implemented in the user file
509    */
510 }
511 
512 /**
513   * @brief  EXTI line detection callback.
514   * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
515   * @retval None
516   */
HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)517 __weak void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
518 {
519   /* Prevent unused argument(s) compilation warning */
520   UNUSED(GPIO_Pin);
521 
522   /* NOTE: This function should not be modified, when the callback is needed,
523            the HAL_GPIO_EXTI_Falling_Callback could be implemented in the user file
524    */
525 }
526 /**
527   * @}
528   */
529 
530 /**
531   * @}
532   */
533 
534 #endif /* HAL_GPIO_MODULE_ENABLED */
535 /**
536   * @}
537   */
538 
539 /**
540   * @}
541   */
542 
543