xref: /btstack/port/stm32-l451-miromico-sx1280/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c (revision 2fd737d36a1de5d778cacc671d4b4d8c4f3fed82)
1 /**
2   ******************************************************************************
3   * @file    stm32l4xx_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   @verbatim
12   ==============================================================================
13                     ##### GPIO Peripheral features #####
14   ==============================================================================
15   [..]
16     (+) Each port bit of the general-purpose I/O (GPIO) ports can be individually
17         configured by software in several modes:
18         (++) Input mode
19         (++) Analog mode
20         (++) Output mode
21         (++) Alternate function mode
22         (++) External interrupt/event lines
23 
24     (+) During and just after reset, the alternate functions and external interrupt
25         lines are not active and the I/O ports are configured in input floating mode.
26 
27     (+) All GPIO pins have weak internal pull-up and pull-down resistors, which can be
28         activated or not.
29 
30     (+) In Output or Alternate mode, each IO can be configured on open-drain or push-pull
31         type and the IO speed can be selected depending on the VDD value.
32 
33     (+) The microcontroller IO pins are connected to onboard peripherals/modules through a
34         multiplexer that allows only one peripheral alternate function (AF) connected
35        to an IO pin at a time. In this way, there can be no conflict between peripherals
36        sharing the same IO pin.
37 
38     (+) All ports have external interrupt/event capability. To use external interrupt
39         lines, the port must be configured in input mode. All available GPIO pins are
40         connected to the 16 external interrupt/event lines from EXTI0 to EXTI15.
41 
42     (+) The external interrupt/event controller consists of up to 39 edge detectors
43         (16 lines are connected to GPIO) for generating event/interrupt requests (each
44         input line can be independently configured to select the type (interrupt or event)
45         and the corresponding trigger event (rising or falling or both). Each line can
46         also be masked independently.
47 
48                      ##### How to use this driver #####
49   ==============================================================================
50   [..]
51     (#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE().
52 
53     (#) Configure the GPIO pin(s) using HAL_GPIO_Init().
54         (++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
55         (++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef
56              structure.
57         (++) In case of Output or alternate function mode selection: the speed is
58              configured through "Speed" member from GPIO_InitTypeDef structure.
59         (++) In alternate mode is selection, the alternate function connected to the IO
60              is configured through "Alternate" member from GPIO_InitTypeDef structure.
61         (++) Analog mode is required when a pin is to be used as ADC channel
62              or DAC output.
63         (++) In case of external interrupt/event selection the "Mode" member from
64              GPIO_InitTypeDef structure select the type (interrupt or event) and
65              the corresponding trigger event (rising or falling or both).
66 
67     (#) In case of external interrupt/event mode selection, configure NVIC IRQ priority
68         mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using
69         HAL_NVIC_EnableIRQ().
70 
71     (#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
72 
73     (#) To set/reset the level of a pin configured in output mode use
74         HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
75 
76    (#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
77 
78     (#) During and just after reset, the alternate functions are not
79         active and the GPIO pins are configured in input floating mode (except JTAG
80         pins).
81 
82     (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose
83         (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has
84         priority over the GPIO function.
85 
86     (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as
87         general purpose PH0 and PH1, respectively, when the HSE oscillator is off.
88         The HSE has priority over the GPIO function.
89 
90   @endverbatim
91   ******************************************************************************
92   * @attention
93   *
94   * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
95   * All rights reserved.</center></h2>
96   *
97   * This software component is licensed by ST under BSD 3-Clause license,
98   * the "License"; You may not use this file except in compliance with the
99   * License. You may obtain a copy of the License at:
100   *                        opensource.org/licenses/BSD-3-Clause
101   *
102   ******************************************************************************
103   */
104 
105 /* Includes ------------------------------------------------------------------*/
106 #include "stm32l4xx_hal.h"
107 
108 /** @addtogroup STM32L4xx_HAL_Driver
109   * @{
110   */
111 
112 /** @defgroup GPIO GPIO
113   * @brief GPIO HAL module driver
114   * @{
115   */
116 /** MISRA C:2012 deviation rule has been granted for following rules:
117   * Rule-12.2 - Medium: RHS argument is in interval [0,INF] which is out of
118   * range of the shift operator in following API :
119   * HAL_GPIO_Init
120   * HAL_GPIO_DeInit
121   */
122 
123 #ifdef HAL_GPIO_MODULE_ENABLED
124 
125 /* Private typedef -----------------------------------------------------------*/
126 /* Private defines -----------------------------------------------------------*/
127 /** @defgroup GPIO_Private_Defines GPIO Private Defines
128   * @{
129   */
130 #define GPIO_MODE             (0x00000003u)
131 #define ANALOG_MODE           (0x00000008u)
132 #define EXTI_MODE             (0x10000000u)
133 #define GPIO_MODE_IT          (0x00010000u)
134 #define GPIO_MODE_EVT         (0x00020000u)
135 #define RISING_EDGE           (0x00100000u)
136 #define FALLING_EDGE          (0x00200000u)
137 #define GPIO_OUTPUT_TYPE      (0x00000010u)
138 
139 #define GPIO_NUMBER           (16u)
140 /**
141   * @}
142   */
143 
144 /* Private macros ------------------------------------------------------------*/
145 /* Private variables ---------------------------------------------------------*/
146 /* Private function prototypes -----------------------------------------------*/
147 /* Exported functions --------------------------------------------------------*/
148 
149 /** @defgroup GPIO_Exported_Functions GPIO Exported Functions
150   * @{
151   */
152 
153 /** @defgroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions
154  *  @brief    Initialization and Configuration functions
155  *
156 @verbatim
157  ===============================================================================
158               ##### Initialization and de-initialization functions #####
159  ===============================================================================
160 
161 @endverbatim
162   * @{
163   */
164 
165 /**
166   * @brief  Initialize the GPIOx peripheral according to the specified parameters in the GPIO_Init.
167   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
168   * @param  GPIO_Init pointer to a GPIO_InitTypeDef structure that contains
169   *         the configuration information for the specified GPIO peripheral.
170   * @retval None
171   */
HAL_GPIO_Init(GPIO_TypeDef * GPIOx,GPIO_InitTypeDef * GPIO_Init)172 void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
173 {
174   uint32_t position = 0x00u;
175   uint32_t iocurrent;
176   uint32_t temp;
177 
178   /* Check the parameters */
179   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
180   assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
181   assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
182   assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
183 
184   /* Configure the port pins */
185   while (((GPIO_Init->Pin) >> position) != 0x00u)
186   {
187     /* Get current io position */
188     iocurrent = (GPIO_Init->Pin) & (1uL << position);
189 
190     if (iocurrent != 0x00u)
191     {
192       /*--------------------- GPIO Mode Configuration ------------------------*/
193       /* In case of Output or Alternate function mode selection */
194       if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
195          (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
196       {
197         /* Check the Speed parameter */
198         assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
199         /* Configure the IO Speed */
200         temp = GPIOx->OSPEEDR;
201         temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
202         temp |= (GPIO_Init->Speed << (position * 2u));
203         GPIOx->OSPEEDR = temp;
204 
205         /* Configure the IO Output Type */
206         temp = GPIOx->OTYPER;
207         temp &= ~(GPIO_OTYPER_OT0 << position) ;
208         temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4u) << position);
209         GPIOx->OTYPER = temp;
210       }
211 
212 #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
213 
214       /* In case of Analog mode, check if ADC control mode is selected */
215       if((GPIO_Init->Mode & GPIO_MODE_ANALOG) == GPIO_MODE_ANALOG)
216       {
217         /* Configure the IO Output Type */
218         temp = GPIOx->ASCR;
219         temp &= ~(GPIO_ASCR_ASC0 << position) ;
220         temp |= (((GPIO_Init->Mode & ANALOG_MODE) >> 3) << position);
221         GPIOx->ASCR = temp;
222       }
223 
224 #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
225 
226       /* Activate the Pull-up or Pull down resistor for the current IO */
227       temp = GPIOx->PUPDR;
228       temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
229       temp |= ((GPIO_Init->Pull) << (position * 2u));
230       GPIOx->PUPDR = temp;
231 
232       /* In case of Alternate function mode selection */
233       if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
234       {
235         /* Check the Alternate function parameters */
236         assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
237         assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
238 
239         /* Configure Alternate function mapped with the current IO */
240         temp = GPIOx->AFR[position >> 3u];
241         temp &= ~(0xFu << ((position & 0x07u) * 4u));
242         temp |= ((GPIO_Init->Alternate) << ((position & 0x07u) * 4u));
243         GPIOx->AFR[position >> 3u] = temp;
244       }
245 
246       /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
247       temp = GPIOx->MODER;
248       temp &= ~(GPIO_MODER_MODE0 << (position * 2u));
249       temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2u));
250       GPIOx->MODER = temp;
251 
252       /*--------------------- EXTI Mode Configuration ------------------------*/
253       /* Configure the External Interrupt or event for the current IO */
254       if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
255       {
256         /* Enable SYSCFG Clock */
257         __HAL_RCC_SYSCFG_CLK_ENABLE();
258 
259         temp = SYSCFG->EXTICR[position >> 2u];
260         temp &= ~(0x0FuL << (4u * (position & 0x03u)));
261         temp |= (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u)));
262         SYSCFG->EXTICR[position >> 2u] = temp;
263 
264         /* Clear EXTI line configuration */
265         temp = EXTI->IMR1;
266         temp &= ~(iocurrent);
267         if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
268         {
269           temp |= iocurrent;
270         }
271         EXTI->IMR1 = temp;
272 
273         temp = EXTI->EMR1;
274         temp &= ~(iocurrent);
275         if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
276         {
277           temp |= iocurrent;
278         }
279         EXTI->EMR1 = temp;
280 
281         /* Clear Rising Falling edge configuration */
282         temp = EXTI->RTSR1;
283         temp &= ~(iocurrent);
284         if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
285         {
286           temp |= iocurrent;
287         }
288         EXTI->RTSR1 = temp;
289 
290         temp = EXTI->FTSR1;
291         temp &= ~(iocurrent);
292         if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
293         {
294           temp |= iocurrent;
295         }
296         EXTI->FTSR1 = temp;
297       }
298     }
299 
300     position++;
301   }
302 }
303 
304 /**
305   * @brief  De-initialize the GPIOx peripheral registers to their default reset values.
306   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
307   * @param  GPIO_Pin specifies the port bit to be written.
308   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
309   * @retval None
310   */
HAL_GPIO_DeInit(GPIO_TypeDef * GPIOx,uint32_t GPIO_Pin)311 void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)
312 {
313   uint32_t position = 0x00u;
314   uint32_t iocurrent;
315   uint32_t tmp;
316 
317   /* Check the parameters */
318   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
319   assert_param(IS_GPIO_PIN(GPIO_Pin));
320 
321   /* Configure the port pins */
322   while ((GPIO_Pin >> position) != 0x00u)
323   {
324     /* Get current io position */
325     iocurrent = (GPIO_Pin) & (1uL << position);
326 
327     if (iocurrent != 0x00u)
328     {
329       /*------------------------- EXTI Mode Configuration --------------------*/
330       /* Clear the External Interrupt or Event for the current IO */
331 
332       tmp = SYSCFG->EXTICR[position >> 2u];
333       tmp &= (0x0FuL << (4u * (position & 0x03u)));
334       if (tmp == (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u))))
335       {
336         /* Clear EXTI line configuration */
337         EXTI->IMR1 &= ~(iocurrent);
338         EXTI->EMR1 &= ~(iocurrent);
339 
340         /* Clear Rising Falling edge configuration */
341         EXTI->RTSR1 &= ~(iocurrent);
342         EXTI->FTSR1 &= ~(iocurrent);
343 
344         tmp = 0x0FuL << (4u * (position & 0x03u));
345         SYSCFG->EXTICR[position >> 2u] &= ~tmp;
346       }
347 
348       /*------------------------- GPIO Mode Configuration --------------------*/
349       /* Configure IO in Analog Mode */
350       GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2u));
351 
352       /* Configure the default Alternate Function in current IO */
353       GPIOx->AFR[position >> 3u] &= ~(0xFu << ((position & 0x07u) * 4u)) ;
354 
355       /* Configure the default value for IO Speed */
356       GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
357 
358       /* Configure the default value IO Output Type */
359       GPIOx->OTYPER  &= ~(GPIO_OTYPER_OT0 << position) ;
360 
361       /* Deactivate the Pull-up and Pull-down resistor for the current IO */
362       GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
363 
364 #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
365       /* Deactivate the Control bit of Analog mode for the current IO */
366       GPIOx->ASCR &= ~(GPIO_ASCR_ASC0<< position);
367 #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
368     }
369 
370     position++;
371   }
372 }
373 
374 /**
375   * @}
376   */
377 
378 /** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
379  *  @brief GPIO Read, Write, Toggle, Lock and EXTI management functions.
380  *
381 @verbatim
382  ===============================================================================
383                        ##### IO operation functions #####
384  ===============================================================================
385 
386 @endverbatim
387   * @{
388   */
389 
390 /**
391   * @brief  Read the specified input port pin.
392   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
393   * @param  GPIO_Pin specifies the port bit to read.
394   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
395   * @retval The input port pin value.
396   */
HAL_GPIO_ReadPin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)397 GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
398 {
399   GPIO_PinState bitstatus;
400 
401   /* Check the parameters */
402   assert_param(IS_GPIO_PIN(GPIO_Pin));
403 
404   if ((GPIOx->IDR & GPIO_Pin) != 0x00u)
405   {
406     bitstatus = GPIO_PIN_SET;
407   }
408   else
409   {
410     bitstatus = GPIO_PIN_RESET;
411   }
412   return bitstatus;
413 }
414 
415 /**
416   * @brief  Set or clear the selected data port bit.
417   *
418   * @note   This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify
419   *         accesses. In this way, there is no risk of an IRQ occurring between
420   *         the read and the modify access.
421   *
422   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
423   * @param  GPIO_Pin specifies the port bit to be written.
424   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
425   * @param  PinState specifies the value to be written to the selected bit.
426   *         This parameter can be one of the GPIO_PinState enum values:
427   *            @arg GPIO_PIN_RESET: to clear the port pin
428   *            @arg GPIO_PIN_SET: to set the port pin
429   * @retval None
430   */
HAL_GPIO_WritePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin,GPIO_PinState PinState)431 void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
432 {
433   /* Check the parameters */
434   assert_param(IS_GPIO_PIN(GPIO_Pin));
435   assert_param(IS_GPIO_PIN_ACTION(PinState));
436 
437   if(PinState != GPIO_PIN_RESET)
438   {
439     GPIOx->BSRR = (uint32_t)GPIO_Pin;
440   }
441   else
442   {
443     GPIOx->BRR = (uint32_t)GPIO_Pin;
444   }
445 }
446 
447 /**
448   * @brief  Toggle the specified GPIO pin.
449   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
450   * @param  GPIO_Pin specifies the pin to be toggled.
451   * @retval None
452   */
HAL_GPIO_TogglePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)453 void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
454 {
455   /* Check the parameters */
456   assert_param(IS_GPIO_PIN(GPIO_Pin));
457 
458   if ((GPIOx->ODR & GPIO_Pin) != 0x00u)
459   {
460     GPIOx->BRR = (uint32_t)GPIO_Pin;
461   }
462   else
463   {
464     GPIOx->BSRR = (uint32_t)GPIO_Pin;
465   }
466 }
467 
468 /**
469 * @brief  Lock GPIO Pins configuration registers.
470   * @note   The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
471   *         GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
472   * @note   The configuration of the locked GPIO pins can no longer be modified
473   *         until the next reset.
474   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
475   * @param  GPIO_Pin specifies the port bits to be locked.
476   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
477   * @retval None
478   */
HAL_GPIO_LockPin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)479 HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
480 {
481   __IO uint32_t tmp = GPIO_LCKR_LCKK;
482 
483   /* Check the parameters */
484   assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));
485   assert_param(IS_GPIO_PIN(GPIO_Pin));
486 
487   /* Apply lock key write sequence */
488   tmp |= GPIO_Pin;
489   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
490   GPIOx->LCKR = tmp;
491   /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
492   GPIOx->LCKR = GPIO_Pin;
493   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
494   GPIOx->LCKR = tmp;
495   /* Read LCKK register. This read is mandatory to complete key lock sequence */
496   tmp = GPIOx->LCKR;
497 
498   /* Read again in order to confirm lock is active */
499   if ((GPIOx->LCKR & GPIO_LCKR_LCKK) != 0x00u)
500   {
501     return HAL_OK;
502   }
503   else
504   {
505     return HAL_ERROR;
506   }
507 }
508 
509 /**
510   * @brief  Handle EXTI interrupt request.
511   * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
512   * @retval None
513   */
HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)514 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
515 {
516   /* EXTI line interrupt detected */
517   if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
518   {
519     __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
520     HAL_GPIO_EXTI_Callback(GPIO_Pin);
521   }
522 }
523 
524 /**
525   * @brief  EXTI line detection callback.
526   * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
527   * @retval None
528   */
HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)529 __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
530 {
531   /* Prevent unused argument(s) compilation warning */
532   UNUSED(GPIO_Pin);
533 
534   /* NOTE: This function should not be modified, when the callback is needed,
535            the HAL_GPIO_EXTI_Callback could be implemented in the user file
536    */
537 }
538 
539 /**
540   * @}
541   */
542 
543 
544 /**
545   * @}
546   */
547 
548 #endif /* HAL_GPIO_MODULE_ENABLED */
549 /**
550   * @}
551   */
552 
553 /**
554   * @}
555   */
556 
557 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
558