318 lines
8.9 KiB
C
318 lines
8.9 KiB
C
|
/*
|
||
|
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
||
|
* Copyright 2016-2020 NXP
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||
|
*/
|
||
|
|
||
|
#include "fsl_gpio.h"
|
||
|
|
||
|
/* Component ID definition, used by tools. */
|
||
|
#ifndef FSL_COMPONENT_ID
|
||
|
#define FSL_COMPONENT_ID "platform.drivers.lpc_gpio"
|
||
|
#endif
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* Variables
|
||
|
******************************************************************************/
|
||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||
|
/*! @brief Array to map FGPIO instance number to clock name. */
|
||
|
static const clock_ip_name_t s_gpioClockName[] = GPIO_CLOCKS;
|
||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||
|
|
||
|
#if !(defined(FSL_FEATURE_GPIO_HAS_NO_RESET) && FSL_FEATURE_GPIO_HAS_NO_RESET)
|
||
|
/*! @brief Pointers to GPIO resets for each instance. */
|
||
|
static const reset_ip_name_t s_gpioResets[] = GPIO_RSTS_N;
|
||
|
#endif
|
||
|
/*******************************************************************************
|
||
|
* Prototypes
|
||
|
************ ******************************************************************/
|
||
|
/*!
|
||
|
* @brief Enable GPIO port clock.
|
||
|
*
|
||
|
* @param base GPIO peripheral base pointer.
|
||
|
* @param port GPIO port number.
|
||
|
*/
|
||
|
static void GPIO_EnablePortClock(GPIO_Type *base, uint32_t port);
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* Code
|
||
|
******************************************************************************/
|
||
|
static void GPIO_EnablePortClock(GPIO_Type *base, uint32_t port)
|
||
|
{
|
||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||
|
assert(port < ARRAY_SIZE(s_gpioClockName));
|
||
|
|
||
|
/* Upgate the GPIO clock */
|
||
|
CLOCK_EnableClock(s_gpioClockName[port]);
|
||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* brief Initializes the GPIO peripheral.
|
||
|
*
|
||
|
* This function ungates the GPIO clock.
|
||
|
*
|
||
|
* param base GPIO peripheral base pointer.
|
||
|
* param port GPIO port number.
|
||
|
*/
|
||
|
void GPIO_PortInit(GPIO_Type *base, uint32_t port)
|
||
|
{
|
||
|
GPIO_EnablePortClock(base, port);
|
||
|
|
||
|
#if !(defined(FSL_FEATURE_GPIO_HAS_NO_RESET) && FSL_FEATURE_GPIO_HAS_NO_RESET)
|
||
|
/* Reset the GPIO module */
|
||
|
RESET_PeripheralReset(s_gpioResets[port]);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* brief Initializes a GPIO pin used by the board.
|
||
|
*
|
||
|
* To initialize the GPIO, define a pin configuration, either input or output, in the user file.
|
||
|
* Then, call the GPIO_PinInit() function.
|
||
|
*
|
||
|
* This is an example to define an input pin or output pin configuration:
|
||
|
* code
|
||
|
* Define a digital input pin configuration,
|
||
|
* gpio_pin_config_t config =
|
||
|
* {
|
||
|
* kGPIO_DigitalInput,
|
||
|
* 0,
|
||
|
* }
|
||
|
* Define a digital output pin configuration,
|
||
|
* gpio_pin_config_t config =
|
||
|
* {
|
||
|
* kGPIO_DigitalOutput,
|
||
|
* 0,
|
||
|
* }
|
||
|
* endcode
|
||
|
*
|
||
|
* param base GPIO peripheral base pointer(Typically GPIO)
|
||
|
* param port GPIO port number
|
||
|
* param pin GPIO pin number
|
||
|
* param config GPIO pin configuration pointer
|
||
|
*/
|
||
|
void GPIO_PinInit(GPIO_Type *base, uint32_t port, uint32_t pin, const gpio_pin_config_t *config)
|
||
|
{
|
||
|
GPIO_EnablePortClock(base, port);
|
||
|
|
||
|
if (config->pinDirection == kGPIO_DigitalInput)
|
||
|
{
|
||
|
#if defined(FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR) && (FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR)
|
||
|
base->DIRCLR[port] = 1UL << pin;
|
||
|
#else
|
||
|
base->DIR[port] &= ~(1UL << pin);
|
||
|
#endif /*FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR*/
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Set default output value */
|
||
|
if (config->outputLogic == 0U)
|
||
|
{
|
||
|
base->CLR[port] = (1UL << pin);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
base->SET[port] = (1UL << pin);
|
||
|
}
|
||
|
/* Set pin direction */
|
||
|
#if defined(FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR) && (FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR)
|
||
|
base->DIRSET[port] = 1UL << pin;
|
||
|
#else
|
||
|
base->DIR[port] |= 1UL << pin;
|
||
|
#endif /*FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if defined(FSL_FEATURE_GPIO_HAS_INTERRUPT) && FSL_FEATURE_GPIO_HAS_INTERRUPT
|
||
|
/*!
|
||
|
* @brief Set the configuration of pin interrupt.
|
||
|
*
|
||
|
* @param base GPIO base pointer.
|
||
|
* @param port GPIO port number
|
||
|
* @param pin GPIO pin number.
|
||
|
* @param config GPIO pin interrupt configuration..
|
||
|
*/
|
||
|
void GPIO_SetPinInterruptConfig(GPIO_Type *base, uint32_t port, uint32_t pin, gpio_interrupt_config_t *config)
|
||
|
{
|
||
|
base->INTEDG[port] = (base->INTEDG[port] & ~(1UL << pin)) | ((uint32_t)config->mode << pin);
|
||
|
|
||
|
base->INTPOL[port] = (base->INTPOL[port] & ~(1UL << pin)) | ((uint32_t)config->polarity << pin);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Enables multiple pins interrupt.
|
||
|
*
|
||
|
* @param base GPIO base pointer.
|
||
|
* @param port GPIO port number.
|
||
|
* @param index GPIO interrupt number.
|
||
|
* @param mask GPIO pin number macro.
|
||
|
*/
|
||
|
void GPIO_PortEnableInterrupts(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask)
|
||
|
{
|
||
|
if ((uint32_t)kGPIO_InterruptA == index)
|
||
|
{
|
||
|
base->INTENA[port] = base->INTENA[port] | mask;
|
||
|
}
|
||
|
else if ((uint32_t)kGPIO_InterruptB == index)
|
||
|
{
|
||
|
base->INTENB[port] = base->INTENB[port] | mask;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*Should not enter here*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Disables multiple pins interrupt.
|
||
|
*
|
||
|
* @param base GPIO base pointer.
|
||
|
* @param port GPIO port number.
|
||
|
* @param index GPIO interrupt number.
|
||
|
* @param mask GPIO pin number macro.
|
||
|
*/
|
||
|
void GPIO_PortDisableInterrupts(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask)
|
||
|
{
|
||
|
if ((uint32_t)kGPIO_InterruptA == index)
|
||
|
{
|
||
|
base->INTENA[port] = base->INTENA[port] & ~mask;
|
||
|
}
|
||
|
else if ((uint32_t)kGPIO_InterruptB == index)
|
||
|
{
|
||
|
base->INTENB[port] = base->INTENB[port] & ~mask;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*Should not enter here*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Clears multiple pins interrupt flag. Status flags are cleared by
|
||
|
* writing a 1 to the corresponding bit position.
|
||
|
*
|
||
|
* @param base GPIO base pointer.
|
||
|
* @param port GPIO port number.
|
||
|
* @param index GPIO interrupt number.
|
||
|
* @param mask GPIO pin number macro.
|
||
|
*/
|
||
|
void GPIO_PortClearInterruptFlags(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask)
|
||
|
{
|
||
|
if ((uint32_t)kGPIO_InterruptA == index)
|
||
|
{
|
||
|
base->INTSTATA[port] = mask;
|
||
|
}
|
||
|
else if ((uint32_t)kGPIO_InterruptB == index)
|
||
|
{
|
||
|
base->INTSTATB[port] = mask;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*Should not enter here*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @ Read port interrupt status.
|
||
|
*
|
||
|
* @param base GPIO base pointer.
|
||
|
* @param port GPIO port number
|
||
|
* @param index GPIO interrupt number.
|
||
|
* @retval masked GPIO status value
|
||
|
*/
|
||
|
uint32_t GPIO_PortGetInterruptStatus(GPIO_Type *base, uint32_t port, uint32_t index)
|
||
|
{
|
||
|
uint32_t status = 0U;
|
||
|
|
||
|
if ((uint32_t)kGPIO_InterruptA == index)
|
||
|
{
|
||
|
status = base->INTSTATA[port];
|
||
|
}
|
||
|
else if ((uint32_t)kGPIO_InterruptB == index)
|
||
|
{
|
||
|
status = base->INTSTATB[port];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*Should not enter here*/
|
||
|
}
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Enables the specific pin interrupt.
|
||
|
*
|
||
|
* @param base GPIO base pointer.
|
||
|
* @param port GPIO port number.
|
||
|
* @param pin GPIO pin number.
|
||
|
* @param index GPIO interrupt number.
|
||
|
*/
|
||
|
void GPIO_PinEnableInterrupt(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index)
|
||
|
{
|
||
|
if ((uint32_t)kGPIO_InterruptA == index)
|
||
|
{
|
||
|
base->INTENA[port] = base->INTENA[port] | (1UL << pin);
|
||
|
}
|
||
|
else if ((uint32_t)kGPIO_InterruptB == index)
|
||
|
{
|
||
|
base->INTENB[port] = base->INTENB[port] | (1UL << pin);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*Should not enter here*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Disables the specific pin interrupt.
|
||
|
*
|
||
|
* @param base GPIO base pointer.
|
||
|
* @param port GPIO port number.
|
||
|
* @param pin GPIO pin number.
|
||
|
* @param index GPIO interrupt number.
|
||
|
*/
|
||
|
void GPIO_PinDisableInterrupt(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index)
|
||
|
{
|
||
|
if ((uint32_t)kGPIO_InterruptA == index)
|
||
|
{
|
||
|
base->INTENA[port] = base->INTENA[port] & ~(1UL << pin);
|
||
|
}
|
||
|
else if ((uint32_t)kGPIO_InterruptB == index)
|
||
|
{
|
||
|
base->INTENB[port] = base->INTENB[port] & ~(1UL << pin);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*Should not enter here*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Clears the specific pin interrupt flag. Status flags are cleared by
|
||
|
* writing a 1 to the corresponding bit position.
|
||
|
*
|
||
|
* @param base GPIO base pointer.
|
||
|
* @param port GPIO port number.
|
||
|
* @param index GPIO interrupt number.
|
||
|
* @param mask GPIO pin number macro.
|
||
|
*/
|
||
|
void GPIO_PinClearInterruptFlag(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index)
|
||
|
{
|
||
|
if ((uint32_t)kGPIO_InterruptA == index)
|
||
|
{
|
||
|
base->INTSTATA[port] = 1UL << pin;
|
||
|
}
|
||
|
else if ((uint32_t)kGPIO_InterruptB == index)
|
||
|
{
|
||
|
base->INTSTATB[port] = 1UL << pin;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*Should not enter here*/
|
||
|
}
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_GPIO_HAS_INTERRUPT */
|