Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c (21479B)
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 /** 172 * @brief Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init. 173 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 174 * @param GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains 175 * the configuration information for the specified GPIO peripheral. 176 * @retval None 177 */ 178 void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) 179 { 180 uint32_t position = 0x00u; 181 uint32_t ioposition; 182 uint32_t iocurrent; 183 uint32_t temp; 184 uint32_t config = 0x00u; 185 __IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */ 186 uint32_t registeroffset; /* offset used during computation of CNF and MODE bits placement inside CRL or CRH register */ 187 188 /* Check the parameters */ 189 assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); 190 assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); 191 assert_param(IS_GPIO_MODE(GPIO_Init->Mode)); 192 193 /* Configure the port pins */ 194 while (((GPIO_Init->Pin) >> position) != 0x00u) 195 { 196 /* Get the IO position */ 197 ioposition = (0x01uL << position); 198 199 /* Get the current IO position */ 200 iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition; 201 202 if (iocurrent == ioposition) 203 { 204 /* Check the Alternate function parameters */ 205 assert_param(IS_GPIO_AF_INSTANCE(GPIOx)); 206 207 /* Based on the required mode, filling config variable with MODEy[1:0] and CNFy[3:2] corresponding bits */ 208 switch (GPIO_Init->Mode) 209 { 210 /* If we are configuring the pin in OUTPUT push-pull mode */ 211 case GPIO_MODE_OUTPUT_PP: 212 /* Check the GPIO speed parameter */ 213 assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); 214 config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_PP; 215 break; 216 217 /* If we are configuring the pin in OUTPUT open-drain mode */ 218 case GPIO_MODE_OUTPUT_OD: 219 /* Check the GPIO speed parameter */ 220 assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); 221 config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_OD; 222 break; 223 224 /* If we are configuring the pin in ALTERNATE FUNCTION push-pull mode */ 225 case GPIO_MODE_AF_PP: 226 /* Check the GPIO speed parameter */ 227 assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); 228 config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_PP; 229 break; 230 231 /* If we are configuring the pin in ALTERNATE FUNCTION open-drain mode */ 232 case GPIO_MODE_AF_OD: 233 /* Check the GPIO speed parameter */ 234 assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); 235 config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_OD; 236 break; 237 238 /* If we are configuring the pin in INPUT (also applicable to EVENT and IT mode) */ 239 case GPIO_MODE_INPUT: 240 case GPIO_MODE_IT_RISING: 241 case GPIO_MODE_IT_FALLING: 242 case GPIO_MODE_IT_RISING_FALLING: 243 case GPIO_MODE_EVT_RISING: 244 case GPIO_MODE_EVT_FALLING: 245 case GPIO_MODE_EVT_RISING_FALLING: 246 /* Check the GPIO pull parameter */ 247 assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); 248 if (GPIO_Init->Pull == GPIO_NOPULL) 249 { 250 config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_FLOATING; 251 } 252 else if (GPIO_Init->Pull == GPIO_PULLUP) 253 { 254 config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD; 255 256 /* Set the corresponding ODR bit */ 257 GPIOx->BSRR = ioposition; 258 } 259 else /* GPIO_PULLDOWN */ 260 { 261 config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD; 262 263 /* Reset the corresponding ODR bit */ 264 GPIOx->BRR = ioposition; 265 } 266 break; 267 268 /* If we are configuring the pin in INPUT analog mode */ 269 case GPIO_MODE_ANALOG: 270 config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_ANALOG; 271 break; 272 273 /* Parameters are checked with assert_param */ 274 default: 275 break; 276 } 277 278 /* Check if the current bit belongs to first half or last half of the pin count number 279 in order to address CRH or CRL register*/ 280 configregister = (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL : &GPIOx->CRH; 281 registeroffset = (iocurrent < GPIO_PIN_8) ? (position << 2u) : ((position - 8u) << 2u); 282 283 /* Apply the new configuration of the pin to the register */ 284 MODIFY_REG((*configregister), ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset), (config << registeroffset)); 285 286 /*--------------------- EXTI Mode Configuration ------------------------*/ 287 /* Configure the External Interrupt or event for the current IO */ 288 if ((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE) 289 { 290 /* Enable AFIO Clock */ 291 __HAL_RCC_AFIO_CLK_ENABLE(); 292 temp = AFIO->EXTICR[position >> 2u]; 293 CLEAR_BIT(temp, (0x0Fu) << (4u * (position & 0x03u))); 294 SET_BIT(temp, (GPIO_GET_INDEX(GPIOx)) << (4u * (position & 0x03u))); 295 AFIO->EXTICR[position >> 2u] = temp; 296 297 298 /* Enable or disable the rising trigger */ 299 if ((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE) 300 { 301 SET_BIT(EXTI->RTSR, iocurrent); 302 } 303 else 304 { 305 CLEAR_BIT(EXTI->RTSR, iocurrent); 306 } 307 308 /* Enable or disable the falling trigger */ 309 if ((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE) 310 { 311 SET_BIT(EXTI->FTSR, iocurrent); 312 } 313 else 314 { 315 CLEAR_BIT(EXTI->FTSR, iocurrent); 316 } 317 318 /* Configure the event mask */ 319 if ((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT) 320 { 321 SET_BIT(EXTI->EMR, iocurrent); 322 } 323 else 324 { 325 CLEAR_BIT(EXTI->EMR, iocurrent); 326 } 327 328 /* Configure the interrupt mask */ 329 if ((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT) 330 { 331 SET_BIT(EXTI->IMR, iocurrent); 332 } 333 else 334 { 335 CLEAR_BIT(EXTI->IMR, iocurrent); 336 } 337 } 338 } 339 340 position++; 341 } 342 } 343 344 /** 345 * @brief De-initializes the GPIOx peripheral registers to their default reset values. 346 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 347 * @param GPIO_Pin: specifies the port bit to be written. 348 * This parameter can be one of GPIO_PIN_x where x can be (0..15). 349 * @retval None 350 */ 351 void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin) 352 { 353 uint32_t position = 0x00u; 354 uint32_t iocurrent; 355 uint32_t tmp; 356 __IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */ 357 uint32_t registeroffset; 358 359 /* Check the parameters */ 360 assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); 361 assert_param(IS_GPIO_PIN(GPIO_Pin)); 362 363 /* Configure the port pins */ 364 while ((GPIO_Pin >> position) != 0u) 365 { 366 /* Get current io position */ 367 iocurrent = (GPIO_Pin) & (1uL << position); 368 369 if (iocurrent) 370 { 371 /*------------------------- EXTI Mode Configuration --------------------*/ 372 /* Clear the External Interrupt or Event for the current IO */ 373 374 tmp = AFIO->EXTICR[position >> 2u]; 375 tmp &= 0x0FuL << (4u * (position & 0x03u)); 376 if (tmp == (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u)))) 377 { 378 /* Clear EXTI line configuration */ 379 CLEAR_BIT(EXTI->IMR, (uint32_t)iocurrent); 380 CLEAR_BIT(EXTI->EMR, (uint32_t)iocurrent); 381 382 /* Clear Rising Falling edge configuration */ 383 CLEAR_BIT(EXTI->FTSR, (uint32_t)iocurrent); 384 CLEAR_BIT(EXTI->RTSR, (uint32_t)iocurrent); 385 386 tmp = 0x0FuL << (4u * (position & 0x03u)); 387 CLEAR_BIT(AFIO->EXTICR[position >> 2u], tmp); 388 } 389 /*------------------------- GPIO Mode Configuration --------------------*/ 390 /* Check if the current bit belongs to first half or last half of the pin count number 391 in order to address CRH or CRL register */ 392 configregister = (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL : &GPIOx->CRH; 393 registeroffset = (iocurrent < GPIO_PIN_8) ? (position << 2u) : ((position - 8u) << 2u); 394 395 /* CRL/CRH default value is floating input(0x04) shifted to correct position */ 396 MODIFY_REG(*configregister, ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset), GPIO_CRL_CNF0_0 << registeroffset); 397 398 /* ODR default value is 0 */ 399 CLEAR_BIT(GPIOx->ODR, iocurrent); 400 } 401 402 position++; 403 } 404 } 405 406 /** 407 * @} 408 */ 409 410 /** @defgroup GPIO_Exported_Functions_Group2 IO operation functions 411 * @brief GPIO Read and Write 412 * 413 @verbatim 414 =============================================================================== 415 ##### IO operation functions ##### 416 =============================================================================== 417 [..] 418 This subsection provides a set of functions allowing to manage the GPIOs. 419 420 @endverbatim 421 * @{ 422 */ 423 424 /** 425 * @brief Reads the specified input port pin. 426 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 427 * @param GPIO_Pin: specifies the port bit to read. 428 * This parameter can be GPIO_PIN_x where x can be (0..15). 429 * @retval The input port pin value. 430 */ 431 GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 432 { 433 GPIO_PinState bitstatus; 434 435 /* Check the parameters */ 436 assert_param(IS_GPIO_PIN(GPIO_Pin)); 437 438 if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET) 439 { 440 bitstatus = GPIO_PIN_SET; 441 } 442 else 443 { 444 bitstatus = GPIO_PIN_RESET; 445 } 446 return bitstatus; 447 } 448 449 /** 450 * @brief Sets or clears the selected data port bit. 451 * 452 * @note This function uses GPIOx_BSRR register to allow atomic read/modify 453 * accesses. In this way, there is no risk of an IRQ occurring between 454 * the read and the modify access. 455 * 456 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 457 * @param GPIO_Pin: specifies the port bit to be written. 458 * This parameter can be one of GPIO_PIN_x where x can be (0..15). 459 * @param PinState: specifies the value to be written to the selected bit. 460 * This parameter can be one of the GPIO_PinState enum values: 461 * @arg GPIO_PIN_RESET: to clear the port pin 462 * @arg GPIO_PIN_SET: to set the port pin 463 * @retval None 464 */ 465 void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) 466 { 467 /* Check the parameters */ 468 assert_param(IS_GPIO_PIN(GPIO_Pin)); 469 assert_param(IS_GPIO_PIN_ACTION(PinState)); 470 471 if (PinState != GPIO_PIN_RESET) 472 { 473 GPIOx->BSRR = GPIO_Pin; 474 } 475 else 476 { 477 GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u; 478 } 479 } 480 481 /** 482 * @brief Toggles the specified GPIO pin 483 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 484 * @param GPIO_Pin: Specifies the pins to be toggled. 485 * @retval None 486 */ 487 void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 488 { 489 uint32_t odr; 490 491 /* Check the parameters */ 492 assert_param(IS_GPIO_PIN(GPIO_Pin)); 493 494 /* get current Output Data Register value */ 495 odr = GPIOx->ODR; 496 497 /* Set selected pins that were at low level, and reset ones that were high */ 498 GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin); 499 } 500 501 /** 502 * @brief Locks GPIO Pins configuration registers. 503 * @note The locking mechanism allows the IO configuration to be frozen. When the LOCK sequence 504 * has been applied on a port bit, it is no longer possible to modify the value of the port bit until 505 * the next reset. 506 * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral 507 * @param GPIO_Pin: specifies the port bit to be locked. 508 * This parameter can be any combination of GPIO_PIN_x where x can be (0..15). 509 * @retval None 510 */ 511 HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 512 { 513 __IO uint32_t tmp = GPIO_LCKR_LCKK; 514 515 /* Check the parameters */ 516 assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx)); 517 assert_param(IS_GPIO_PIN(GPIO_Pin)); 518 519 /* Apply lock key write sequence */ 520 SET_BIT(tmp, GPIO_Pin); 521 /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ 522 GPIOx->LCKR = tmp; 523 /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */ 524 GPIOx->LCKR = GPIO_Pin; 525 /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ 526 GPIOx->LCKR = tmp; 527 /* Read LCKK register. This read is mandatory to complete key lock sequence */ 528 tmp = GPIOx->LCKR; 529 530 /* read again in order to confirm lock is active */ 531 if ((uint32_t)(GPIOx->LCKR & GPIO_LCKR_LCKK)) 532 { 533 return HAL_OK; 534 } 535 else 536 { 537 return HAL_ERROR; 538 } 539 } 540 541 /** 542 * @brief This function handles EXTI interrupt request. 543 * @param GPIO_Pin: Specifies the pins connected EXTI line 544 * @retval None 545 */ 546 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) 547 { 548 /* EXTI line interrupt detected */ 549 if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u) 550 { 551 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); 552 HAL_GPIO_EXTI_Callback(GPIO_Pin); 553 } 554 } 555 556 /** 557 * @brief EXTI line detection callbacks. 558 * @param GPIO_Pin: Specifies the pins connected EXTI line 559 * @retval None 560 */ 561 __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 562 { 563 /* Prevent unused argument(s) compilation warning */ 564 UNUSED(GPIO_Pin); 565 /* NOTE: This function Should not be modified, when the callback is needed, 566 the HAL_GPIO_EXTI_Callback could be implemented in the user file 567 */ 568 } 569 570 /** 571 * @} 572 */ 573 574 /** 575 * @} 576 */ 577 578 #endif /* HAL_GPIO_MODULE_ENABLED */ 579 /** 580 * @} 581 */ 582 583 /** 584 * @} 585 */ 586
