5#include "hpm_interrupt.h"
6#include "hpm_ioc_regs.h"
16HPMGPIO* HPMGPIO::map[HPMGPIO::PORT_COUNT][HPMGPIO::PIN_COUNT] = {};
17GPIO_Type* HPMGPIO::port_controller_map[HPMGPIO::PORT_COUNT] = {};
18HPMGPIO::PortIrqRouteState HPMGPIO::port_irq_route_map[HPMGPIO::PORT_COUNT] = {};
23std::atomic_flag g_hpm_gpio_irq_route_lock = ATOMIC_FLAG_INIT;
25bool HPM_GPIO_IsFastController(GPIO_Type* gpio)
28 return gpio == HPM_FGPIO;
35class HPMGPIOIrqRouteGuard
38 HPMGPIOIrqRouteGuard()
39 : irq_state_(disable_global_irq(CSR_MSTATUS_MIE_MASK) & CSR_MSTATUS_MIE_MASK)
41 while (g_hpm_gpio_irq_route_lock.test_and_set(std::memory_order_acquire))
46 ~HPMGPIOIrqRouteGuard()
48 g_hpm_gpio_irq_route_lock.clear(std::memory_order_release);
49 restore_global_irq(irq_state_);
52 HPMGPIOIrqRouteGuard(
const HPMGPIOIrqRouteGuard&) =
delete;
53 HPMGPIOIrqRouteGuard& operator=(
const HPMGPIOIrqRouteGuard&) =
delete;
70static inline void HPM_GPIO_ConfigMuxToGPIO(GPIO_Type* gpio, uint32_t port,
72 bool enable_loopback =
true)
74 uint32_t func_ctl = IOC_PAD_FUNC_CTL_ALT_SELECT_SET(0);
77 func_ctl |= IOC_PAD_FUNC_CTL_LOOP_BACK_MASK;
79 HPM_IOC->PAD[pad_index].FUNC_CTL = func_ctl;
82#if defined(GPIO_DI_GPIOY) && defined(HPM_PIOC)
83 if (port == GPIO_DI_GPIOY && (gpio == HPM_GPIO0 || HPM_GPIO_IsFastController(gpio)))
85 HPM_PIOC->PAD[pad_index].FUNC_CTL = IOC_PAD_FUNC_CTL_ALT_SELECT_SET(3);
103 pad_index_(pad_index == INVALID_PAD_INDEX ? ResolvePadIndex(gpio, port, pin)
106 if (port_ < PORT_COUNT && pin_ < PIN_COUNT && !HPM_GPIO_IsFastController(gpio_))
108 map[port_][pin_] =
this;
109 if (port_controller_map[port_] ==
nullptr)
111 port_controller_map[port_] = gpio_;
131 if (irq_ == INVALID_IRQ || port_ >= PORT_COUNT || pin_ >= PIN_COUNT)
135 if (HPM_GPIO_IsFastController(gpio_))
140 HPMGPIOIrqRouteGuard guard;
141 if (interrupt_enabled_)
146 PortIrqRouteState& route = port_irq_route_map[port_];
147 const bool needs_port_irq_enable = (route.enabled_pin_count == 0u);
148 if (!needs_port_irq_enable && (route.controller != gpio_ || route.irq != irq_))
153 gpio_enable_pin_interrupt(gpio_, port_, pin_);
155 if (needs_port_irq_enable)
157 route.controller = gpio_;
159 intc_m_enable_irq_with_priority(irq_, 1);
162 ++route.enabled_pin_count;
163 interrupt_enabled_ =
true;
180 if (irq_ == INVALID_IRQ || port_ >= PORT_COUNT || pin_ >= PIN_COUNT)
184 if (HPM_GPIO_IsFastController(gpio_))
189 HPMGPIOIrqRouteGuard guard;
190 if (!interrupt_enabled_)
195 gpio_disable_pin_interrupt(gpio_, port_, pin_);
197 PortIrqRouteState& route = port_irq_route_map[port_];
198 if (route.enabled_pin_count == 0u)
201 interrupt_enabled_ =
false;
205 if (route.controller != gpio_ || route.irq != irq_)
207 interrupt_enabled_ =
false;
211 --route.enabled_pin_count;
212 if (route.enabled_pin_count == 0u)
214 const uint32_t route_irq = route.irq;
216 intc_m_disable_irq(route_irq);
219 interrupt_enabled_ =
false;
236 if (port_ >= PORT_COUNT || pin_ >= PIN_COUNT)
251 const bool is_interrupt_direction =
255 if (is_interrupt_direction && HPM_GPIO_IsFastController(gpio_))
261#if !defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) || (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT != 1)
266 if (pad_index_ != INVALID_PAD_INDEX)
270 HPM_GPIO_ConfigMuxToGPIO(gpio_, port_, pad_index_);
276 gpio_set_pin_input(gpio_, port_, pin_);
280 gpio_set_pin_output(gpio_, port_, pin_);
283 gpio_set_pin_input(gpio_, port_, pin_);
284 gpio_config_pin_interrupt(gpio_, port_, pin_, gpio_interrupt_trigger_edge_falling);
287 gpio_set_pin_input(gpio_, port_, pin_);
288 gpio_config_pin_interrupt(gpio_, port_, pin_, gpio_interrupt_trigger_edge_rising);
291#if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
292 gpio_set_pin_input(gpio_, port_, pin_);
293 gpio_config_pin_interrupt(gpio_, port_, pin_, gpio_interrupt_trigger_edge_both);
302 if (pad_index_ != INVALID_PAD_INDEX)
304 uint32_t pad_ctl = HPM_IOC->PAD[pad_index_].PAD_CTL;
308 ~(IOC_PAD_PAD_CTL_PE_MASK | IOC_PAD_PAD_CTL_PS_MASK | IOC_PAD_PAD_CTL_OD_MASK);
315 pad_ctl |= IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1);
318 pad_ctl |= IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(0);
324 pad_ctl |= IOC_PAD_PAD_CTL_OD_SET(1);
327 HPM_IOC->PAD[pad_index_].PAD_CTL = pad_ctl;
345 if (port_ >= PORT_COUNT || pin_ >= PIN_COUNT)
350 if (pad_index_ == INVALID_PAD_INDEX)
355 if (interrupt_enabled_)
365 gpio_disable_pin_interrupt(gpio_, port_, pin_);
368 gpio_set_pin_input(gpio_, port_, pin_);
370 HPM_IOC->PAD[pad_index_].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK;
372 uint32_t pad_ctl = HPM_IOC->PAD[pad_index_].PAD_CTL;
373 pad_ctl &= ~(IOC_PAD_PAD_CTL_PE_MASK | IOC_PAD_PAD_CTL_OD_MASK);
374 HPM_IOC->PAD[pad_index_].PAD_CTL = pad_ctl;
395 if (port >= PORT_COUNT)
400 GPIO_Type* controller = port_controller_map[port];
401 if (controller ==
nullptr)
406 const uint32_t flags = gpio_get_port_interrupt_flags(controller, port);
412 for (uint8_t pin = 0; pin < PIN_COUNT; ++pin)
414 if ((flags & (1u << pin)) == 0u)
419 gpio_clear_pin_interrupt_flag(controller, port, pin);
420 if (
auto* gpio = map[port][pin]; gpio !=
nullptr && gpio->interrupt_enabled_)
422 gpio->callback_.Run(
true);
430uint16_t HPMGPIO::ResolvePadIndex(GPIO_Type* gpio, uint32_t port, uint8_t pin)
432 if (gpio != HPM_GPIO0 && !HPM_GPIO_IsFastController(gpio))
434 return INVALID_PAD_INDEX;
439#if defined(GPIO_DI_GPIOA) && defined(IOC_PAD_PA00)
441 return static_cast<uint16_t
>(IOC_PAD_PA00 + pin);
443#if defined(GPIO_DI_GPIOB) && defined(IOC_PAD_PB00)
445 return static_cast<uint16_t
>(IOC_PAD_PB00 + pin);
447#if defined(GPIO_DI_GPIOX) && defined(IOC_PAD_PX00)
449 return pin < 8u ? static_cast<uint16_t>(IOC_PAD_PX00 + pin) : INVALID_PAD_INDEX;
451#if defined(GPIO_DI_GPIOY) && defined(IOC_PAD_PY00)
453 return pin < 8u ? static_cast<uint16_t>(IOC_PAD_PY00 + pin) : INVALID_PAD_INDEX;
456 return INVALID_PAD_INDEX;
464extern "C" void libxr_hpm_gpio_check_interrupt(uint32_t port)
474#define LIBXR_HPM_GPIO_PORT_ISR(irq, port) \
475 SDK_DECLARE_EXT_ISR_M(irq, libxr_hpm_gpio_##irq) \
476 void libxr_hpm_gpio_##irq(void) { HPMGPIO::CheckInterrupt(port); }
478#if defined(IRQn_GPIO0_A) && defined(GPIO_DI_GPIOA)
479LIBXR_HPM_GPIO_PORT_ISR(IRQn_GPIO0_A, GPIO_DI_GPIOA)
481#if defined(IRQn_GPIO0_B) && defined(GPIO_DI_GPIOB)
482LIBXR_HPM_GPIO_PORT_ISR(IRQn_GPIO0_B, GPIO_DI_GPIOB)
484#if defined(IRQn_GPIO0_C) && defined(GPIO_DI_GPIOC)
485LIBXR_HPM_GPIO_PORT_ISR(IRQn_GPIO0_C, GPIO_DI_GPIOC)
487#if defined(IRQn_GPIO0_D) && defined(GPIO_DI_GPIOD)
488LIBXR_HPM_GPIO_PORT_ISR(IRQn_GPIO0_D, GPIO_DI_GPIOD)
490#if defined(IRQn_GPIO0_E) && defined(GPIO_DI_GPIOE)
491LIBXR_HPM_GPIO_PORT_ISR(IRQn_GPIO0_E, GPIO_DI_GPIOE)
493#if defined(IRQn_GPIO0_F) && defined(GPIO_DI_GPIOF)
494LIBXR_HPM_GPIO_PORT_ISR(IRQn_GPIO0_F, GPIO_DI_GPIOF)
496#if defined(IRQn_GPIO0_X) && defined(GPIO_DI_GPIOX)
497LIBXR_HPM_GPIO_PORT_ISR(IRQn_GPIO0_X, GPIO_DI_GPIOX)
499#if defined(IRQn_GPIO0_Y) && defined(GPIO_DI_GPIOY)
500LIBXR_HPM_GPIO_PORT_ISR(IRQn_GPIO0_Y, GPIO_DI_GPIOY)
502#if defined(IRQn_GPIO0_Z) && defined(GPIO_DI_GPIOZ)
503LIBXR_HPM_GPIO_PORT_ISR(IRQn_GPIO0_Z, GPIO_DI_GPIOZ)
@ OUTPUT_PUSH_PULL
推挽输出模式 / Push-pull output mode.
@ RISING_INTERRUPT
上升沿中断模式 / Rising edge interrupt mode.
@ FALL_RISING_INTERRUPT
双沿触发中断模式 / Both edge interrupt mode.
@ OUTPUT_OPEN_DRAIN
开漏输出模式 / Open-drain output mode.
@ INPUT
输入模式 / Input mode.
@ FALL_INTERRUPT
下降沿中断模式 / Falling edge interrupt mode.
@ NONE
无上拉或下拉 / No pull-up or pull-down.
@ DOWN
下拉模式 / Pull-down mode.
HPM 平台 GPIO 驱动实现 / GPIO driver implementation for HPM platform.
ErrorCode EnableInterrupt() override
使能当前引脚中断 / Enable GPIO interrupt for current pin.
ErrorCode SetAnalogHighImpedance()
将当前 PAD 配置为模拟高阻 / Configure current pad to analog high-impedance.
ErrorCode SetConfig(Configuration config) override
配置当前引脚模式 / Configure GPIO mode for current pin.
static void CheckInterrupt(uint32_t port)
分发某一端口的 GPIO 中断回调 / Dispatch GPIO interrupt callbacks for one port.
ErrorCode DisableInterrupt() override
失能当前引脚中断 / Disable GPIO interrupt for current pin.
HPMGPIO(GPIO_Type *gpio, uint32_t port, uint8_t pin, uint32_t irq=INVALID_IRQ, uint16_t pad_index=INVALID_PAD_INDEX)
构造 HPM GPIO 对象 / Construct an HPM GPIO object.
HPM GPIO 驱动适配头文件 / Adapter header for the HPM GPIO driver.
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ STATE_ERR
状态错误 / State error
@ NOT_SUPPORT
不支持 / Not supported
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
存储 GPIO 配置参数的结构体 / Structure storing GPIO configuration parameters.
Pull pull
GPIO 上拉/下拉配置 / GPIO pull-up/pull-down configuration.
Direction direction
GPIO 引脚方向 / GPIO pin direction.