/*! * @file apm32s10x_gpio.c * * @brief This file provides all the GPIO firmware functions * * @version V1.0.1 * * @date 2022-12-31 * * @attention * * Copyright (C) 2022-2023 Geehy Semiconductor * * You may not use this file except in compliance with the * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope * that it will be usefull and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions * and limitations under the License. */ /* Includes */ #include "apm32s10x_gpio.h" #include "apm32s10x_rcm.h" /** @addtogroup APM32S10x_StdPeriphDriver @{ */ /** @addtogroup GPIO_Driver GPIO Driver @{ */ /** @defgroup GPIO_Functions Functions @{ */ /*! * @brief Reset GPIO peripheral registers to their default reset values * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @retval None */ void GPIO_Reset(GPIO_T* port) { RCM_APB2_PERIPH_T APB2Periph; if (port == GPIOA) { APB2Periph = RCM_APB2_PERIPH_GPIOA; } else if (port == GPIOB) { APB2Periph = RCM_APB2_PERIPH_GPIOB; } else if (port == GPIOC) { APB2Periph = RCM_APB2_PERIPH_GPIOC; } else if (port == GPIOD) { APB2Periph = RCM_APB2_PERIPH_GPIOD; } else if (port == GPIOE) { APB2Periph = RCM_APB2_PERIPH_GPIOE; } RCM_EnableAPB2PeriphReset(APB2Periph); RCM_DisableAPB2PeriphReset(APB2Periph); } /*! * @brief Reset Alternate Functions registers to their default reset values * * @param None * * @retval None */ void GPIO_AFIOReset(void) { RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_AFIO); RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_AFIO); } /*! * @brief Configure the GPIO peripheral according to the specified parameters in the gpioConfig * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @param gpioConfig: pointer to a GPIO_Config_T structure * * @retval None */ void GPIO_Config(GPIO_T* port, GPIO_Config_T* gpioConfig) { uint8_t i; uint32_t mode; uint32_t CR; uint32_t temp; uint32_t shift; mode = gpioConfig->mode & 0x0f; if (gpioConfig->mode & 0x80) { mode |= gpioConfig->speed; } if (gpioConfig->pin & 0xff) { CR = port->CFGLOW; for (i = 0, shift = 0x01; i < 8; i++, shift <<= 1) { if (gpioConfig->pin & shift) { temp = i << 2; CR &= (uint32_t)~(0x0f << temp); CR |= mode << temp; if (gpioConfig->mode == GPIO_MODE_IN_PD) { port->BC = shift; } else if (gpioConfig->mode == GPIO_MODE_IN_PU) { port->BSC = shift; } } } port->CFGLOW = CR; } if (gpioConfig->pin & 0xff00) { CR = port->CFGHIG; for (i = 8, shift = 0x100; i < 16; i++, shift <<= 1) { if (gpioConfig->pin & shift) { temp = (i - 8) << 2; CR &= (uint32_t)~(0x0f << temp); CR |= mode << temp; if (gpioConfig->mode == GPIO_MODE_IN_PD) { port->BC = shift; } else if (gpioConfig->mode == GPIO_MODE_IN_PU) { port->BSC = shift; } } } port->CFGHIG = CR; } } /*! * @brief Fill each gpioConfig member with its default value. * * @param gpioConfig : pointer to a GPIO_Config_T structure which will be initialized. * * @retval None */ void GPIO_ConfigStructInit(GPIO_Config_T* gpioConfig) { gpioConfig->pin = GPIO_PIN_ALL; gpioConfig->speed = GPIO_SPEED_2MHz; gpioConfig->mode = GPIO_MODE_IN_FLOATING; } /*! * @brief Read the specified input port pin * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @param pin : specify pin to read. * This parameter can be one of GPIO_PIN_x( x can be from 0 to 15). * * @retval The input port pin value */ uint8_t GPIO_ReadInputBit(GPIO_T* port, uint16_t pin) { uint8_t ret; ret = (port->IDATA & pin) ? BIT_SET : BIT_RESET; return ret; } /*! * @brief Read the specified GPIO input data port * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @retval GPIO input data port value */ uint16_t GPIO_ReadInputPort(GPIO_T* port) { return (uint16_t)port->IDATA; } /*! * @brief Read the specified output data port bit * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @param pin : specify pin to read. * This parameter can be one of GPIO_PIN_x( x can be from 0 to 15). * * @retval The output port pin value */ uint8_t GPIO_ReadOutputBit(GPIO_T* port, uint16_t pin) { uint8_t ret; ret = (port->ODATA & pin) ? BIT_SET : BIT_RESET; return ret; } /*! * @brief Read the specified GPIO output data port * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @retval output data port value */ uint16_t GPIO_ReadOutputPort(GPIO_T* port) { return (uint16_t)port->ODATA; } /*! * @brief Set the selected data port bits * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @param pin : specify pin to be written. * This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15). * * @retval None */ void GPIO_SetBit(GPIO_T* port, uint16_t pin) { port->BSC = (uint32_t)pin; } /*! * @brief Clear the selected data port bits * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @param pin : specify pin to be cleared. * This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15). * * @retval None */ void GPIO_ResetBit(GPIO_T* port, uint16_t pin) { port->BC = (uint32_t)pin; } /*! * @brief Write data to the specified GPIO data port bit * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @param pin : Select specifies pin. * This parameter can be one of GPIO_PIN_x( x can be from 0 to 15). * * @param bitVal : specify the value to be written to the port output data register * This parameter can be one of the following values: * @arg BIT_RESET: Reset the port pin * @arg BIT_SET : Set the port pin * * @retval None */ void GPIO_WriteBitValue(GPIO_T* port, uint16_t pin, uint8_t bitVal) { if (bitVal != BIT_RESET) { port->BSC = pin; } else { port->BC = pin ; } } /*! * @brief Write data to the specified GPIO data port * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @param portValue : specify the value to be written to the port output data register. * * @retval None */ void GPIO_WriteOutputPort(GPIO_T* port, uint16_t portValue) { port->ODATA = (uint32_t)portValue; } /*! * @brief Lock GPIO Pins configuration registers * * @param port: Select the GPIO port. * This parameter can be one of GPIOx( x can be from A to E). * * @param pin : Select specifies pin. * This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15). * * @retval None */ void GPIO_ConfigPinLock(GPIO_T* port, uint16_t pin) { uint32_t val = 0x00010000; val |= pin; /* Set LCKK bit */ port->LOCK = val ; /* Reset LCKK bit */ port->LOCK = pin; /* Set LCKK bit */ port->LOCK = val; /* Read LCKK bit */ val = port->LOCK; /* Read LCKK bit */ val = port->LOCK; } /*! * @brief Select the GPIO pin used as Event output * * @param portSource: select the GPIO port to be used as source for Event output. * This parameter can be one of GPIO_PORT_SOURCE_x( x can be from A to E). * * @param pinSource : specify the pin for the Event output * This parameter can be GPIO_PIN_SOURCE_x( x can be from 0 to 15). * * @retval None */ void GPIO_ConfigEventOutput(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSource) { AFIO->EVCTRL_B.PORTSEL = portSource; AFIO->EVCTRL_B.PINSEL = pinSource; } /*! * @brief Enable the Event Output * * @param None * * @retval None */ void GPIO_EnableEventOutput(void) { AFIO->EVCTRL_B.EVOEN = BIT_SET; } /*! * @brief Disable the Event Output * * @param None * * @retval None */ void GPIO_DisableEventOutput(void) { AFIO->EVCTRL_B.EVOEN = BIT_RESET; } /*! * @brief Change the mapping of the specified pin * * @param remap : select the pin to remap * This parameter can be one of the following values: * @arg GPIO_NO_REMAP_SPI1 : No SPI1 Alternate Function mapping * @arg GPIO_REMAP_SPI1 : SPI1 Alternate Function mapping * @arg GPIO_NO_REMAP_I2C1 : No I2C1 Alternate Function mapping * @arg GPIO_REMAP_I2C1 : I2C1 Alternate Function mapping * @arg GPIO_NO_REMAP_USART1 : No USART1 Alternate Function mapping * @arg GPIO_REMAP_USART1 : USART1 Alternate Function mapping * @arg GPIO_NO_REMAP_USART2 : No USART2 Alternate Function mapping * @arg GPIO_REMAP_USART2 : USART2 Alternate Function mapping * @arg GPIO_NO_REMAP_USART3 : No USART3 Partial Alternate Function mapping * @arg GPIO_PARTIAL_REMAP_USART3 : USART3 Partial Alternate Function mapping * @arg GPIO_FULL_REMAP_USART3 : USART3 Full Alternate Function mapping * @arg GPIO_NO_REMAP_TMR1 : No TIM1 Partial Alternate Function mapping * @arg GPIO_PARTIAL_REMAP_TMR1 : TIM1 Partial Alternate Function mapping * @arg GPIO_FULL_REMAP_TMR1 : TIM1 Full Alternate Function mapping * @arg GPIO_NO_REMAP1_TMR2 : No TIM2 Partial1 Alternate Function mapping * @arg GPIO_PARTIAL_REMAP1_TMR2 : TIM2 Partial1 Alternate Function mapping * @arg GPIO_PARTIAL_REMAP2_TMR2 : TIM2 Partial2 Alternate Function mapping * @arg GPIO_FULL_REMAP_TMR2 : TIM2 Full Alternate Function mapping * @arg GPIO_NO_REMAP_TMR3 : No TIM3 Partial Alternate Function mapping * @arg GPIO_PARTIAL_REMAP_TMR3 : TIM3 Partial Alternate Function mapping * @arg GPIO_FULL_REMAP_TMR3 : TIM3 Full Alternate Function mapping * @arg GPIO_NO_REMAP_TMR4 : No TIM4 Alternate Function mapping * @arg GPIO_REMAP_TMR4 : TIM4 Alternate Function mapping * @arg GPIO_NO_REMAP_CAN1 : No CAN1 Alternate Function mapping * @arg GPIO_REMAP1_CAN1 : CAN1 Alternate Function mapping * @arg GPIO_REMAP2_CAN1 : CAN1 Alternate Function mapping * @arg GPIO_NO_REMAP_PD01 : No PD01 Alternate Function mapping * @arg GPIO_REMAP_PD01 : PD01 Alternate Function mapping * @arg GPIO_NO_REMAP_ADC1_ETRGINJ : No ADC1 External Trigger Injected Conversion remapping * @arg GPIO_REMAP_ADC1_ETRGINJ : ADC1 External Trigger Injected Conversion remapping * @arg GPIO_NO_REMAP_ADC1_ETRGREG : No ADC1 External Trigger Regular Conversion remapping * @arg GPIO_REMAP_ADC1_ETRGREG : ADC1 External Trigger Regular Conversion remapping * @arg GPIO_NO_REMAP_ADC2_ETRGINJ : No ADC2 External Trigger Injected Conversion remapping * @arg GPIO_REMAP_ADC2_ETRGINJ : ADC2 External Trigger Injected Conversion remapping * @arg GPIO_NO_REMAP_ADC2_ETRGREG : No ADC2 External Trigger Regular Conversion remapping * @arg GPIO_REMAP_ADC2_ETRGREG : ADC2 External Trigger Regular Conversion remapping * @arg GPIO_NO_REMAP_CAN2 : No CAN2 Alternate Function mapping * @arg GPIO_REMAP_CAN2 : CAN2 Alternate Function mapping * @arg GPIO_NO_REMAP_SWJ : Full SWJ Enabled (JTAG-DP + SW-DP) * @arg GPIO_REMAP_SWJ_NOJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST * @arg GPIO_REMAP_SWJ_JTAGDISABLE : JTAG-DP Disabled and SW-DP Enabled * @arg GPIO_REMAP_SWJ_DISABLE : Full SWJ Disabled (JTAG-DP + SW-DP) * * @retval When you use GPIO_REMAP_CAN2, you must put this function last of all other ConfigPinRemap Function. */ void GPIO_ConfigPinRemap(GPIO_REMAP_T remap) { uint32_t val, mask, bitOffset; uint32_t regVal; val = remap & 0x0f; mask = (remap >> 4) & 0x0f; bitOffset = (remap >> 8) & 0xff; regVal = AFIO->REMAP1; if (remap >> 8 == 0x18) { regVal &= 0xF0FFFFFF; AFIO->REMAP1 &= 0xF0FFFFFF; } else { regVal |= 0x0F000000; } mask <<= bitOffset; regVal &= (uint32_t)~mask; val <<= bitOffset; regVal |= val; AFIO->REMAP1 = regVal; } /*! * @brief Select the GPIO pin used as EINT Line * * @param portSource : select the GPIO port to be used as source for EINT line. * This parameter can be one of GPIO_PORT_SOURCE_x( x can be from A to E). * * @param pinSource : Specify the EINT line to be configured. * This parameter can be GPIO_PIN_SOURCE_x( x can be from 0 to 15). * * @retval None */ void GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSource) { uint32_t shift; if (pinSource <= GPIO_PIN_SOURCE_3) { shift = pinSource << 2; AFIO->EINTSEL1 &= (uint32_t)~(0x0f << shift); AFIO->EINTSEL1 |= portSource << shift; } else if (pinSource <= GPIO_PIN_SOURCE_7) { shift = (pinSource - GPIO_PIN_SOURCE_4) << 2; AFIO->EINTSEL2 &= (uint32_t)~(0x0f << shift); AFIO->EINTSEL2 |= portSource << shift; } else if (pinSource <= GPIO_PIN_SOURCE_11) { shift = (pinSource - GPIO_PIN_SOURCE_8) << 2; AFIO->EINTSEL3 &= (uint32_t)~(0x0f << shift); AFIO->EINTSEL3 |= portSource << shift; } else if (pinSource <= GPIO_PIN_SOURCE_15) { shift = (pinSource - GPIO_PIN_SOURCE_12) << 2; AFIO->EINTSEL4 &= (uint32_t)~(0x0f << shift); AFIO->EINTSEL4 |= portSource << shift; } } /**@} end of group GPIO_Functions */ /**@} end of group GPIO_Driver */ /**@} end of group APM32S10x_StdPeriphDriver */