STM32L443xx HAL User Manual
stm32l4xx_hal_gpio.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_gpio.c
00004   * @author  MCD Application Team
00005   * @brief   GPIO HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the General Purpose Input/Output (GPIO) peripheral:
00008   *           + Initialization and de-initialization functions
00009   *           + IO operation functions
00010   *
00011   ******************************************************************************
00012   * @attention
00013   *
00014   * Copyright (c) 2017 STMicroelectronics.
00015   * All rights reserved.
00016   *
00017   * This software is licensed under terms that can be found in the LICENSE file
00018   * in the root directory of this software component.
00019   * If no LICENSE file comes with this software, it is provided AS-IS.
00020   *
00021   ******************************************************************************
00022   @verbatim
00023   ==============================================================================
00024                     ##### GPIO Peripheral features #####
00025   ==============================================================================
00026   [..]
00027     (+) Each port bit of the general-purpose I/O (GPIO) ports can be individually
00028         configured by software in several modes:
00029         (++) Input mode
00030         (++) Analog mode
00031         (++) Output mode
00032         (++) Alternate function mode
00033         (++) External interrupt/event lines
00034 
00035     (+) During and just after reset, the alternate functions and external interrupt
00036         lines are not active and the I/O ports are configured in input floating mode.
00037 
00038     (+) All GPIO pins have weak internal pull-up and pull-down resistors, which can be
00039         activated or not.
00040 
00041     (+) In Output or Alternate mode, each IO can be configured on open-drain or push-pull
00042         type and the IO speed can be selected depending on the VDD value.
00043 
00044     (+) The microcontroller IO pins are connected to onboard peripherals/modules through a
00045         multiplexer that allows only one peripheral alternate function (AF) connected
00046        to an IO pin at a time. In this way, there can be no conflict between peripherals
00047        sharing the same IO pin.
00048 
00049     (+) All ports have external interrupt/event capability. To use external interrupt
00050         lines, the port must be configured in input mode. All available GPIO pins are
00051         connected to the 16 external interrupt/event lines from EXTI0 to EXTI15.
00052 
00053     (+) The external interrupt/event controller consists of up to 39 edge detectors
00054         (16 lines are connected to GPIO) for generating event/interrupt requests (each
00055         input line can be independently configured to select the type (interrupt or event)
00056         and the corresponding trigger event (rising or falling or both). Each line can
00057         also be masked independently.
00058 
00059                      ##### How to use this driver #####
00060   ==============================================================================
00061   [..]
00062     (#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE().
00063 
00064     (#) Configure the GPIO pin(s) using HAL_GPIO_Init().
00065         (++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
00066         (++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef
00067              structure.
00068         (++) In case of Output or alternate function mode selection: the speed is
00069              configured through "Speed" member from GPIO_InitTypeDef structure.
00070         (++) In alternate mode is selection, the alternate function connected to the IO
00071              is configured through "Alternate" member from GPIO_InitTypeDef structure.
00072         (++) Analog mode is required when a pin is to be used as ADC channel
00073              or DAC output.
00074         (++) In case of external interrupt/event selection the "Mode" member from
00075              GPIO_InitTypeDef structure select the type (interrupt or event) and
00076              the corresponding trigger event (rising or falling or both).
00077 
00078     (#) In case of external interrupt/event mode selection, configure NVIC IRQ priority
00079         mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using
00080         HAL_NVIC_EnableIRQ().
00081 
00082     (#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
00083 
00084     (#) To set/reset the level of a pin configured in output mode use
00085         HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
00086 
00087    (#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
00088 
00089     (#) During and just after reset, the alternate functions are not
00090         active and the GPIO pins are configured in input floating mode (except JTAG
00091         pins).
00092 
00093     (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose
00094         (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has
00095         priority over the GPIO function.
00096 
00097     (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as
00098         general purpose PH0 and PH1, respectively, when the HSE oscillator is off.
00099         The HSE has priority over the GPIO function.
00100 
00101   @endverbatim
00102   ******************************************************************************
00103   */
00104 
00105 /* Includes ------------------------------------------------------------------*/
00106 #include "stm32l4xx_hal.h"
00107 
00108 /** @addtogroup STM32L4xx_HAL_Driver
00109   * @{
00110   */
00111 
00112 /** @defgroup GPIO GPIO
00113   * @brief GPIO HAL module driver
00114   * @{
00115   */
00116 /** MISRA C:2012 deviation rule has been granted for following rules:
00117   * Rule-12.2 - Medium: RHS argument is in interval [0,INF] which is out of
00118   * range of the shift operator in following API :
00119   * HAL_GPIO_Init
00120   * HAL_GPIO_DeInit
00121   */
00122 
00123 #ifdef HAL_GPIO_MODULE_ENABLED
00124 
00125 /* Private typedef -----------------------------------------------------------*/
00126 /* Private defines -----------------------------------------------------------*/
00127 /** @addtogroup GPIO_Private_Defines GPIO Private Defines
00128   * @{
00129   */
00130 #define GPIO_NUMBER           (16u)
00131 /**
00132   * @}
00133   */
00134 
00135 /* Private macros ------------------------------------------------------------*/
00136 /* Private variables ---------------------------------------------------------*/
00137 /* Private function prototypes -----------------------------------------------*/
00138 /* Exported functions --------------------------------------------------------*/
00139 
00140 /** @defgroup GPIO_Exported_Functions GPIO Exported Functions
00141   * @{
00142   */
00143 
00144 /** @defgroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions
00145  *  @brief    Initialization and Configuration functions
00146  *
00147 @verbatim
00148  ===============================================================================
00149               ##### Initialization and de-initialization functions #####
00150  ===============================================================================
00151 
00152 @endverbatim
00153   * @{
00154   */
00155 
00156 /**
00157   * @brief  Initialize the GPIOx peripheral according to the specified parameters in the GPIO_Init.
00158   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
00159   * @param  GPIO_Init pointer to a GPIO_InitTypeDef structure that contains
00160   *         the configuration information for the specified GPIO peripheral.
00161   * @retval None
00162   */
00163 void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
00164 {
00165   uint32_t position = 0x00u;
00166   uint32_t iocurrent;
00167   uint32_t temp;
00168 
00169   /* Check the parameters */
00170   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
00171   assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
00172   assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
00173 
00174   /* Configure the port pins */
00175   while (((GPIO_Init->Pin) >> position) != 0x00u)
00176   {
00177     /* Get current io position */
00178     iocurrent = (GPIO_Init->Pin) & (1uL << position);
00179 
00180     if (iocurrent != 0x00u)
00181     {
00182       /*--------------------- GPIO Mode Configuration ------------------------*/
00183       /* In case of Output or Alternate function mode selection */
00184       if (((GPIO_Init->Mode & GPIO_MODE) == MODE_OUTPUT) || ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF))
00185       {
00186         /* Check the Speed parameter */
00187         assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
00188 
00189         /* Configure the IO Speed */
00190         temp = GPIOx->OSPEEDR;
00191         temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
00192         temp |= (GPIO_Init->Speed << (position * 2u));
00193         GPIOx->OSPEEDR = temp;
00194 
00195         /* Configure the IO Output Type */
00196         temp = GPIOx->OTYPER;
00197         temp &= ~(GPIO_OTYPER_OT0 << position) ;
00198         temp |= (((GPIO_Init->Mode & OUTPUT_TYPE) >> OUTPUT_TYPE_Pos) << position);
00199         GPIOx->OTYPER = temp;
00200       }
00201 
00202 #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
00203 
00204       /* In case of Analog mode, check if ADC control mode is selected */
00205       if((GPIO_Init->Mode & GPIO_MODE_ANALOG) == GPIO_MODE_ANALOG)
00206       {
00207         /* Configure the IO Output Type */
00208         temp = GPIOx->ASCR;
00209         temp &= ~(GPIO_ASCR_ASC0 << position) ;
00210         temp |= (((GPIO_Init->Mode & GPIO_MODE_ANALOG_ADC_CONTROL) >> 3) << position);
00211         GPIOx->ASCR = temp;
00212       }
00213 
00214 #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
00215 
00216       /* Activate the Pull-up or Pull down resistor for the current IO */
00217       if ((GPIO_Init->Mode & GPIO_MODE) != MODE_ANALOG)
00218       {
00219         /* Check the Pull parameter */
00220         assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
00221 
00222         temp = GPIOx->PUPDR;
00223         temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2U));
00224         temp |= ((GPIO_Init->Pull) << (position * 2U));
00225         GPIOx->PUPDR = temp;
00226       }
00227 
00228       /* In case of Alternate function mode selection */
00229       if ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
00230       {
00231         /* Check the Alternate function parameters */
00232         assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
00233         assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
00234 
00235         /* Configure Alternate function mapped with the current IO */
00236         temp = GPIOx->AFR[position >> 3u];
00237         temp &= ~(0xFu << ((position & 0x07u) * 4u));
00238         temp |= ((GPIO_Init->Alternate) << ((position & 0x07u) * 4u));
00239         GPIOx->AFR[position >> 3u] = temp;
00240       }
00241 
00242       /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
00243       temp = GPIOx->MODER;
00244       temp &= ~(GPIO_MODER_MODE0 << (position * 2u));
00245       temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2u));
00246       GPIOx->MODER = temp;
00247 
00248       /*--------------------- EXTI Mode Configuration ------------------------*/
00249       /* Configure the External Interrupt or event for the current IO */
00250       if ((GPIO_Init->Mode & EXTI_MODE) != 0x00u)
00251       {
00252         /* Enable SYSCFG Clock */
00253         __HAL_RCC_SYSCFG_CLK_ENABLE();
00254 
00255         temp = SYSCFG->EXTICR[position >> 2u];
00256         temp &= ~(0x0FuL << (4u * (position & 0x03u)));
00257         temp |= (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u)));
00258         SYSCFG->EXTICR[position >> 2u] = temp;
00259 
00260         /* Clear Rising Falling edge configuration */
00261         temp = EXTI->RTSR1;
00262         temp &= ~(iocurrent);
00263         if ((GPIO_Init->Mode & TRIGGER_RISING) != 0x00u)
00264         {
00265           temp |= iocurrent;
00266         }
00267         EXTI->RTSR1 = temp;
00268 
00269         temp = EXTI->FTSR1;
00270         temp &= ~(iocurrent);
00271         if ((GPIO_Init->Mode & TRIGGER_FALLING) != 0x00u)
00272         {
00273           temp |= iocurrent;
00274         }
00275         EXTI->FTSR1 = temp;
00276 
00277         /* Clear EXTI line configuration */
00278         temp = EXTI->EMR1;
00279         temp &= ~(iocurrent);
00280         if ((GPIO_Init->Mode & EXTI_EVT) != 0x00u)
00281         {
00282           temp |= iocurrent;
00283         }
00284         EXTI->EMR1 = temp;
00285 
00286         temp = EXTI->IMR1;
00287         temp &= ~(iocurrent);
00288         if ((GPIO_Init->Mode & EXTI_IT) != 0x00u)
00289         {
00290           temp |= iocurrent;
00291         }
00292         EXTI->IMR1 = temp;
00293       }
00294     }
00295 
00296     position++;
00297   }
00298 }
00299 
00300 /**
00301   * @brief  De-initialize the GPIOx peripheral registers to their default reset values.
00302   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
00303   * @param  GPIO_Pin specifies the port bit to be written.
00304   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
00305   * @retval None
00306   */
00307 void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)
00308 {
00309   uint32_t position = 0x00u;
00310   uint32_t iocurrent;
00311   uint32_t tmp;
00312 
00313   /* Check the parameters */
00314   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
00315   assert_param(IS_GPIO_PIN(GPIO_Pin));
00316 
00317   /* Configure the port pins */
00318   while ((GPIO_Pin >> position) != 0x00u)
00319   {
00320     /* Get current io position */
00321     iocurrent = (GPIO_Pin) & (1uL << position);
00322 
00323     if (iocurrent != 0x00u)
00324     {
00325       /*------------------------- EXTI Mode Configuration --------------------*/
00326       /* Clear the External Interrupt or Event for the current IO */
00327 
00328       tmp = SYSCFG->EXTICR[position >> 2u];
00329       tmp &= (0x0FuL << (4u * (position & 0x03u)));
00330       if (tmp == (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u))))
00331       {
00332         /* Clear EXTI line configuration */
00333         EXTI->IMR1 &= ~(iocurrent);
00334         EXTI->EMR1 &= ~(iocurrent);
00335 
00336         /* Clear Rising Falling edge configuration */
00337         EXTI->FTSR1 &= ~(iocurrent);
00338         EXTI->RTSR1 &= ~(iocurrent);
00339 
00340         tmp = 0x0FuL << (4u * (position & 0x03u));
00341         SYSCFG->EXTICR[position >> 2u] &= ~tmp;
00342       }
00343 
00344       /*------------------------- GPIO Mode Configuration --------------------*/
00345       /* Configure IO in Analog Mode */
00346       GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2u));
00347 
00348       /* Configure the default Alternate Function in current IO */
00349       GPIOx->AFR[position >> 3u] &= ~(0xFu << ((position & 0x07u) * 4u)) ;
00350 
00351       /* Configure the default value for IO Speed */
00352       GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
00353 
00354       /* Configure the default value IO Output Type */
00355       GPIOx->OTYPER  &= ~(GPIO_OTYPER_OT0 << position) ;
00356 
00357       /* Deactivate the Pull-up and Pull-down resistor for the current IO */
00358       GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
00359 
00360 #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
00361       /* Deactivate the Control bit of Analog mode for the current IO */
00362       GPIOx->ASCR &= ~(GPIO_ASCR_ASC0<< position);
00363 #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
00364     }
00365 
00366     position++;
00367   }
00368 }
00369 
00370 /**
00371   * @}
00372   */
00373 
00374 /** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
00375  *  @brief GPIO Read, Write, Toggle, Lock and EXTI management functions.
00376  *
00377 @verbatim
00378  ===============================================================================
00379                        ##### IO operation functions #####
00380  ===============================================================================
00381 
00382 @endverbatim
00383   * @{
00384   */
00385 
00386 /**
00387   * @brief  Read the specified input port pin.
00388   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
00389   * @param  GPIO_Pin specifies the port bit to read.
00390   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
00391   * @retval The input port pin value.
00392   */
00393 GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
00394 {
00395   GPIO_PinState bitstatus;
00396 
00397   /* Check the parameters */
00398   assert_param(IS_GPIO_PIN(GPIO_Pin));
00399 
00400   if ((GPIOx->IDR & GPIO_Pin) != 0x00u)
00401   {
00402     bitstatus = GPIO_PIN_SET;
00403   }
00404   else
00405   {
00406     bitstatus = GPIO_PIN_RESET;
00407   }
00408   return bitstatus;
00409 }
00410 
00411 /**
00412   * @brief  Set or clear the selected data port bit.
00413   *
00414   * @note   This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify
00415   *         accesses. In this way, there is no risk of an IRQ occurring between
00416   *         the read and the modify access.
00417   *
00418   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
00419   * @param  GPIO_Pin specifies the port bit to be written.
00420   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
00421   * @param  PinState specifies the value to be written to the selected bit.
00422   *         This parameter can be one of the GPIO_PinState enum values:
00423   *            @arg GPIO_PIN_RESET: to clear the port pin
00424   *            @arg GPIO_PIN_SET: to set the port pin
00425   * @retval None
00426   */
00427 void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
00428 {
00429   /* Check the parameters */
00430   assert_param(IS_GPIO_PIN(GPIO_Pin));
00431   assert_param(IS_GPIO_PIN_ACTION(PinState));
00432 
00433   if(PinState != GPIO_PIN_RESET)
00434   {
00435     GPIOx->BSRR = (uint32_t)GPIO_Pin;
00436   }
00437   else
00438   {
00439     GPIOx->BRR = (uint32_t)GPIO_Pin;
00440   }
00441 }
00442 
00443 /**
00444   * @brief  Toggle the specified GPIO pin.
00445   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
00446   * @param  GPIO_Pin specifies the pin to be toggled.
00447   * @retval None
00448   */
00449 void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
00450 {
00451   uint32_t odr;
00452 
00453   /* Check the parameters */
00454   assert_param(IS_GPIO_PIN(GPIO_Pin));
00455 
00456   /* get current Ouput Data Register value */
00457   odr = GPIOx->ODR;
00458 
00459   /* Set selected pins that were at low level, and reset ones that were high */
00460   GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
00461 }
00462 
00463 /**
00464 * @brief  Lock GPIO Pins configuration registers.
00465   * @note   The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
00466   *         GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
00467   * @note   The configuration of the locked GPIO pins can no longer be modified
00468   *         until the next reset.
00469   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
00470   * @param  GPIO_Pin specifies the port bits to be locked.
00471   *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
00472   * @retval None
00473   */
00474 HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
00475 {
00476   __IO uint32_t tmp = GPIO_LCKR_LCKK;
00477 
00478   /* Check the parameters */
00479   assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));
00480   assert_param(IS_GPIO_PIN(GPIO_Pin));
00481 
00482   /* Apply lock key write sequence */
00483   tmp |= GPIO_Pin;
00484   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
00485   GPIOx->LCKR = tmp;
00486   /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
00487   GPIOx->LCKR = GPIO_Pin;
00488   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
00489   GPIOx->LCKR = tmp;
00490   /* Read LCKK register. This read is mandatory to complete key lock sequence */
00491   tmp = GPIOx->LCKR;
00492 
00493   /* Read again in order to confirm lock is active */
00494   if ((GPIOx->LCKR & GPIO_LCKR_LCKK) != 0x00u)
00495   {
00496     return HAL_OK;
00497   }
00498   else
00499   {
00500     return HAL_ERROR;
00501   }
00502 }
00503 
00504 /**
00505   * @brief  Handle EXTI interrupt request.
00506   * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
00507   * @retval None
00508   */
00509 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
00510 {
00511   /* EXTI line interrupt detected */
00512   if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
00513   {
00514     __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
00515     HAL_GPIO_EXTI_Callback(GPIO_Pin);
00516   }
00517 }
00518 
00519 /**
00520   * @brief  EXTI line detection callback.
00521   * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
00522   * @retval None
00523   */
00524 __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
00525 {
00526   /* Prevent unused argument(s) compilation warning */
00527   UNUSED(GPIO_Pin);
00528 
00529   /* NOTE: This function should not be modified, when the callback is needed,
00530            the HAL_GPIO_EXTI_Callback could be implemented in the user file
00531    */
00532 }
00533 
00534 /**
00535   * @}
00536   */
00537 
00538 
00539 /**
00540   * @}
00541   */
00542 
00543 #endif /* HAL_GPIO_MODULE_ENABLED */
00544 /**
00545   * @}
00546   */
00547 
00548 /**
00549   * @}
00550   */
00551