/* ---------------------------------------------------------------------- * Copyright (C) 2016 ARM Limited. All rights reserved. * * $Date: 26. April 2016 * $Revision: V1.3 * * Project: GPIO Driver for ST STM32F10x * -------------------------------------------------------------------- */ #include "GPIO_STM32F10x.h" /* History: * Version 1.3 * Corrected corruption of Serial wire JTAG pins alternate function configuration. * Version 1.2 * Added GPIO_GetPortClockState function * GPIO_PinConfigure function enables GPIO peripheral clock, if not already enabled * Version 1.1 * GPIO_PortClock and GPIO_PinConfigure functions rewritten * GPIO_STM32F1xx header file cleaned up and simplified * GPIO_AFConfigure function and accompanying definitions added * Version 1.0 * Initial release */ /* Serial wire JTAG pins alternate function Configuration * Can be user defined by C preprocessor: * AFIO_SWJ_FULL, AFIO_SWJ_FULL_NO_NJTRST, AFIO_SWJ_JTAG_NO_SW, AFIO_SWJ_NO_JTAG_NO_SW */ #ifndef AFIO_MAPR_SWJ_CFG_VAL #define AFIO_MAPR_SWJ_CFG_VAL (AFIO_SWJ_FULL) // Full SWJ (JTAG-DP + SW-DP) #endif /** \fn void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool en) \brief Port Clock Control \param[in] GPIOx Pointer to GPIO peripheral \param[in] enable Enable or disable clock */ void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool enable) { if (enable) { if (GPIOx == GPIOA) RCC->APB2ENR |= (1U << 2); else if (GPIOx == GPIOB) RCC->APB2ENR |= (1U << 3); else if (GPIOx == GPIOC) RCC->APB2ENR |= (1U << 4); else if (GPIOx == GPIOD) RCC->APB2ENR |= (1U << 5); else if (GPIOx == GPIOE) RCC->APB2ENR |= (1U << 6); else if (GPIOx == GPIOF) RCC->APB2ENR |= (1U << 7); else if (GPIOx == GPIOG) RCC->APB2ENR |= (1U << 8); } else { if (GPIOx == GPIOA) RCC->APB2ENR &= ~(1U << 2); else if (GPIOx == GPIOB) RCC->APB2ENR &= ~(1U << 3); else if (GPIOx == GPIOC) RCC->APB2ENR &= ~(1U << 4); else if (GPIOx == GPIOD) RCC->APB2ENR &= ~(1U << 5); else if (GPIOx == GPIOE) RCC->APB2ENR &= ~(1U << 6); else if (GPIOx == GPIOF) RCC->APB2ENR &= ~(1U << 7); else if (GPIOx == GPIOG) RCC->APB2ENR &= ~(1U << 8); } } /** \fn bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx) \brief Get GPIO port clock state \param[in] GPIOx Pointer to GPIO peripheral \return true - enabled false - disabled */ bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx) { if (GPIOx == GPIOA) { return ((RCC->APB2ENR & (1U << 2)) != 0U); } else if (GPIOx == GPIOB) { return ((RCC->APB2ENR & (1U << 3)) != 0U); } else if (GPIOx == GPIOC) { return ((RCC->APB2ENR & (1U << 4)) != 0U); } else if (GPIOx == GPIOD) { return ((RCC->APB2ENR & (1U << 5)) != 0U); } else if (GPIOx == GPIOE) { return ((RCC->APB2ENR & (1U << 6)) != 0U); } else if (GPIOx == GPIOF) { return ((RCC->APB2ENR & (1U << 7)) != 0U); } else if (GPIOx == GPIOG) { return ((RCC->APB2ENR & (1U << 8)) != 0U); } return false; } /** \fn bool GPIO_PinConfigure (GPIO_TypeDef *GPIOx, uint32_t num, GPIO_CONF conf, GPIO_MODE mode) \brief Configure port pin \param[in] GPIOx Pointer to GPIO peripheral \param[in] num Port pin number \param[in] mode \ref GPIO_MODE \param[in] conf \ref GPIO_CONF \return true - success false - error */ bool GPIO_PinConfigure(GPIO_TypeDef *GPIOx, uint32_t num, GPIO_CONF conf, GPIO_MODE mode) { __IO uint32_t *reg; if (num > 15) return false; if (GPIO_GetPortClockState(GPIOx) == false) { /* Enable GPIOx peripheral clock */ GPIO_PortClock (GPIOx, true); } if (mode == GPIO_MODE_INPUT) { if (conf == GPIO_IN_PULL_DOWN) { /* Enable pull down on selected input */ GPIOx->ODR &= ~(1 << num); } else if (conf == GPIO_IN_PULL_UP) { /* Enable pull up on selected input */ conf &= ~1; GPIOx->ODR |= (1 << num); } } if (num < 8) { reg = &GPIOx->CRL; } else { num -= 8; reg = &GPIOx->CRH; } *reg &= ~(0xF << (num << 2)); *reg |= ((conf << 2) | mode) << (num << 2); return true; } /** \fn void GPIO_AFConfigure (AFIO_REMAP af_type) \brief Configure alternate functions \param[in] af_type Alternate function remap type */ void GPIO_AFConfigure (AFIO_REMAP af_type) { uint32_t msk, val; volatile uint32_t mapr; if (af_type != AFIO_UNAVAILABLE_REMAP) { msk = (af_type >> 5) & 0x07; val = (af_type >> 8) & 0x0F; if (!(RCC->APB2ENR & RCC_APB2ENR_AFIOEN)) { /* Enable AFIO peripheral clock */ RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; } if (af_type & (1 << 12)) { /* AF remap and debug I/O config register 2 */ mapr = AFIO->MAPR2; mapr &= ~(msk << (af_type & 0x1F)); mapr |= (val << (af_type & 0x1F)); AFIO->MAPR2 = mapr; } else { /* AF remap and debug I/O config register */ mapr = AFIO->MAPR; mapr &= ~(msk << (af_type & 0x1F)); mapr |= (val << (af_type & 0x1F)); /* Serial wire JTAG configuration */ msk = (AFIO_MAPR_SWJ_CFG_VAL >> 5) & 0x07; val = (AFIO_MAPR_SWJ_CFG_VAL >> 8) & 0x0F; mapr &= ~(msk << (AFIO_MAPR_SWJ_CFG_VAL & 0x1F)); mapr |= (val << (AFIO_MAPR_SWJ_CFG_VAL & 0x1F)); AFIO->MAPR = mapr; } } }