rt-thread-official/bsp/acm32/acm32f0x0-nucleo/libraries/HAL_Driver/Src/HAL_GPIO.c

622 lines
18 KiB
C
Raw Normal View History

/*
******************************************************************************
* @file HAL_GPIO.c
* @version V1.0.0
* @date 2020
* @brief GPIO HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the General Purpose Input/Output (GPIO) peripheral:
* @ Initialization functions
* @ IO operation functions
******************************************************************************
*/
#include "ACM32Fxx_HAL.h"
/*********************************************************************************
* Function : HAL_GPIO_IRQHandler
* Description : GPIO interrupt Handler
* Input :
* Outpu :
* Author : Chris_Kyle Date : 2020
**********************************************************************************/
void HAL_GPIO_IRQHandler(enum_GPIOx_t fe_GPIO, uint32_t fu32_GPIO_Pin)
{
GPIO_TypeDef *GPIOx;
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
}break;
default: break;
}
if (fe_GPIO == GPIOB || fe_GPIO == GPIOD )
{
fu32_GPIO_Pin <<= 16;
}
if (GPIOx->RIS & fu32_GPIO_Pin)
{
GPIOx->IC = fu32_GPIO_Pin;
/* user can call your application process function here */
/* ...... */
}
}
/*********************************************************************************
* Function : HAL_GPIO_Init
* Description : Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init
* Input : fe_GPIO: to select the GPIO peripheral.
* Input : GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
the configuration information for the specified GPIO peripheral.
* Outpu :
* Author : Chris_Kyle Date : 2020
**********************************************************************************/
void HAL_GPIO_Init(enum_GPIOx_t fe_GPIO, GPIO_InitTypeDef *GPIO_Init)
{
uint32_t lu32_Position = 0;
uint32_t lu32_Current_Pin;
uint32_t lu32_Position_Mask;
volatile uint32_t *lu32_SEL1 = NULL; // 指向 -> 管脚复用寄存器1
volatile uint32_t *lu32_SEL2 = NULL; // 指向 -> 管脚复用寄存器2
volatile uint32_t *lu32_PollUP = NULL; // 指向 -> 上拉选择寄存器
volatile uint32_t *lu32_PollDown = NULL; // 指向 -> 下拉选择寄存器
volatile uint32_t *lu32_ODEnable = NULL; // 指向 -> 开漏使能寄存器
volatile uint32_t *lu32_ADS = NULL; // 指向 -> 数字、模拟选择寄存器
GPIO_TypeDef *GPIOx;
#if (USE_FULL_ASSERT == 1)
/* Check the parameters */
if (!IS_GPIO_ALL_INSTANCE(fe_GPIO)) return;
if (!IS_GPIO_PIN(GPIO_Init->Pin)) return;
if (!IS_GPIO_MODE(GPIO_Init->Mode)) return;
if (!IS_GPIO_PULL(GPIO_Init->Pull)) return;
#endif
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
System_Module_Enable(EN_GPIOAB);
lu32_PollUP = &(SCU->PABPUR);
lu32_PollDown = &(SCU->PABPDR);
lu32_ODEnable = &(SCU->PABODR);
lu32_ADS = &(SCU->PABADS);
if (fe_GPIO == GPIOB)
{
GPIO_Init->Pin <<= 16;
lu32_SEL1 = &(SCU->PBSEL1);
lu32_SEL2 = &(SCU->PBSEL2);
}
else
{
lu32_SEL1 = &(SCU->PASEL1);
lu32_SEL2 = &(SCU->PASEL2);
}
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
System_Module_Enable(EN_GPIOCD);
lu32_PollUP = &(SCU->PCDPUR);
lu32_PollDown = &(SCU->PCDPDR);
lu32_ODEnable = &(SCU->PCDODR);
lu32_ADS = &(SCU->PCDADS);
if (fe_GPIO == GPIOD)
{
GPIO_Init->Pin <<= 16;
lu32_SEL1 = &(SCU->PDSEL1);
}
else
{
lu32_SEL1 = &(SCU->PCSEL1);
lu32_SEL2 = &(SCU->PCSEL2);
}
}break;
default: break;
}
/* Configure Select pins */
while ((GPIO_Init->Pin) >> lu32_Position != 0)
{
/* Get current pin position */
lu32_Current_Pin = (GPIO_Init->Pin) & (1uL << lu32_Position);
if (lu32_Current_Pin)
{
switch (GPIO_Init->Mode)
{
/* GPIO IN Function */
case GPIO_MODE_INPUT:
{
GPIOx->DIR &= ~lu32_Current_Pin;
}break;
/* GPIO OUT Function */
case GPIO_MODE_OUTPUT_PP:
case GPIO_MODE_OUTPUT_OD:
{
GPIOx->DIR |= lu32_Current_Pin;
}break;
/* Alternate Function */
case GPIO_MODE_AF_PP:
case GPIO_MODE_AF_OD:
{
/* Get Position Mask */
if (lu32_Position < 16)
{ /* GOIOA、GPIOC、GPIOE */
lu32_Position_Mask = lu32_Position;
}
else
{ /* GPIOB、GPIOD、GPIOF */
lu32_Position_Mask = lu32_Position - 16;
}
/* SET GPIO Function */
if (lu32_Position_Mask < 8)
{
*lu32_SEL1 = (*lu32_SEL1 & ~(0xF << (lu32_Position_Mask * 4))) | (GPIO_Init->Alternate << (lu32_Position_Mask * 4));
}
else
{
*lu32_SEL2 = (*lu32_SEL2 & ~(0xF << ((lu32_Position_Mask - 8) * 4))) | (GPIO_Init->Alternate << ((lu32_Position_Mask - 8) * 4));
}
}break;
/* GPIO INT Function */
case GPIO_MODE_IT_RISING:
case GPIO_MODE_IT_FALLING:
case GPIO_MODE_IT_RISING_FALLING:
case GPIO_MODE_IT_HIGH_LEVEL:
case GPIO_MODE_IT_LOW_LEVEL:
{
/* Set direction Input、Enable INT */
GPIOx->DIR &= ~lu32_Current_Pin;
GPIOx->IEN |= lu32_Current_Pin;
/* Single edge */
if (GPIO_Init->Mode == GPIO_MODE_IT_RISING || GPIO_Init->Mode == GPIO_MODE_IT_FALLING)
{
/* edge trigger */
GPIOx->IS &= ~lu32_Current_Pin;
/* Single trigger */
GPIOx->IBE &= ~lu32_Current_Pin;
if (GPIO_Init->Mode == GPIO_MODE_IT_RISING)
{
GPIOx->IEV |= lu32_Current_Pin;
}
else
{
GPIOx->IEV &= ~lu32_Current_Pin;
}
}
/* Double edge */
if (GPIO_Init->Mode == GPIO_MODE_IT_RISING_FALLING)
{
/* edge trigger */
GPIOx->IS &= ~lu32_Current_Pin;
/* Double trigger */
GPIOx->IBE |= lu32_Current_Pin;
}
/* LEVEL trigger */
if (GPIO_Init->Mode == GPIO_MODE_IT_HIGH_LEVEL || GPIO_Init->Mode == GPIO_MODE_IT_LOW_LEVEL)
{
/* LEVEL trigger */
GPIOx->IS |= lu32_Current_Pin;
if (GPIO_Init->Mode == GPIO_MODE_IT_HIGH_LEVEL)
{
GPIOx->IEV |= lu32_Current_Pin;
}
else
{
GPIOx->IEV &= ~lu32_Current_Pin;
}
}
}break;
default: break;
}
/* Set Pull UP or DOWN or NO */
if (GPIO_Init->Pull == GPIO_NOPULL)
{
*lu32_PollUP &= ~lu32_Current_Pin;
*lu32_PollDown &= ~lu32_Current_Pin;
}
else if (GPIO_Init->Pull == GPIO_PULLUP)
{
*lu32_PollUP |= lu32_Current_Pin;
*lu32_PollDown &= ~lu32_Current_Pin;
}
else if (GPIO_Init->Pull == GPIO_PULLDOWN)
{
*lu32_PollUP &= ~lu32_Current_Pin;
*lu32_PollDown |= lu32_Current_Pin;
}
/* Set Open Drain Mode */
if (GPIO_Init->Mode & GPIO_MODE_OD_MASK)
{
*lu32_ODEnable |= lu32_Current_Pin;
}
else
{
*lu32_ODEnable &= ~lu32_Current_Pin;
}
/* GPIO Function */
if (GPIO_Init->Mode & GPIO_MODE_IO_MASK)
{
/* Get Position Mask */
if (lu32_Position < 16)
{ /* GOIOA、GPIOC、GPIOE */
lu32_Position_Mask = lu32_Position;
}
else
{ /* GPIOB、GPIOD、GPIOF */
lu32_Position_Mask = lu32_Position - 16;
}
/* SET GPIO Function */
if (lu32_Position_Mask < 8)
{
*lu32_SEL1 = (*lu32_SEL1 & ~(0xF << (lu32_Position_Mask * 4))) | (GPIO_FUNCTION_0 << (lu32_Position_Mask * 4));
}
else
{
*lu32_SEL2 = (*lu32_SEL2 & ~(0xF << ((lu32_Position_Mask - 8) * 4))) | (GPIO_FUNCTION_0 << ((lu32_Position_Mask - 8) * 4));
}
}
/* SET Digital or Analog */
if (GPIO_Init->Mode == GPIO_MODE_ANALOG)
{
*lu32_ADS |= lu32_Current_Pin;
}
else
{
*lu32_ADS &= ~lu32_Current_Pin;
}
}
lu32_Position++;
}
}
/*********************************************************************************
* Function : HAL_GPIO_DeInit
* Description : De-initializes the GPIOx peripheral registers to their default reset values.
* Input : fe_GPIOto select the GPIO peripheral.
* Input : fu32_Pinspecifies the port bit to be written.
This parameter can be one of GPIO_PIN_x where x can be (0..15).
* Outpu :
* Author : Chris_Kyle Date : 2020
**********************************************************************************/
void HAL_GPIO_DeInit(enum_GPIOx_t fe_GPIO, uint32_t fu32_Pin)
{
uint32_t lu32_Position = 0;
uint32_t lu32_Current_Pin;
uint32_t lu32_Position_Mask;
volatile uint32_t *lu32_SEL1 = NULL; // 指向 -> 管脚复用寄存器1
volatile uint32_t *lu32_SEL2 = NULL; // 指向 -> 管脚复用寄存器2
volatile uint32_t *lu32_PollUP = NULL; // 指向 -> 上拉选择寄存器
volatile uint32_t *lu32_PollDown = NULL; // 指向 -> 下拉选择寄存器
volatile uint32_t *lu32_ODEnable = NULL; // 指向 -> 开漏使能寄存器
volatile uint32_t *lu32_ADS = NULL; // 指向 -> 数字、模拟选择寄存器
GPIO_TypeDef *GPIOx;
#if (USE_FULL_ASSERT == 1)
/* Check the parameters */
if (!IS_GPIO_ALL_INSTANCE(fe_GPIO)) return;
if (!IS_GPIO_PIN(fu32_Pin)) return;
#endif
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
System_Module_Enable(EN_GPIOAB);
lu32_PollUP = &(SCU->PABPUR);
lu32_PollDown = &(SCU->PABPDR);
lu32_ODEnable = &(SCU->PABODR);
lu32_ADS = &(SCU->PABADS);
if (fe_GPIO == GPIOB)
{
fu32_Pin <<= 16;
lu32_SEL1 = &(SCU->PBSEL1);
lu32_SEL2 = &(SCU->PBSEL2);
}
else
{
lu32_SEL1 = &(SCU->PASEL1);
lu32_SEL2 = &(SCU->PASEL2);
}
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
System_Module_Enable(EN_GPIOCD);
lu32_PollUP = &(SCU->PCDPUR);
lu32_PollDown = &(SCU->PCDPDR);
lu32_ODEnable = &(SCU->PCDODR);
lu32_ADS = &(SCU->PCDADS);
if (fe_GPIO == GPIOD)
{
fu32_Pin <<= 16;
lu32_SEL1 = &(SCU->PDSEL1);
}
else
{
lu32_SEL1 = &(SCU->PCSEL1);
lu32_SEL2 = &(SCU->PCSEL2);
}
}break;
default: break;
}
/* Configure Select pins */
while (fu32_Pin >> lu32_Position != 0)
{
/* Get current pin position */
lu32_Current_Pin = fu32_Pin & (1uL << lu32_Position);
if (lu32_Current_Pin)
{
/* GPIO IN Function */
GPIOx->DIR &= ~lu32_Current_Pin;
GPIOx->CLR |= lu32_Current_Pin;
/* Disable Enable INT */
GPIOx->IEN &= ~lu32_Current_Pin;
/* Clear trigger config */
GPIOx->IS &= ~lu32_Current_Pin;
GPIOx->IBE &= ~lu32_Current_Pin;
GPIOx->IEV &= ~lu32_Current_Pin;
/* Get Position Mask */
if (lu32_Position < 16)
{ /* GOIOA、GPIOC、GPIOE */
lu32_Position_Mask = lu32_Position;
}
else
{ /* GPIOB、GPIOD、GPIOF */
lu32_Position_Mask = lu32_Position - 16;
}
/* SET GPIO Function */
if (lu32_Position_Mask < 8)
{
*lu32_SEL1 &= ~(0xF << (lu32_Position_Mask * 4));
}
else
{
*lu32_SEL2 &= ~(0xF << ((lu32_Position_Mask - 8) * 4));
}
/* NO Pull */
*lu32_PollUP &= ~lu32_Current_Pin;
*lu32_PollDown &= ~lu32_Current_Pin;
/* Not Open Drain */
*lu32_ODEnable &= ~lu32_Current_Pin;
/* Analog Mode */
*lu32_ADS |= lu32_Current_Pin;
}
lu32_Position++;
}
}
/*********************************************************************************
* Function : HAL_GPIO_AnalogEnable
* Description : Quickly Configure to analog function
* Input : fe_GPIOto select the GPIO peripheral.
* Input : fu32_Pinspecifies the port bit to be written.
This parameter can be one of GPIO_PIN_x where x can be (0..15).
* Outpu :
* Author : Chris_Kyle Date : 2020
**********************************************************************************/
void HAL_GPIO_AnalogEnable(enum_GPIOx_t fe_GPIO, uint32_t fu32_Pin)
{
uint32_t lu32_Position = 0;
uint32_t lu32_Current_Pin;
volatile uint32_t *lp32_ADS = NULL; // 指向 -> 数字、模拟选择寄存器
#if (USE_FULL_ASSERT == 1)
/* Check the parameters */
if (!IS_GPIO_ALL_INSTANCE(fe_GPIO)) return;
if (!IS_GPIO_PIN(fu32_Pin)) return;
#endif
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
System_Module_Enable(EN_GPIOAB);
lp32_ADS = &(SCU->PABADS);
if (fe_GPIO == GPIOB)
{
fu32_Pin <<= 16;
}
}break;
case GPIOC:
case GPIOD:
{
System_Module_Enable(EN_GPIOCD);
lp32_ADS = &(SCU->PCDADS);
if (fe_GPIO == GPIOD)
{
fu32_Pin <<= 16;
}
}break;
default: break;
}
/* Configure Select pins */
while ((fu32_Pin) >> lu32_Position != 0)
{
/* Get current pin position */
lu32_Current_Pin = (fu32_Pin) & (1uL << lu32_Position);
if (lu32_Current_Pin)
{
*lp32_ADS |= lu32_Current_Pin;
}
lu32_Position++;
}
}
/*********************************************************************************
* Function : HAL_GPIO_WritePin
* Description : Set or clear the selected data port bit.
* Input :
* Outpu :
* Author : Chris_Kyle Date : 2020
**********************************************************************************/
void HAL_GPIO_WritePin(enum_GPIOx_t fe_GPIO, uint32_t fu32_GPIO_Pin, enum_PinState_t fe_PinState)
{
GPIO_TypeDef *GPIOx;
#if (USE_FULL_ASSERT == 1)
/* Check the parameters */
if (!IS_GPIO_ALL_INSTANCE(fe_GPIO)) return;
if (!IS_GPIO_PIN(fu32_GPIO_Pin)) return;
if (!IS_GPIO_PIN_ACTION(fe_PinState)) return;
#endif
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
}break;
default: break;
}
if (fe_GPIO == GPIOB || fe_GPIO == GPIOD )
{
fu32_GPIO_Pin <<= 16;
}
if (GPIO_PIN_SET == fe_PinState)
{
GPIOx->ODATA |= fu32_GPIO_Pin;
}
else
{
GPIOx->ODATA &= ~fu32_GPIO_Pin;
}
}
/*********************************************************************************
* Function : HAL_GPIO_ReadPin
* Description : Read the specified input port pin.
* Input :
* Outpu :
* Author : Chris_Kyle Date : 2020
**********************************************************************************/
enum_PinState_t HAL_GPIO_ReadPin(enum_GPIOx_t fe_GPIO, uint32_t fu32_GPIO_Pin)
{
GPIO_TypeDef *GPIOx;
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
}break;
default: break;
}
if (fe_GPIO == GPIOB || fe_GPIO == GPIOD )
{
fu32_GPIO_Pin <<= 16;
}
if (GPIOx->IDATA & fu32_GPIO_Pin)
{
return GPIO_PIN_SET;
}
else
{
return GPIO_PIN_CLEAR;
}
}