blob: 2cec9828283591b7b3ba074699e1946bf9de410f [file] [log] [blame]
/*
* Copyright 2018 - 2019 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_device_registers.h"
#include "fsl_gpio.h"
#include "gpio.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief The pin config struct of gpio adapter. */
typedef struct _hal_gpio_pin
{
uint16_t port : 3U;
uint16_t pin : 5U;
uint16_t direction : 1U;
uint16_t trigger : 3U;
uint16_t reserved : 4U;
} hal_gpio_pin_t;
typedef struct _hal_gpio_state
{
struct _hal_gpio_state *next;
hal_gpio_callback_t callback;
void *callbackParam;
hal_gpio_pin_t pin;
} hal_gpio_state_t;
/*******************************************************************************
* Prototypes
******************************************************************************/
static void HAL_GpioInterruptHandle(uint8_t port);
/*******************************************************************************
* Variables
******************************************************************************/
static hal_gpio_state_t *s_GpioHead;
/*******************************************************************************
* Code
******************************************************************************/
static void HAL_GpioInterruptHandle(uint8_t port)
{
hal_gpio_state_t *head = s_GpioHead;
GPIO_Type *gpioList[] = GPIO_BASE_PTRS;
uint32_t intFlag;
/* Get and clear gpio pin interrupt Flag */
intFlag = GPIO_PortGetInterruptFlags(gpioList[port]);
GPIO_PortClearInterruptFlags(gpioList[port], intFlag);
while (NULL != head)
{
/* Check which triger is ON! */
if (kHAL_GpioInterruptDisable != (hal_gpio_interrupt_trigger_t)head->pin.trigger)
{
if ((port == head->pin.port) && (0U != (intFlag & (1U << head->pin.pin))))
{
if ((NULL != head->callback))
{
head->callback(head->callbackParam);
}
}
}
head = head->next;
}
}
/* IRQHandler for GPIO1 */
#if defined(GPIO1) && (FSL_FEATURE_SOC_IGPIO_COUNT > 0U)
void GPIO1_Combined_0_15_IRQHandler(void);
void GPIO1_Combined_0_15_IRQHandler(void)
{
HAL_GpioInterruptHandle(1);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void GPIO1_Combined_16_31_IRQHandler(void);
void GPIO1_Combined_16_31_IRQHandler(void)
{
HAL_GpioInterruptHandle(1);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
#endif
/* IRQHandler for GPIO2 */
#if defined(GPIO2) && (FSL_FEATURE_SOC_IGPIO_COUNT > 0U)
void GPIO2_Combined_0_15_IRQHandler(void);
void GPIO2_Combined_0_15_IRQHandler(void)
{
HAL_GpioInterruptHandle(2);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void GPIO2_Combined_16_31_IRQHandler(void);
void GPIO2_Combined_16_31_IRQHandler(void)
{
HAL_GpioInterruptHandle(2);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
#endif
/* IRQHandler for GPIO3 */
#if defined(GPIO3) && (FSL_FEATURE_SOC_IGPIO_COUNT > 0U)
void GPIO3_Combined_0_15_IRQHandler(void);
void GPIO3_Combined_0_15_IRQHandler(void)
{
HAL_GpioInterruptHandle(3);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void GPIO3_Combined_16_31_IRQHandler(void);
void GPIO3_Combined_16_31_IRQHandler(void)
{
HAL_GpioInterruptHandle(3);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
#endif
/* IRQHandler for GPIO4 */
#if defined(GPIO4) && (FSL_FEATURE_SOC_IGPIO_COUNT > 0U)
void GPIO4_Combined_0_15_IRQHandler(void);
void GPIO4_Combined_0_15_IRQHandler(void)
{
HAL_GpioInterruptHandle(4);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void GPIO4_Combined_16_31_IRQHandler(void);
void GPIO4_Combined_16_31_IRQHandler(void)
{
HAL_GpioInterruptHandle(4);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
#endif
/* IRQHandler for GPIO5 */
#if defined(GPIO5) && (FSL_FEATURE_SOC_IGPIO_COUNT > 0U)
void GPIO5_Combined_0_15_IRQHandler(void);
void GPIO5_Combined_0_15_IRQHandler(void)
{
HAL_GpioInterruptHandle(5);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void GPIO5_Combined_16_31_IRQHandler(void);
void GPIO5_Combined_16_31_IRQHandler(void)
{
HAL_GpioInterruptHandle(5);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
#endif
/* IRQHandler for GPIO6 GPIO7 GPIO8 GPIO9 */
#if defined(GPIO6) && defined(GPIO7) && defined(GPIO8) && defined(GPIO9) && (FSL_FEATURE_SOC_IGPIO_COUNT > 8U)
void GPIO6_7_8_9_IRQHandler(void);
void GPIO6_7_8_9_IRQHandler(void)
{
HAL_GpioInterruptHandle(6);
HAL_GpioInterruptHandle(7);
HAL_GpioInterruptHandle(8);
HAL_GpioInterruptHandle(9);
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
#endif
static hal_gpio_status_t HAL_GpioConflictSearch(hal_gpio_state_t *head, uint8_t port, uint8_t pin)
{
while (head)
{
if ((head->pin.port == port) && (head->pin.pin == pin))
{
return kStatus_HAL_GpioPinConflict;
}
head = head->next;
}
return kStatus_HAL_GpioSuccess;
}
static hal_gpio_status_t HAL_GpioAddItem(hal_gpio_state_t **head, hal_gpio_state_t *node)
{
hal_gpio_state_t *p = *head;
uint32_t regPrimask;
regPrimask = DisableGlobalIRQ();
if (NULL == p)
{
*head = node;
}
else
{
while (p->next)
{
if (p == node)
{
EnableGlobalIRQ(regPrimask);
return kStatus_HAL_GpioPinConflict;
}
p = p->next;
}
p->next = node;
}
node->next = NULL;
EnableGlobalIRQ(regPrimask);
return kStatus_HAL_GpioSuccess;
}
static hal_gpio_status_t HAL_GpioRemoveItem(hal_gpio_state_t **head, hal_gpio_state_t *node)
{
hal_gpio_state_t *p = *head;
hal_gpio_state_t *q = NULL;
uint32_t regPrimask;
regPrimask = DisableGlobalIRQ();
while (p)
{
if (p == node)
{
if (NULL == q)
{
*head = p->next;
}
else
{
q->next = p->next;
}
break;
}
else
{
q = p;
p = p->next;
}
}
EnableGlobalIRQ(regPrimask);
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioInit(hal_gpio_handle_t gpioHandle, hal_gpio_pin_config_t *pinConfig)
{
hal_gpio_state_t *gpioState;
GPIO_Type *gpioList[] = GPIO_BASE_PTRS;
hal_gpio_status_t status = kStatus_HAL_GpioSuccess;
gpio_pin_config_t gpioPinconfig = {
kGPIO_DigitalInput,
0,
kGPIO_NoIntmode,
};
assert(gpioHandle);
assert(pinConfig);
if (HAL_GPIO_HANDLE_SIZE < sizeof(hal_gpio_state_t))
{
return kStatus_HAL_GpioError;
}
gpioState = (hal_gpio_state_t *)gpioHandle;
/* Check if the port is vaild */
if (NULL == gpioList[pinConfig->port])
{
return kStatus_HAL_GpioError;
}
if ((NULL != s_GpioHead) &&
(kStatus_HAL_GpioSuccess != HAL_GpioConflictSearch(s_GpioHead, pinConfig->port, pinConfig->pin)))
{
return kStatus_HAL_GpioPinConflict;
}
status = HAL_GpioAddItem(&s_GpioHead, gpioState);
if (kStatus_HAL_GpioSuccess != status)
{
return status;
}
gpioState->pin.pin = pinConfig->pin;
gpioState->pin.port = pinConfig->port;
gpioState->pin.direction = (uint16_t)pinConfig->direction;
gpioState->pin.trigger = (uint16_t)kHAL_GpioInterruptDisable;
if (kHAL_GpioDirectionOut == (hal_gpio_direction_t)pinConfig->direction)
{
gpioPinconfig.direction = kGPIO_DigitalOutput;
}
else
{
gpioPinconfig.direction = kGPIO_DigitalInput;
}
gpioPinconfig.outputLogic = pinConfig->level;
GPIO_PinInit(gpioList[gpioState->pin.port], gpioState->pin.pin, &gpioPinconfig);
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioDeinit(hal_gpio_handle_t gpioHandle)
{
hal_gpio_state_t *gpioState;
GPIO_Type *gpioList[] = GPIO_BASE_PTRS;
assert(gpioHandle);
gpioState = (hal_gpio_state_t *)gpioHandle;
if ((uint16_t)kHAL_GpioDirectionIn == gpioState->pin.direction)
{
GPIO_PortDisableInterrupts(gpioList[gpioState->pin.port], (uint32_t)(1U << gpioState->pin.pin));
}
HAL_GpioRemoveItem(&s_GpioHead, gpioState);
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioGetInput(hal_gpio_handle_t gpioHandle, uint8_t *pinState)
{
hal_gpio_state_t *gpioStateHandle;
GPIO_Type *gpioList[] = GPIO_BASE_PTRS;
assert(gpioHandle);
gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
*pinState = ((GPIO_PinRead(gpioList[gpioStateHandle->pin.port], gpioStateHandle->pin.pin)) ? 1 : 0);
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioSetOutput(hal_gpio_handle_t gpioHandle, uint8_t pinState)
{
hal_gpio_state_t *gpioStateHandle;
GPIO_Type *gpioList[] = GPIO_BASE_PTRS;
assert(gpioHandle);
gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
GPIO_PinWrite(gpioList[gpioStateHandle->pin.port], gpioStateHandle->pin.pin, (pinState) ? 1 : 0);
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioInstallCallback(hal_gpio_handle_t gpioHandle,
hal_gpio_callback_t callback,
void *callbackParam)
{
hal_gpio_state_t *gpioStateHandle;
assert(gpioHandle);
gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
gpioStateHandle->callbackParam = callbackParam;
gpioStateHandle->callback = callback;
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioGetTriggerMode(hal_gpio_handle_t gpioHandle, hal_gpio_interrupt_trigger_t *gpioTrigger)
{
hal_gpio_state_t *gpioStateHandle;
assert(gpioHandle);
gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
if (kHAL_GpioDirectionOut == (hal_gpio_direction_t)gpioStateHandle->pin.direction)
{
return kStatus_HAL_GpioError;
}
*gpioTrigger = (hal_gpio_interrupt_trigger_t)gpioStateHandle->pin.trigger;
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioSetTriggerMode(hal_gpio_handle_t gpioHandle, hal_gpio_interrupt_trigger_t gpioTrigger)
{
hal_gpio_state_t *gpioStateHandle;
GPIO_Type *gpioList[] = GPIO_BASE_PTRS;
uint32_t regPrimask;
IRQn_Type gpioLowIRQsList[] = GPIO_COMBINED_LOW_IRQS;
IRQn_Type gpioHighIRQsList[] = GPIO_COMBINED_HIGH_IRQS;
gpio_interrupt_mode_t triggerType;
assert(gpioHandle);
gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
if (kHAL_GpioDirectionOut == (hal_gpio_direction_t)gpioStateHandle->pin.direction)
{
return kStatus_HAL_GpioError;
}
switch (gpioTrigger)
{
case kHAL_GpioInterruptLogicZero:
triggerType = kGPIO_IntLowLevel;
break;
case kHAL_GpioInterruptLogicOne:
triggerType = kGPIO_IntHighLevel;
break;
case kHAL_GpioInterruptRisingEdge:
triggerType = kGPIO_IntRisingEdge;
break;
case kHAL_GpioInterruptFallingEdge:
triggerType = kGPIO_IntFallingEdge;
break;
case kHAL_GpioInterruptEitherEdge:
triggerType = kGPIO_IntRisingOrFallingEdge;
break;
default:
triggerType = kGPIO_NoIntmode;
break;
}
gpioStateHandle->pin.trigger = (uint16_t)gpioTrigger;
/* Disbale Global Interrupt */
regPrimask = DisableGlobalIRQ();
/* initialize gpio interrupt */
GPIO_PinSetInterruptConfig(gpioList[gpioStateHandle->pin.port], gpioStateHandle->pin.pin, triggerType);
/* Enable IRQ */
if (triggerType != kGPIO_NoIntmode)
{
GPIO_PortEnableInterrupts(gpioList[gpioStateHandle->pin.port], (1U << gpioStateHandle->pin.pin));
if (gpioStateHandle->pin.pin <= 15)
{
NVIC_SetPriority(gpioLowIRQsList[gpioStateHandle->pin.port], HAL_GPIO_ISR_PRIORITY);
(void)EnableIRQ(gpioLowIRQsList[gpioStateHandle->pin.port]);
}
else
{
NVIC_SetPriority(gpioHighIRQsList[gpioStateHandle->pin.port], HAL_GPIO_ISR_PRIORITY);
(void)EnableIRQ(gpioHighIRQsList[gpioStateHandle->pin.port]);
}
}
else
{
GPIO_PortDisableInterrupts(gpioList[gpioStateHandle->pin.port], (uint32_t)(1 << gpioStateHandle->pin.pin));
}
/* Enable Global Interrupt */
EnableGlobalIRQ(regPrimask);
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioWakeUpSetting(hal_gpio_handle_t gpioHandle, uint8_t enable)
{
hal_gpio_state_t *gpioStateHandle;
assert(gpioHandle);
gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
if (kHAL_GpioDirectionOut == (hal_gpio_direction_t)gpioStateHandle->pin.direction)
{
return kStatus_HAL_GpioError;
}
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioEnterLowpower(hal_gpio_handle_t gpioHandle)
{
assert(gpioHandle);
return kStatus_HAL_GpioSuccess;
}
hal_gpio_status_t HAL_GpioExitLowpower(hal_gpio_handle_t gpioHandle)
{
assert(gpioHandle);
return kStatus_HAL_GpioSuccess;
}