502 lines
13 KiB
C
502 lines
13 KiB
C
/*
|
|
* Copyright 2018 - 2022 NXP
|
|
* All rights reserved.
|
|
*
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "fsl_device_registers.h"
|
|
#include "fsl_gpio.h"
|
|
#include "fsl_adapter_gpio.h"
|
|
|
|
/* Component ID definition, used by tools. */
|
|
#ifndef FSL_COMPONENT_ID
|
|
#define FSL_COMPONENT_ID "component.igpio_adapter"
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
/*! @brief The pin config struct of gpio adapter. */
|
|
typedef struct _hal_gpio_pin
|
|
{
|
|
uint16_t port : 4U;
|
|
uint16_t pin : 5U;
|
|
uint16_t direction : 1U;
|
|
uint16_t trigger : 3U;
|
|
uint16_t reserved : 3U;
|
|
} 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 gpio_port);
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
static hal_gpio_state_t *s_GpioHead;
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
|
|
static void HAL_GpioInterruptHandle(uint8_t gpio_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[gpio_port]);
|
|
GPIO_PortClearInterruptFlags(gpioList[gpio_port], intFlag);
|
|
|
|
while (NULL != head)
|
|
{
|
|
/* Check which triger is ON! */
|
|
if (kHAL_GpioInterruptDisable != (hal_gpio_interrupt_trigger_t)head->pin.trigger)
|
|
{
|
|
if ((gpio_port == head->pin.port) && (0U != (intFlag & ((uint32_t)1 << 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);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
void GPIO1_Combined_16_31_IRQHandler(void);
|
|
void GPIO1_Combined_16_31_IRQHandler(void)
|
|
{
|
|
HAL_GpioInterruptHandle(1);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
#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);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
void GPIO2_Combined_16_31_IRQHandler(void);
|
|
void GPIO2_Combined_16_31_IRQHandler(void)
|
|
{
|
|
HAL_GpioInterruptHandle(2);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
#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);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
void GPIO3_Combined_16_31_IRQHandler(void);
|
|
void GPIO3_Combined_16_31_IRQHandler(void)
|
|
{
|
|
HAL_GpioInterruptHandle(3);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
#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);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
void GPIO4_Combined_16_31_IRQHandler(void);
|
|
void GPIO4_Combined_16_31_IRQHandler(void)
|
|
{
|
|
HAL_GpioInterruptHandle(4);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
#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);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
void GPIO5_Combined_16_31_IRQHandler(void);
|
|
void GPIO5_Combined_16_31_IRQHandler(void)
|
|
{
|
|
HAL_GpioInterruptHandle(5);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
#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);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
#endif
|
|
#if defined(GPIO13) && (FSL_FEATURE_SOC_IGPIO_COUNT > 13U)
|
|
void GPIO13_Combined_0_31_IRQHandler(void);
|
|
void GPIO13_Combined_0_31_IRQHandler(void)
|
|
{
|
|
HAL_GpioInterruptHandle(13);
|
|
|
|
SDK_ISR_EXIT_BARRIER;
|
|
}
|
|
#endif
|
|
static hal_gpio_status_t HAL_GpioConflictSearch(hal_gpio_state_t *head, uint8_t gpio_port, uint8_t pin)
|
|
{
|
|
while (NULL != head)
|
|
{
|
|
if ((head->pin.port == gpio_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 (NULL != 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 (NULL != 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;
|
|
}
|
|
|
|
void HAL_GpioPreInit(void)
|
|
{
|
|
s_GpioHead = NULL;
|
|
}
|
|
|
|
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);
|
|
assert(HAL_GPIO_HANDLE_SIZE >= sizeof(hal_gpio_state_t));
|
|
|
|
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;
|
|
gpioPinconfig.outputLogic = pinConfig->level;
|
|
}
|
|
else
|
|
{
|
|
gpioPinconfig.direction = kGPIO_DigitalInput;
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
(void)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 = ((0U != GPIO_PinRead(gpioList[gpioStateHandle->pin.port], gpioStateHandle->pin.pin)) ? 1U : 0U);
|
|
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, (0U != pinState) ? 1U : 0U);
|
|
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], ((uint32_t)1 << gpioStateHandle->pin.pin));
|
|
if (gpioStateHandle->pin.pin <= 15U)
|
|
{
|
|
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;
|
|
}
|