1 /**
2   ******************************************************************************
3   * @file    stm32f4xx_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) 2017 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   Subject to the specific hardware characteristics of each I/O port listed in the datasheet, each
28   port bit of the General Purpose IO (GPIO) Ports, can be individually configured by software
29   in several modes:
30   (+) Input mode
31   (+) Analog mode
32   (+) Output mode
33   (+) Alternate function mode
34   (+) External interrupt/event lines
35 
36   [..]
37   During and just after reset, the alternate functions and external interrupt
38   lines are not active and the I/O ports are configured in input floating mode.
39 
40   [..]
41   All GPIO pins have weak internal pull-up and pull-down resistors, which can be
42   activated or not.
43 
44   [..]
45   In Output or Alternate mode, each IO can be configured on open-drain or push-pull
46   type and the IO speed can be selected depending on the VDD value.
47 
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   [..]
54   The external interrupt/event controller consists of up to 23 edge detectors
55   (16 lines are connected to GPIO) for generating event/interrupt requests (each
56   input line can be independently configured to select the type (interrupt or event)
57   and the corresponding trigger event (rising or falling or both). Each line can
58   also be masked independently.
59 
60                      ##### How to use this driver #####
61   ==============================================================================
62   [..]
63     (#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE().
64 
65     (#) Configure the GPIO pin(s) using HAL_GPIO_Init().
66         (++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
67         (++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef
68              structure.
69         (++) In case of Output or alternate function mode selection: the speed is
70              configured through "Speed" member from GPIO_InitTypeDef structure.
71         (++) In alternate mode is selection, the alternate function connected to the IO
72              is configured through "Alternate" member from GPIO_InitTypeDef structure.
73         (++) Analog mode is required when a pin is to be used as ADC channel
74              or DAC output.
75         (++) In case of external interrupt/event selection the "Mode" member from
76              GPIO_InitTypeDef structure select the type (interrupt or event) and
77              the corresponding trigger event (rising or falling or both).
78 
79     (#) In case of external interrupt/event mode selection, configure NVIC IRQ priority
80         mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using
81         HAL_NVIC_EnableIRQ().
82 
83     (#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
84 
85     (#) To set/reset the level of a pin configured in output mode use
86         HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
87 
88     (#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
89 
90 
91     (#) During and just after reset, the alternate functions are not
92         active and the GPIO pins are configured in input floating mode (except JTAG
93         pins).
94 
95     (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose
96         (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has
97         priority over the GPIO function.
98 
99     (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as
100         general purpose PH0 and PH1, respectively, when the HSE oscillator is off.
101         The HSE has priority over the GPIO function.
102 
103   @endverbatim
104   ******************************************************************************
105   */
106 
107 /* Includes ------------------------------------------------------------------*/
108 #include "stm32f4xx_hal.h"
109 
110 /** @addtogroup STM32F4xx_HAL_Driver
111   * @{
112   */
113 
114 /** @defgroup GPIO GPIO
115   * @brief GPIO HAL module driver
116   * @{
117   */
118 
119 #ifdef HAL_GPIO_MODULE_ENABLED
120 
121 /* Private typedef -----------------------------------------------------------*/
122 /* Private define ------------------------------------------------------------*/
123 /** @addtogroup GPIO_Private_Constants GPIO Private Constants
124   * @{
125   */
126 
127 #define GPIO_NUMBER           16U
128 /**
129   * @}
130   */
131 /* Private macro -------------------------------------------------------------*/
132 /* Private variables ---------------------------------------------------------*/
133 /* Private function prototypes -----------------------------------------------*/
134 /* Private functions ---------------------------------------------------------*/
135 /* Exported functions --------------------------------------------------------*/
136 /** @defgroup GPIO_Exported_Functions GPIO Exported Functions
137   * @{
138   */
139 
140 /** @defgroup GPIO_Exported_Functions_Group1 Initialization and de-initialization functions
141   *  @brief    Initialization and Configuration functions
142   *
143 @verbatim
144  ===============================================================================
145               ##### Initialization and de-initialization functions #####
146  ===============================================================================
147   [..]
148     This section provides functions allowing to initialize and de-initialize the GPIOs
149     to be ready for use.
150 
151 @endverbatim
152   * @{
153   */
154 
155 
156 /**
157   * @brief  Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init.
158   * @param  GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
159   *                      x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
160   * @param  GPIO_Init pointer to a GPIO_InitTypeDef structure that contains
161   *         the configuration information for the specified GPIO peripheral.
162   * @retval None
163   */
HAL_GPIO_Init(GPIO_TypeDef * GPIOx,GPIO_InitTypeDef * GPIO_Init)164 void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
165 {
166   uint32_t position;
167   uint32_t ioposition = 0x00U;
168   uint32_t iocurrent = 0x00U;
169   uint32_t temp = 0x00U;
170 
171   /* Check the parameters */
172   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
173   assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
174   assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
175 
176   /* Configure the port pins */
177   for(position = 0U; position < GPIO_NUMBER; position++)
178   {
179     /* Get the IO position */
180     ioposition = 0x01U << position;
181     /* Get the current IO position */
182     iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;
183 
184     if(iocurrent == ioposition)
185     {
186       /*--------------------- GPIO Mode Configuration ------------------------*/
187       /* In case of Output or Alternate function mode selection */
188       if(((GPIO_Init->Mode & GPIO_MODE) == MODE_OUTPUT) || \
189           (GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
190       {
191         /* Check the Speed parameter */
192         assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
193         /* Configure the IO Speed */
194         temp = GPIOx->OSPEEDR;
195         temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2U));
196         temp |= (GPIO_Init->Speed << (position * 2U));
197         GPIOx->OSPEEDR = temp;
198 
199         /* Configure the IO Output Type */
200         temp = GPIOx->OTYPER;
201         temp &= ~(GPIO_OTYPER_OT_0 << position) ;
202         temp |= (((GPIO_Init->Mode & OUTPUT_TYPE) >> OUTPUT_TYPE_Pos) << position);
203         GPIOx->OTYPER = temp;
204        }
205 
206       if((GPIO_Init->Mode & GPIO_MODE) != MODE_ANALOG)
207       {
208         /* Check the parameters */
209         assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
210 
211         /* Activate the Pull-up or Pull down resistor for the current IO */
212         temp = GPIOx->PUPDR;
213         temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2U));
214         temp |= ((GPIO_Init->Pull) << (position * 2U));
215         GPIOx->PUPDR = temp;
216       }
217 
218       /* In case of Alternate function mode selection */
219       if((GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
220       {
221         /* Check the Alternate function parameter */
222         assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
223         /* Configure Alternate function mapped with the current IO */
224         temp = GPIOx->AFR[position >> 3U];
225         temp &= ~(0xFU << ((uint32_t)(position & 0x07U) * 4U)) ;
226         temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & 0x07U) * 4U));
227         GPIOx->AFR[position >> 3U] = temp;
228       }
229 
230       /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
231       temp = GPIOx->MODER;
232       temp &= ~(GPIO_MODER_MODER0 << (position * 2U));
233       temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2U));
234       GPIOx->MODER = temp;
235 
236       /*--------------------- EXTI Mode Configuration ------------------------*/
237       /* Configure the External Interrupt or event for the current IO */
238       if((GPIO_Init->Mode & EXTI_MODE) != 0x00U)
239       {
240         /* Enable SYSCFG Clock */
241         __HAL_RCC_SYSCFG_CLK_ENABLE();
242 
243         temp = SYSCFG->EXTICR[position >> 2U];
244         temp &= ~(0x0FU << (4U * (position & 0x03U)));
245         temp |= ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4U * (position & 0x03U)));
246         SYSCFG->EXTICR[position >> 2U] = temp;
247 
248         /* Clear Rising Falling edge configuration */
249         temp = EXTI->RTSR;
250         temp &= ~((uint32_t)iocurrent);
251         if((GPIO_Init->Mode & TRIGGER_RISING) != 0x00U)
252         {
253           temp |= iocurrent;
254         }
255         EXTI->RTSR = temp;
256 
257         temp = EXTI->FTSR;
258         temp &= ~((uint32_t)iocurrent);
259         if((GPIO_Init->Mode & TRIGGER_FALLING) != 0x00U)
260         {
261           temp |= iocurrent;
262         }
263         EXTI->FTSR = temp;
264 
265         temp = EXTI->EMR;
266         temp &= ~((uint32_t)iocurrent);
267         if((GPIO_Init->Mode & EXTI_EVT) != 0x00U)
268         {
269           temp |= iocurrent;
270         }
271         EXTI->EMR = temp;
272 
273         /* Clear EXTI line configuration */
274         temp = EXTI->IMR;
275         temp &= ~((uint32_t)iocurrent);
276         if((GPIO_Init->Mode & EXTI_IT) != 0x00U)
277         {
278           temp |= iocurrent;
279         }
280         EXTI->IMR = temp;
281       }
282     }
283   }
284 }
285 
286 /**
287   * @brief  De-initializes the GPIOx peripheral registers to their default reset values.
288   * @param  GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
289   *                      x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
290   * @param  GPIO_Pin specifies the port bit to be written.
291   *          This parameter can be one of GPIO_PIN_x where x can be (0..15).
292   * @retval None
293   */
HAL_GPIO_DeInit(GPIO_TypeDef * GPIOx,uint32_t GPIO_Pin)294 void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)
295 {
296   uint32_t position;
297   uint32_t ioposition = 0x00U;
298   uint32_t iocurrent = 0x00U;
299   uint32_t tmp = 0x00U;
300 
301   /* Check the parameters */
302   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
303 
304   /* Configure the port pins */
305   for(position = 0U; position < GPIO_NUMBER; position++)
306   {
307     /* Get the IO position */
308     ioposition = 0x01U << position;
309     /* Get the current IO position */
310     iocurrent = (GPIO_Pin) & ioposition;
311 
312     if(iocurrent == ioposition)
313     {
314       /*------------------------- EXTI Mode Configuration --------------------*/
315       tmp = SYSCFG->EXTICR[position >> 2U];
316       tmp &= (0x0FU << (4U * (position & 0x03U)));
317       if(tmp == ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4U * (position & 0x03U))))
318       {
319         /* Clear EXTI line configuration */
320         EXTI->IMR &= ~((uint32_t)iocurrent);
321         EXTI->EMR &= ~((uint32_t)iocurrent);
322 
323         /* Clear Rising Falling edge configuration */
324         EXTI->FTSR &= ~((uint32_t)iocurrent);
325         EXTI->RTSR &= ~((uint32_t)iocurrent);
326 
327         /* Configure the External Interrupt or event for the current IO */
328         tmp = 0x0FU << (4U * (position & 0x03U));
329         SYSCFG->EXTICR[position >> 2U] &= ~tmp;
330       }
331 
332       /*------------------------- GPIO Mode Configuration --------------------*/
333       /* Configure IO Direction in Input Floating Mode */
334       GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (position * 2U));
335 
336       /* Configure the default Alternate Function in current IO */
337       GPIOx->AFR[position >> 3U] &= ~(0xFU << ((uint32_t)(position & 0x07U) * 4U)) ;
338 
339       /* Deactivate the Pull-up and Pull-down resistor for the current IO */
340       GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (position * 2U));
341 
342       /* Configure the default value IO Output Type */
343       GPIOx->OTYPER  &= ~(GPIO_OTYPER_OT_0 << position) ;
344 
345       /* Configure the default value for IO Speed */
346       GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2U));
347     }
348   }
349 }
350 
351 /**
352   * @}
353   */
354 
355 /** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
356   *  @brief   GPIO Read and Write
357   *
358 @verbatim
359  ===============================================================================
360                        ##### IO operation functions #####
361  ===============================================================================
362 
363 @endverbatim
364   * @{
365   */
366 
367 /**
368   * @brief  Reads the specified input port pin.
369   * @param  GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
370   *                      x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
371   * @param  GPIO_Pin specifies the port bit to read.
372   *         This parameter can be GPIO_PIN_x where x can be (0..15).
373   * @retval The input port pin value.
374   */
HAL_GPIO_ReadPin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)375 GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
376 {
377   GPIO_PinState bitstatus;
378 
379   /* Check the parameters */
380   assert_param(IS_GPIO_PIN(GPIO_Pin));
381 
382   if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
383   {
384     bitstatus = GPIO_PIN_SET;
385   }
386   else
387   {
388     bitstatus = GPIO_PIN_RESET;
389   }
390   return bitstatus;
391 }
392 
393 /**
394   * @brief  Sets or clears the selected data port bit.
395   *
396   * @note   This function uses GPIOx_BSRR register to allow atomic read/modify
397   *         accesses. In this way, there is no risk of an IRQ occurring between
398   *         the read and the modify access.
399   *
400   * @param  GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
401   *                      x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
402   * @param  GPIO_Pin specifies the port bit to be written.
403   *          This parameter can be one of GPIO_PIN_x where x can be (0..15).
404   * @param  PinState specifies the value to be written to the selected bit.
405   *          This parameter can be one of the GPIO_PinState enum values:
406   *            @arg GPIO_PIN_RESET: to clear the port pin
407   *            @arg GPIO_PIN_SET: to set the port pin
408   * @retval None
409   */
HAL_GPIO_WritePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin,GPIO_PinState PinState)410 void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
411 {
412   /* Check the parameters */
413   assert_param(IS_GPIO_PIN(GPIO_Pin));
414   assert_param(IS_GPIO_PIN_ACTION(PinState));
415 
416   if(PinState != GPIO_PIN_RESET)
417   {
418     GPIOx->BSRR = GPIO_Pin;
419   }
420   else
421   {
422     GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U;
423   }
424 }
425 
426 /**
427   * @brief  Toggles the specified GPIO pins.
428   * @param  GPIOx Where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
429   *                      x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
430   * @param  GPIO_Pin Specifies the pins to be toggled.
431   * @retval None
432   */
HAL_GPIO_TogglePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)433 void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
434 {
435   uint32_t odr;
436 
437   /* Check the parameters */
438   assert_param(IS_GPIO_PIN(GPIO_Pin));
439 
440   /* get current Output Data Register value */
441   odr = GPIOx->ODR;
442 
443   /* Set selected pins that were at low level, and reset ones that were high */
444   GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
445 }
446 
447 /**
448   * @brief  Locks GPIO Pins configuration registers.
449   * @note   The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
450   *         GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
451   * @note   The configuration of the locked GPIO pins can no longer be modified
452   *         until the next reset.
453   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32F4 family
454   * @param  GPIO_Pin specifies the port bit to be locked.
455   *         This parameter can be any combination of GPIO_PIN_x where x can be (0..15).
456   * @retval None
457   */
HAL_GPIO_LockPin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)458 HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
459 {
460   __IO uint32_t tmp = GPIO_LCKR_LCKK;
461 
462   /* Check the parameters */
463   assert_param(IS_GPIO_PIN(GPIO_Pin));
464 
465   /* Apply lock key write sequence */
466   tmp |= GPIO_Pin;
467   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
468   GPIOx->LCKR = tmp;
469   /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
470   GPIOx->LCKR = GPIO_Pin;
471   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
472   GPIOx->LCKR = tmp;
473   /* Read LCKR register. This read is mandatory to complete key lock sequence */
474   tmp = GPIOx->LCKR;
475 
476   /* Read again in order to confirm lock is active */
477  if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET)
478   {
479     return HAL_OK;
480   }
481   else
482   {
483     return HAL_ERROR;
484   }
485 }
486 
487 /**
488   * @brief  This function handles EXTI interrupt request.
489   * @param  GPIO_Pin Specifies the pins connected EXTI line
490   * @retval None
491   */
HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)492 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
493 {
494   /* EXTI line interrupt detected */
495   if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
496   {
497     __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
498     HAL_GPIO_EXTI_Callback(GPIO_Pin);
499   }
500 }
501 
502 /**
503   * @brief  EXTI line detection callbacks.
504   * @param  GPIO_Pin Specifies the pins connected EXTI line
505   * @retval None
506   */
HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)507 __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
508 {
509   /* Prevent unused argument(s) compilation warning */
510   UNUSED(GPIO_Pin);
511   /* NOTE: This function Should not be modified, when the callback is needed,
512            the HAL_GPIO_EXTI_Callback could be implemented in the user file
513    */
514 }
515 
516 /**
517   * @}
518   */
519 
520 
521 /**
522   * @}
523   */
524 
525 #endif /* HAL_GPIO_MODULE_ENABLED */
526 /**
527   * @}
528   */
529 
530 /**
531   * @}
532   */
533 
534