1 /**
2   ******************************************************************************
3   * @file    stm32f0xx_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 28 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    (#) HAL_GPIO_DeInit allows to set register values to their reset value. It's also
72        recommended to use it to unconfigure pin which was used as an external interrupt
73        or in event mode. That's the only way to reset corresponding bit in EXTI & SYSCFG
74        registers.
75 
76    (#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
77 
78    (#) To set/reset the level of a pin configured in output mode use
79        HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
80 
81    (#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
82 
83    (#) During and just after reset, the alternate functions are not
84        active and the GPIO pins are configured in input floating mode (except JTAG
85        pins).
86 
87    (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose
88        (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has
89        priority over the GPIO function.
90 
91    (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as
92         general purpose PF0 and PF1, respectively, when the HSE oscillator is off.
93        The HSE has priority over the GPIO function.
94 
95   @endverbatim
96   ******************************************************************************
97   * @attention
98   *
99   * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
100   * All rights reserved.</center></h2>
101   *
102   * This software component is licensed by ST under BSD 3-Clause license,
103   * the "License"; You may not use this file except in compliance with the
104   * License. You may obtain a copy of the License at:
105   *                        opensource.org/licenses/BSD-3-Clause
106   *
107   ******************************************************************************
108   */
109 
110 /* Includes ------------------------------------------------------------------*/
111 #include "stm32f0xx_hal.h"
112 
113 /** @addtogroup STM32F0xx_HAL_Driver
114   * @{
115   */
116 
117 /** @defgroup GPIO GPIO
118   * @brief GPIO HAL module driver
119   * @{
120   */
121 
122 /** MISRA C:2012 deviation rule has been granted for following rules:
123   * Rule-18.1_d - Medium: Array pointer `GPIOx' is accessed with index [..,..]
124   * which may be out of array bounds [..,UNKNOWN] in following APIs:
125   * HAL_GPIO_Init
126   * HAL_GPIO_DeInit
127   */
128 
129 #ifdef HAL_GPIO_MODULE_ENABLED
130 
131 /* Private typedef -----------------------------------------------------------*/
132 /* Private defines -----------------------------------------------------------*/
133 /** @addtogroup GPIO_Private_Constants GPIO Private Constants
134   * @{
135   */
136 #define GPIO_NUMBER           16U
137 /**
138   * @}
139   */
140 
141 /* Private macros ------------------------------------------------------------*/
142 /* Private variables ---------------------------------------------------------*/
143 /* Private function prototypes -----------------------------------------------*/
144 /* Exported functions --------------------------------------------------------*/
145 
146 /** @defgroup GPIO_Exported_Functions GPIO Exported Functions
147   * @{
148   */
149 
150 /** @defgroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions
151  *  @brief    Initialization and Configuration functions
152  *
153 @verbatim
154  ===============================================================================
155               ##### Initialization and de-initialization functions #####
156  ===============================================================================
157 
158 @endverbatim
159   * @{
160   */
161 
162 /**
163   * @brief  Initialize the GPIOx peripheral according to the specified parameters in the GPIO_Init.
164   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32F0 family
165   * @param  GPIO_Init pointer to a GPIO_InitTypeDef structure that contains
166   *         the configuration information for the specified GPIO peripheral.
167   * @retval None
168   */
HAL_GPIO_Init(GPIO_TypeDef * GPIOx,GPIO_InitTypeDef * GPIO_Init)169 void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
170 {
171   uint32_t position = 0x00u;
172   uint32_t iocurrent;
173   uint32_t temp;
174 
175   /* Check the parameters */
176   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
177   assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
178   assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
179 
180   /* Configure the port pins */
181   while (((GPIO_Init->Pin) >> position) != 0x00u)
182   {
183     /* Get current io position */
184     iocurrent = (GPIO_Init->Pin) & (1uL << position);
185 
186     if (iocurrent != 0x00u)
187     {
188       /*--------------------- GPIO Mode Configuration ------------------------*/
189       /* In case of Output or Alternate function mode selection */
190       if(((GPIO_Init->Mode & GPIO_MODE) == MODE_OUTPUT) ||
191          ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF))
192       {
193         /* Check the Speed parameter */
194         assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
195         /* Configure the IO Speed */
196         temp = GPIOx->OSPEEDR;
197         temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2u));
198         temp |= (GPIO_Init->Speed << (position * 2u));
199         GPIOx->OSPEEDR = temp;
200 
201         /* Configure the IO Output Type */
202         temp = GPIOx->OTYPER;
203         temp &= ~(GPIO_OTYPER_OT_0 << position) ;
204         temp |= (((GPIO_Init->Mode & OUTPUT_TYPE) >> OUTPUT_TYPE_Pos) << position);
205         GPIOx->OTYPER = temp;
206       }
207 
208       if((GPIO_Init->Mode & GPIO_MODE) != MODE_ANALOG)
209       {
210         /* Check the Pull parameter */
211         assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
212 
213         /* Activate the Pull-up or Pull down resistor for the current IO */
214         temp = GPIOx->PUPDR;
215         temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2u));
216         temp |= ((GPIO_Init->Pull) << (position * 2u));
217         GPIOx->PUPDR = temp;
218       }
219 
220       /* In case of Alternate function mode selection */
221       if((GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
222       {
223         /* Check the Alternate function parameters */
224         assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
225         assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
226 
227         /* Configure Alternate function mapped with the current IO */
228         temp = GPIOx->AFR[position >> 3u];
229         temp &= ~(0xFu << ((position & 0x07u) * 4u));
230         temp |= ((GPIO_Init->Alternate) << ((position & 0x07u) * 4u));
231         GPIOx->AFR[position >> 3u] = temp;
232       }
233 
234       /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
235       temp = GPIOx->MODER;
236       temp &= ~(GPIO_MODER_MODER0 << (position * 2u));
237       temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2u));
238       GPIOx->MODER = temp;
239 
240       /*--------------------- EXTI Mode Configuration ------------------------*/
241       /* Configure the External Interrupt or event for the current IO */
242       if((GPIO_Init->Mode & EXTI_MODE) != 0x00u)
243       {
244         /* Enable SYSCFG Clock */
245         __HAL_RCC_SYSCFG_CLK_ENABLE();
246 
247         temp = SYSCFG->EXTICR[position >> 2u];
248         temp &= ~(0x0FuL << (4u * (position & 0x03u)));
249         temp |= (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u)));
250         SYSCFG->EXTICR[position >> 2u] = temp;
251 
252         /* Clear EXTI line configuration */
253         temp = EXTI->IMR;
254         temp &= ~(iocurrent);
255         if((GPIO_Init->Mode & EXTI_IT) != 0x00u)
256         {
257           temp |= iocurrent;
258         }
259         EXTI->IMR = temp;
260 
261         temp = EXTI->EMR;
262         temp &= ~(iocurrent);
263         if((GPIO_Init->Mode & EXTI_EVT) != 0x00u)
264         {
265           temp |= iocurrent;
266         }
267         EXTI->EMR = temp;
268 
269         /* Clear Rising Falling edge configuration */
270         temp = EXTI->RTSR;
271         temp &= ~(iocurrent);
272         if((GPIO_Init->Mode & TRIGGER_RISING) != 0x00u)
273         {
274           temp |= iocurrent;
275         }
276         EXTI->RTSR = temp;
277 
278         temp = EXTI->FTSR;
279         temp &= ~(iocurrent);
280         if((GPIO_Init->Mode & TRIGGER_FALLING) != 0x00u)
281         {
282           temp |= iocurrent;
283         }
284         EXTI->FTSR = temp;
285       }
286     }
287 
288     position++;
289   }
290 }
291 
292 /**
293   * @brief  De-initialize the GPIOx peripheral registers to their default reset values.
294   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32F0 family
295   * @param  GPIO_Pin specifies the port bit to be written.
296   *         This parameter can be one of GPIO_PIN_x where x can be (0..15).
297   * @retval None
298   */
HAL_GPIO_DeInit(GPIO_TypeDef * GPIOx,uint32_t GPIO_Pin)299 void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)
300 {
301   uint32_t position = 0x00u;
302   uint32_t iocurrent;
303   uint32_t tmp;
304 
305   /* Check the parameters */
306   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
307   assert_param(IS_GPIO_PIN(GPIO_Pin));
308 
309   /* Configure the port pins */
310   while ((GPIO_Pin >> position) != 0x00u)
311   {
312     /* Get current io position */
313     iocurrent = (GPIO_Pin) & (1uL << position);
314 
315     if (iocurrent != 0x00u)
316     {
317       /*------------------------- EXTI Mode Configuration --------------------*/
318       /* Clear the External Interrupt or Event for the current IO */
319 
320       tmp = SYSCFG->EXTICR[position >> 2u];
321       tmp &= (0x0FuL << (4u * (position & 0x03u)));
322       if (tmp == (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u))))
323       {
324         /* Clear EXTI line configuration */
325         EXTI->IMR &= ~((uint32_t)iocurrent);
326         EXTI->EMR &= ~((uint32_t)iocurrent);
327 
328         /* Clear Rising Falling edge configuration */
329         EXTI->RTSR &= ~((uint32_t)iocurrent);
330         EXTI->FTSR &= ~((uint32_t)iocurrent);
331 
332         /* Configure the External Interrupt or event for the current IO */
333         tmp = 0x0FuL << (4u * (position & 0x03u));
334         SYSCFG->EXTICR[position >> 2u] &= ~tmp;
335       }
336 
337       /*------------------------- GPIO Mode Configuration --------------------*/
338       /* Configure IO Direction in Input Floating Mode */
339       GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (position * 2u));
340 
341       /* Configure the default Alternate Function in current IO */
342       GPIOx->AFR[position >> 3u] &= ~(0xFu << ((uint32_t)(position & 0x07u) * 4u)) ;
343 
344       /* Deactivate the Pull-up and Pull-down resistor for the current IO */
345       GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (position * 2u));
346 
347       /* Configure the default value IO Output Type */
348       GPIOx->OTYPER  &= ~(GPIO_OTYPER_OT_0 << position) ;
349 
350       /* Configure the default value for IO Speed */
351       GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2u));
352 
353     }
354 
355     position++;
356   }
357 }
358 
359 /**
360   * @}
361   */
362 
363 /** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
364  *  @brief GPIO Read, Write, Toggle, Lock and EXTI management functions.
365  *
366 @verbatim
367  ===============================================================================
368                        ##### IO operation functions #####
369  ===============================================================================
370 
371 @endverbatim
372   * @{
373   */
374 
375 /**
376   * @brief  Read the specified input port pin.
377   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32F0 family
378   * @param  GPIO_Pin specifies the port bit to read.
379   *         This parameter can be GPIO_PIN_x where x can be (0..15).
380   * @retval The input port pin value.
381   */
HAL_GPIO_ReadPin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)382 GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
383 {
384   GPIO_PinState bitstatus;
385 
386   /* Check the parameters */
387   assert_param(IS_GPIO_PIN(GPIO_Pin));
388 
389   if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
390   {
391     bitstatus = GPIO_PIN_SET;
392   }
393   else
394   {
395     bitstatus = GPIO_PIN_RESET;
396   }
397   return bitstatus;
398   }
399 
400 /**
401   * @brief  Set or clear the selected data port bit.
402   * @note   This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify
403   *         accesses. In this way, there is no risk of an IRQ occurring between
404   *         the read and the modify access.
405   *
406   * @param  GPIOx where x can be (A..H) to select the GPIO peripheral for STM32F0 family
407   * @param  GPIO_Pin specifies the port bit to be written.
408   *          This parameter can be one of GPIO_PIN_x where x can be (0..15).
409   * @param  PinState specifies the value to be written to the selected bit.
410   *          This parameter can be one of the GPIO_PinState enum values:
411   *            @arg GPIO_PIN_RESET: to clear the port pin
412   *            @arg GPIO_PIN_SET: to set the port pin
413   * @retval None
414   */
HAL_GPIO_WritePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin,GPIO_PinState PinState)415 void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
416 {
417   /* Check the parameters */
418   assert_param(IS_GPIO_PIN(GPIO_Pin));
419   assert_param(IS_GPIO_PIN_ACTION(PinState));
420 
421   if (PinState != GPIO_PIN_RESET)
422   {
423     GPIOx->BSRR = (uint32_t)GPIO_Pin;
424   }
425   else
426   {
427     GPIOx->BRR = (uint32_t)GPIO_Pin;
428   }
429 }
430 
431 /**
432   * @brief  Toggle the specified GPIO pin.
433   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32F0 family
434   * @param  GPIO_Pin specifies the pin to be toggled.
435   * @retval None
436   */
HAL_GPIO_TogglePin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)437 void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
438 {
439   uint32_t odr;
440 
441   /* Check the parameters */
442   assert_param(IS_GPIO_PIN(GPIO_Pin));
443 
444   /* get current Ouput Data Register value */
445   odr = GPIOx->ODR;
446 
447   /* Set selected pins that were at low level, and reset ones that were high */
448   GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
449 }
450 
451 /**
452 * @brief  Locks GPIO Pins configuration registers.
453 * @note   The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
454 *         GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
455 * @note   The configuration of the locked GPIO pins can no longer be modified
456 *         until the next reset.
457   * @param  GPIOx where x can be (A..F) to select the GPIO peripheral for STM32F0 family
458   * @param  GPIO_Pin specifies the port bits to be locked.
459 *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
460 * @retval None
461 */
HAL_GPIO_LockPin(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)462 HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
463 {
464   __IO uint32_t tmp = GPIO_LCKR_LCKK;
465 
466   /* Check the parameters */
467   assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));
468   assert_param(IS_GPIO_PIN(GPIO_Pin));
469 
470   /* Apply lock key write sequence */
471   SET_BIT(tmp, GPIO_Pin);
472   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
473   GPIOx->LCKR = tmp;
474   /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
475   GPIOx->LCKR = GPIO_Pin;
476   /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
477   GPIOx->LCKR = tmp;
478   /* Read LCKK register. This read is mandatory to complete key lock sequence */
479   tmp = GPIOx->LCKR;
480 
481   /* read again in order to confirm lock is active */
482  if((GPIOx->LCKR & GPIO_LCKR_LCKK) != 0x00u)
483   {
484     return HAL_OK;
485   }
486   else
487   {
488     return HAL_ERROR;
489   }
490 }
491 
492 /**
493   * @brief  Handle EXTI interrupt request.
494   * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
495   * @retval None
496   */
HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)497 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
498 {
499   /* EXTI line interrupt detected */
500   if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
501   {
502     __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
503     HAL_GPIO_EXTI_Callback(GPIO_Pin);
504   }
505 }
506 
507 /**
508   * @brief  EXTI line detection callback.
509   * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
510   * @retval None
511   */
HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)512 __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
513 {
514   /* Prevent unused argument(s) compilation warning */
515   UNUSED(GPIO_Pin);
516 
517   /* NOTE: This function should not be modified, when the callback is needed,
518             the HAL_GPIO_EXTI_Callback could be implemented in the user file
519    */
520 }
521 
522 /**
523   * @}
524   */
525 
526 
527 /**
528   * @}
529   */
530 
531 #endif /* HAL_GPIO_MODULE_ENABLED */
532 /**
533   * @}
534   */
535 
536 /**
537   * @}
538   */
539 
540 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
541