Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c (22184B)
1 /** 2 ****************************************************************************** 3 * @file stm32f1xx_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) 2016 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 20 edge detectors in connectivity 55 line devices, or 19 edge detectors in other devices for generating event/interrupt requests. 56 Each input line can be independently configured to select the type (event or interrupt) and 57 the corresponding trigger event (rising or falling or both). Each line can also masked 58 independently. A pending register maintains the status line of the interrupt requests 59 60 ##### How to use this driver ##### 61 ============================================================================== 62 [..] 63 (#) Enable the GPIO APB2 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 (++) Analog mode is required when a pin is to be used as ADC channel 72 or DAC output. 73 (++) In case of external interrupt/event selection the "Mode" member from 74 GPIO_InitTypeDef structure select the type (interrupt or event) and 75 the corresponding trigger event (rising or falling or both). 76 77 (#) In case of external interrupt/event mode selection, configure NVIC IRQ priority 78 mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using 79 HAL_NVIC_EnableIRQ(). 80 81 (#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin(). 82 83 (#) To set/reset the level of a pin configured in output mode use 84 HAL_GPIO_WritePin()/HAL_GPIO_TogglePin(). 85 86 (#) To lock pin configuration until next reset use HAL_GPIO_LockPin(). 87 88 (#) During and just after reset, the alternate functions are not 89 active and the GPIO pins are configured in input floating mode (except JTAG 90 pins). 91 92 (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose 93 (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has 94 priority over the GPIO function. 95 96 (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as 97 general purpose PD0 and PD1, respectively, when the HSE oscillator is off. 98 The HSE has priority over the GPIO function. 99 100 @endverbatim 101 ****************************************************************************** 102 */ 103 104 /* Includes ------------------------------------------------------------------*/ 105 #include "stm32f1xx_hal.h" 106 107 /** @addtogroup STM32F1xx_HAL_Driver 108 * @{ 109 */ 110 111 /** @defgroup GPIO GPIO 112 * @brief GPIO HAL module driver 113 * @{ 114 */ 115 116 #ifdef HAL_GPIO_MODULE_ENABLED 117 118 /* Private typedef -----------------------------------------------------------*/ 119 /* Private define ------------------------------------------------------------*/ 120 /** @addtogroup GPIO_Private_Constants GPIO Private Constants 121 * @{ 122 */ 123 #define GPIO_MODE 0x00000003u 124 #define EXTI_MODE 0x10000000u 125 #define GPIO_MODE_IT 0x00010000u 126 #define GPIO_MODE_EVT 0x00020000u 127 #define RISING_EDGE 0x00100000u 128 #define FALLING_EDGE 0x00200000u 129 #define GPIO_OUTPUT_TYPE 0x00000010u 130 131 #define GPIO_NUMBER 16u 132 133 /* Definitions for bit manipulation of CRL and CRH register */ 134 #define GPIO_CR_MODE_INPUT 0x00000000u /*!< 00: Input mode (reset state) */ 135 #define GPIO_CR_CNF_ANALOG 0x00000000u /*!< 00: Analog mode */ 136 #define GPIO_CR_CNF_INPUT_FLOATING 0x00000004u /*!< 01: Floating input (reset state) */ 137 #define GPIO_CR_CNF_INPUT_PU_PD 0x00000008u /*!< 10: Input with pull-up / pull-down */ 138 #define GPIO_CR_CNF_GP_OUTPUT_PP 0x00000000u /*!< 00: General purpose output push-pull */ 139 #define GPIO_CR_CNF_GP_OUTPUT_OD 0x00000004u /*!< 01: General purpose output Open-drain */ 140 #define GPIO_CR_CNF_AF_OUTPUT_PP 0x00000008u /*!< 10: Alternate function output Push-pull */ 141 #define GPIO_CR_CNF_AF_OUTPUT_OD 0x0000000Cu /*!< 11: Alternate function output Open-drain */ 142 143 /** 144 * @} 145 */ 146 /* Private macro -------------------------------------------------------------*/ 147 /* Private variables ---------------------------------------------------------*/ 148 /* Private function prototypes -----------------------------------------------*/ 149 /* Private functions ---------------------------------------------------------*/ 150 /* Exported functions --------------------------------------------------------*/ 151 /** @defgroup GPIO_Exported_Functions GPIO Exported Functions 152 * @{ 153 */ 154 155 /** @defgroup GPIO_Exported_Functions_Group1 Initialization and de-initialization functions 156 * @brief Initialization and Configuration functions 157 * 158 @verbatim 159 =============================================================================== 160 ##### Initialization and de-initialization functions ##### 161 =============================================================================== 162 [..] 163 This section provides functions allowing to initialize and de-initialize the GPIOs 164 to be ready for use. 165 166 @endverbatim 167 * @{ 168 */ 169 170 /** 171 * @brief Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init. 172 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 173 * @param GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains 174 * the configuration information for the specified GPIO peripheral. 175 * @retval None 176 */ 177 void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) 178 { 179 uint32_t position = 0x00u; 180 uint32_t ioposition; 181 uint32_t iocurrent; 182 uint32_t temp; 183 uint32_t config = 0x00u; 184 __IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */ 185 uint32_t registeroffset; /* offset used during computation of CNF and MODE bits placement inside CRL or CRH register */ 186 187 /* Check the parameters */ 188 assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); 189 assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); 190 assert_param(IS_GPIO_MODE(GPIO_Init->Mode)); 191 192 /* Configure the port pins */ 193 while (((GPIO_Init->Pin) >> position) != 0x00u) { 194 /* Get the IO position */ 195 ioposition = (0x01uL << position); 196 197 /* Get the current IO position */ 198 iocurrent = (uint32_t) (GPIO_Init->Pin) & ioposition; 199 200 if (iocurrent == ioposition) { 201 /* Check the Alternate function parameters */ 202 assert_param(IS_GPIO_AF_INSTANCE(GPIOx)); 203 204 /* Based on the required mode, filling config variable with MODEy[1:0] and CNFy[3:2] corresponding bits */ 205 switch (GPIO_Init->Mode) { 206 /* If we are configuring the pin in OUTPUT push-pull mode */ 207 case GPIO_MODE_OUTPUT_PP: 208 /* Check the GPIO speed parameter */ 209 assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); 210 config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_PP; 211 break; 212 213 /* If we are configuring the pin in OUTPUT open-drain mode */ 214 case GPIO_MODE_OUTPUT_OD: 215 /* Check the GPIO speed parameter */ 216 assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); 217 config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_OD; 218 break; 219 220 /* If we are configuring the pin in ALTERNATE FUNCTION push-pull mode */ 221 case GPIO_MODE_AF_PP: 222 /* Check the GPIO speed parameter */ 223 assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); 224 config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_PP; 225 break; 226 227 /* If we are configuring the pin in ALTERNATE FUNCTION open-drain mode */ 228 case GPIO_MODE_AF_OD: 229 /* Check the GPIO speed parameter */ 230 assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); 231 config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_OD; 232 break; 233 234 /* If we are configuring the pin in INPUT (also applicable to EVENT and IT mode) */ 235 case GPIO_MODE_INPUT: 236 case GPIO_MODE_IT_RISING: 237 case GPIO_MODE_IT_FALLING: 238 case GPIO_MODE_IT_RISING_FALLING: 239 case GPIO_MODE_EVT_RISING: 240 case GPIO_MODE_EVT_FALLING: 241 case GPIO_MODE_EVT_RISING_FALLING: 242 /* Check the GPIO pull parameter */ 243 assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); 244 if (GPIO_Init->Pull == GPIO_NOPULL) { 245 config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_FLOATING; 246 } else if (GPIO_Init->Pull == GPIO_PULLUP) { 247 config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD; 248 249 /* Set the corresponding ODR bit */ 250 GPIOx->BSRR = ioposition; 251 } else /* GPIO_PULLDOWN */ 252 { 253 config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD; 254 255 /* Reset the corresponding ODR bit */ 256 GPIOx->BRR = ioposition; 257 } 258 break; 259 260 /* If we are configuring the pin in INPUT analog mode */ 261 case GPIO_MODE_ANALOG: 262 config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_ANALOG; 263 break; 264 265 /* Parameters are checked with assert_param */ 266 default: 267 break; 268 } 269 270 /* Check if the current bit belongs to first half or last half of the pin count number 271 in order to address CRH or CRL register*/ 272 configregister = 273 (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL : &GPIOx->CRH; 274 registeroffset = 275 (iocurrent < GPIO_PIN_8) ? 276 (position << 2u) : ((position - 8u) << 2u); 277 278 /* Apply the new configuration of the pin to the register */ 279 MODIFY_REG((*configregister), 280 ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset), 281 (config << registeroffset)); 282 283 /*--------------------- EXTI Mode Configuration ------------------------*/ 284 /* Configure the External Interrupt or event for the current IO */ 285 if ((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE) { 286 /* Enable AFIO Clock */ 287 __HAL_RCC_AFIO_CLK_ENABLE(); 288 temp = AFIO->EXTICR[position >> 2u]; 289 CLEAR_BIT(temp, (0x0Fu) << (4u * (position & 0x03u))); 290 SET_BIT(temp, 291 (GPIO_GET_INDEX(GPIOx)) << (4u * (position & 0x03u))); 292 AFIO->EXTICR[position >> 2u] = temp; 293 294 /* Enable or disable the rising trigger */ 295 if ((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE) { 296 SET_BIT(EXTI->RTSR, iocurrent); 297 } else { 298 CLEAR_BIT(EXTI->RTSR, iocurrent); 299 } 300 301 /* Enable or disable the falling trigger */ 302 if ((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE) { 303 SET_BIT(EXTI->FTSR, iocurrent); 304 } else { 305 CLEAR_BIT(EXTI->FTSR, iocurrent); 306 } 307 308 /* Configure the event mask */ 309 if ((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT) { 310 SET_BIT(EXTI->EMR, iocurrent); 311 } else { 312 CLEAR_BIT(EXTI->EMR, iocurrent); 313 } 314 315 /* Configure the interrupt mask */ 316 if ((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT) { 317 SET_BIT(EXTI->IMR, iocurrent); 318 } else { 319 CLEAR_BIT(EXTI->IMR, iocurrent); 320 } 321 } 322 } 323 324 position++; 325 } 326 } 327 328 /** 329 * @brief De-initializes the GPIOx peripheral registers to their default reset values. 330 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 331 * @param GPIO_Pin: specifies the port bit to be written. 332 * This parameter can be one of GPIO_PIN_x where x can be (0..15). 333 * @retval None 334 */ 335 void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin) 336 { 337 uint32_t position = 0x00u; 338 uint32_t iocurrent; 339 uint32_t tmp; 340 __IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */ 341 uint32_t registeroffset; 342 343 /* Check the parameters */ 344 assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); 345 assert_param(IS_GPIO_PIN(GPIO_Pin)); 346 347 /* Configure the port pins */ 348 while ((GPIO_Pin >> position) != 0u) { 349 /* Get current io position */ 350 iocurrent = (GPIO_Pin) & (1uL << position); 351 352 if (iocurrent) { 353 /*------------------------- EXTI Mode Configuration --------------------*/ 354 /* Clear the External Interrupt or Event for the current IO */ 355 356 tmp = AFIO->EXTICR[position >> 2u]; 357 tmp &= 0x0FuL << (4u * (position & 0x03u)); 358 if (tmp == (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u)))) { 359 /* Clear EXTI line configuration */ 360 CLEAR_BIT(EXTI->IMR, (uint32_t )iocurrent); 361 CLEAR_BIT(EXTI->EMR, (uint32_t )iocurrent); 362 363 /* Clear Rising Falling edge configuration */ 364 CLEAR_BIT(EXTI->FTSR, (uint32_t )iocurrent); 365 CLEAR_BIT(EXTI->RTSR, (uint32_t )iocurrent); 366 367 tmp = 0x0FuL << (4u * (position & 0x03u)); 368 CLEAR_BIT(AFIO->EXTICR[position >> 2u], tmp); 369 } 370 /*------------------------- GPIO Mode Configuration --------------------*/ 371 /* Check if the current bit belongs to first half or last half of the pin count number 372 in order to address CRH or CRL register */ 373 configregister = 374 (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL : &GPIOx->CRH; 375 registeroffset = 376 (iocurrent < GPIO_PIN_8) ? 377 (position << 2u) : ((position - 8u) << 2u); 378 379 /* CRL/CRH default value is floating input(0x04) shifted to correct position */ 380 MODIFY_REG(*configregister, 381 ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset), 382 GPIO_CRL_CNF0_0 << registeroffset); 383 384 /* ODR default value is 0 */ 385 CLEAR_BIT(GPIOx->ODR, iocurrent); 386 } 387 388 position++; 389 } 390 } 391 392 /** 393 * @} 394 */ 395 396 /** @defgroup GPIO_Exported_Functions_Group2 IO operation functions 397 * @brief GPIO Read and Write 398 * 399 @verbatim 400 =============================================================================== 401 ##### IO operation functions ##### 402 =============================================================================== 403 [..] 404 This subsection provides a set of functions allowing to manage the GPIOs. 405 406 @endverbatim 407 * @{ 408 */ 409 410 /** 411 * @brief Reads the specified input port pin. 412 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 413 * @param GPIO_Pin: specifies the port bit to read. 414 * This parameter can be GPIO_PIN_x where x can be (0..15). 415 * @retval The input port pin value. 416 */ 417 GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 418 { 419 GPIO_PinState bitstatus; 420 421 /* Check the parameters */ 422 assert_param(IS_GPIO_PIN(GPIO_Pin)); 423 424 if ((GPIOx->IDR & GPIO_Pin) != (uint32_t) GPIO_PIN_RESET) { 425 bitstatus = GPIO_PIN_SET; 426 } else { 427 bitstatus = GPIO_PIN_RESET; 428 } 429 return bitstatus; 430 } 431 432 /** 433 * @brief Sets or clears the selected data port bit. 434 * 435 * @note This function uses GPIOx_BSRR register to allow atomic read/modify 436 * accesses. In this way, there is no risk of an IRQ occurring between 437 * the read and the modify access. 438 * 439 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 440 * @param GPIO_Pin: specifies the port bit to be written. 441 * This parameter can be one of GPIO_PIN_x where x can be (0..15). 442 * @param PinState: specifies the value to be written to the selected bit. 443 * This parameter can be one of the GPIO_PinState enum values: 444 * @arg GPIO_PIN_RESET: to clear the port pin 445 * @arg GPIO_PIN_SET: to set the port pin 446 * @retval None 447 */ 448 void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, 449 GPIO_PinState PinState) 450 { 451 /* Check the parameters */ 452 assert_param(IS_GPIO_PIN(GPIO_Pin)); 453 assert_param(IS_GPIO_PIN_ACTION(PinState)); 454 455 if (PinState != GPIO_PIN_RESET) { 456 GPIOx->BSRR = GPIO_Pin; 457 } else { 458 GPIOx->BSRR = (uint32_t) GPIO_Pin << 16u; 459 } 460 } 461 462 /** 463 * @brief Toggles the specified GPIO pin 464 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 465 * @param GPIO_Pin: Specifies the pins to be toggled. 466 * @retval None 467 */ 468 void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 469 { 470 uint32_t odr; 471 472 /* Check the parameters */ 473 assert_param(IS_GPIO_PIN(GPIO_Pin)); 474 475 /* get current Output Data Register value */ 476 odr = GPIOx->ODR; 477 478 /* Set selected pins that were at low level, and reset ones that were high */ 479 GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin); 480 } 481 482 /** 483 * @brief Locks GPIO Pins configuration registers. 484 * @note The locking mechanism allows the IO configuration to be frozen. When the LOCK sequence 485 * has been applied on a port bit, it is no longer possible to modify the value of the port bit until 486 * the next reset. 487 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 488 * @param GPIO_Pin: specifies the port bit to be locked. 489 * This parameter can be any combination of GPIO_PIN_x where x can be (0..15). 490 * @retval None 491 */ 492 HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 493 { 494 __IO uint32_t tmp = GPIO_LCKR_LCKK; 495 496 /* Check the parameters */ 497 assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx)); 498 assert_param(IS_GPIO_PIN(GPIO_Pin)); 499 500 /* Apply lock key write sequence */ 501 SET_BIT(tmp, GPIO_Pin); 502 /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ 503 GPIOx->LCKR = tmp; 504 /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */ 505 GPIOx->LCKR = GPIO_Pin; 506 /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ 507 GPIOx->LCKR = tmp; 508 /* Read LCKK register. This read is mandatory to complete key lock sequence */ 509 tmp = GPIOx->LCKR; 510 511 /* read again in order to confirm lock is active */ 512 if ((uint32_t) (GPIOx->LCKR & GPIO_LCKR_LCKK)) { 513 return HAL_OK; 514 } else { 515 return HAL_ERROR; 516 } 517 } 518 519 /** 520 * @brief This function handles EXTI interrupt request. 521 * @param GPIO_Pin: Specifies the pins connected EXTI line 522 * @retval None 523 */ 524 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) 525 { 526 /* EXTI line interrupt detected */ 527 if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u) { 528 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); 529 HAL_GPIO_EXTI_Callback(GPIO_Pin); 530 } 531 } 532 533 /** 534 * @brief EXTI line detection callbacks. 535 * @param GPIO_Pin: Specifies the pins connected EXTI line 536 * @retval None 537 */ 538 __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 539 { 540 /* Prevent unused argument(s) compilation warning */ 541 UNUSED(GPIO_Pin); 542 /* NOTE: This function Should not be modified, when the callback is needed, 543 the HAL_GPIO_EXTI_Callback could be implemented in the user file 544 */ 545 } 546 547 /** 548 * @} 549 */ 550 551 /** 552 * @} 553 */ 554 555 #endif /* HAL_GPIO_MODULE_ENABLED */ 556 /** 557 * @} 558 */ 559 560 /** 561 * @} 562 */ 563
