libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
LibXR::HPMGPIO Class Referencefinal

HPM 平台 GPIO 驱动实现 / GPIO driver implementation for HPM platform. More...

#include <hpm_gpio.hpp>

Inheritance diagram for LibXR::HPMGPIO:
[legend]
Collaboration diagram for LibXR::HPMGPIO:
[legend]

Public Member Functions

 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.
 
bool Read () override
 读取引脚电平 / Read current pin level.
 
void Write (bool value) override
 写引脚电平 / Write output pin level.
 
ErrorCode EnableInterrupt () override
 使能当前引脚中断 / Enable GPIO interrupt for current pin.
 
ErrorCode DisableInterrupt () override
 失能当前引脚中断 / Disable GPIO interrupt for current pin.
 
ErrorCode SetConfig (Configuration config) override
 配置当前引脚模式 / Configure GPIO mode for current pin.
 
ErrorCode SetAnalogHighImpedance ()
 将当前 PAD 配置为模拟高阻 / Configure current pad to analog high-impedance.
 
- Public Member Functions inherited from LibXR::GPIO
 GPIO ()
 默认构造函数 / Default constructor.
 
virtual ~GPIO ()=default
 虚析构函数 / Virtual destructor.
 
ErrorCode RegisterCallback (Callback callback)
 注册 GPIO 事件回调函数 / Registers a callback function for GPIO events.
 

Static Public Member Functions

static void CheckInterrupt (uint32_t port)
 分发某一端口的 GPIO 中断回调 / Dispatch GPIO interrupt callbacks for one port.
 

Additional Inherited Members

- Public Types inherited from LibXR::GPIO
enum class  Direction : uint8_t {
  INPUT , OUTPUT_PUSH_PULL , OUTPUT_OPEN_DRAIN , FALL_INTERRUPT ,
  RISING_INTERRUPT , FALL_RISING_INTERRUPT
}
 定义 GPIO 引脚的方向类型 / Defines the direction types for GPIO pins. More...
 
enum class  Pull : uint8_t { NONE , UP , DOWN }
 定义 GPIO 引脚的上拉/下拉模式。 Defines the pull-up/pull-down configurations for GPIO pins. More...
 
using Callback = LibXR::Callback<>
 
- Public Attributes inherited from LibXR::GPIO
Callback callback_
 GPIO 事件的回调函数 / Callback function for GPIO events.
 

Detailed Description

HPM 平台 GPIO 驱动实现 / GPIO driver implementation for HPM platform.

该类将 LibXR GPIO 抽象接口适配到 HPM SDK GPIO API。Read() 和 Write() 分别调用 gpio_read_pin() 与 gpio_write_pin();SetConfig() 调用 gpio_set_pin_input()、gpio_set_pin_output() 和 gpio_config_pin_interrupt(),并在可解析 PAD 时更新 IOC FUNC_CTL、 PAD_CTL 的 GPIO 复用、loopback、上下拉和开漏位。EnableInterrupt() 与 DisableInterrupt() 只支持普通 HPM_GPIO0 中断路径;完整 SDK GPIO 示例说明 FGPIO 不支持中断,因此 HPM_FGPIO 中断请求返回 ErrorCode::NOT_SUPPORT,并且 不会注册到中断分发表。

This class adapts the LibXR GPIO abstraction to HPM SDK GPIO APIs. Read() and Write() call gpio_read_pin() and gpio_write_pin() respectively. SetConfig() calls gpio_set_pin_input(), gpio_set_pin_output(), and gpio_config_pin_interrupt(), and updates IOC FUNC_CTL / PAD_CTL GPIO mux, loopback, pull, and open-drain bits when the PAD can be resolved. EnableInterrupt() and DisableInterrupt() support only the normal HPM_GPIO0 IRQ path; the full SDK GPIO sample states that FGPIO does not support interrupts, so interrupt requests on HPM_FGPIO return ErrorCode::NOT_SUPPORT and are not registered in the interrupt dispatch map.

中断回调由 CheckInterrupt() 统一分发。 Interrupt callbacks are dispatched through CheckInterrupt().

Definition at line 60 of file hpm_gpio.hpp.

Constructor & Destructor Documentation

◆ HPMGPIO()

HPMGPIO::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 对象并注册到中断映射表 / Construct HPM GPIO object and register into interrupt map.

Parameters
gpioGPIO 控制器基地址 / GPIO controller base address.
portGPIO 端口号 / GPIO port index.
pinGPIO 引脚号 / GPIO pin index.
irq当前 port 对应的 PLIC IRQ 号;没有中断需求时可保持默认值 / PLIC IRQ number for the current port. Keep the default when interrupt support is not needed.
pad_indexIOC PAD 编号,默认值表示自动由 (gpio, port, pin) 推导;无法 推导时仍可读写 GPIO,但 PAD 复用和模拟高阻配置会受限 / IOC PAD index. The default auto-resolves it from (gpio, port, pin). If it cannot be resolved, GPIO read/write can still work, while PAD mux and analog high-impedance configuration are limited.

Definition at line 97 of file hpm_gpio.cpp.

99 : gpio_(gpio),
100 port_(port),
101 pin_(pin),
102 irq_(irq),
103 pad_index_(pad_index == INVALID_PAD_INDEX ? ResolvePadIndex(gpio, port, pin)
104 : pad_index)
105{
106 if (port_ < PORT_COUNT && pin_ < PIN_COUNT && !HPM_GPIO_IsFastController(gpio_))
107 {
108 map[port_][pin_] = this;
109 if (port_controller_map[port_] == nullptr)
110 {
111 port_controller_map[port_] = gpio_;
112 }
113 }
114}

Member Function Documentation

◆ CheckInterrupt()

void HPMGPIO::CheckInterrupt ( uint32_t port)
static

分发某一端口的 GPIO 中断回调 / Dispatch GPIO interrupt callbacks for one port.

扫描并分发指定端口的 GPIO 中断 / Scan and dispatch GPIO IRQ callbacks for one port.

Parameters
portGPIO 端口号 / GPIO port index.

由驱动定义的 GPIO 端口中断入口调用。 Called by the GPIO port interrupt entries that the driver defines.

同时会清除触发引脚的中断标志位。 It also clears interrupt flags for triggered pins.

Parameters
portGPIO 端口号 / GPIO port index.

建议在板级 IRQHandler 中仅调用一次该函数:

  • 读取端口中断标志;
  • 逐 pin 清标志;
  • 触发对应对象的 LibXR 回调。 Recommended to call once from board IRQ handler:
  • read port IRQ flags;
  • clear flag per asserted pin;
  • run corresponding LibXR callback.

Definition at line 393 of file hpm_gpio.cpp.

394{
395 if (port >= PORT_COUNT)
396 {
397 return;
398 }
399
400 GPIO_Type* controller = port_controller_map[port];
401 if (controller == nullptr)
402 {
403 return;
404 }
405
406 const uint32_t flags = gpio_get_port_interrupt_flags(controller, port);
407 if (flags == 0u)
408 {
409 return;
410 }
411
412 for (uint8_t pin = 0; pin < PIN_COUNT; ++pin)
413 {
414 if ((flags & (1u << pin)) == 0u)
415 {
416 continue;
417 }
418
419 gpio_clear_pin_interrupt_flag(controller, port, pin);
420 if (auto* gpio = map[port][pin]; gpio != nullptr && gpio->interrupt_enabled_)
421 {
422 gpio->callback_.Run(true);
423 }
424 }
425}

◆ DisableInterrupt()

ErrorCode HPMGPIO::DisableInterrupt ( )
overridevirtual

失能当前引脚中断 / Disable GPIO interrupt for current pin.

失能当前引脚中断 / Disable interrupt for current pin.

Returns
成功返回 ErrorCode::OK;IRQ/端口参数无效返回 ErrorCode::ARG_ERR; HPM_FGPIO 返回 ErrorCode::NOT_SUPPORT;端口路由状态异常返回 ErrorCode::STATE_ERR / Returns ErrorCode::OK on success, ErrorCode::ARG_ERR for invalid irq/port/pin, ErrorCode::NOT_SUPPORT for HPM_FGPIO, and ErrorCode::STATE_ERR when shared port-route state is inconsistent.
Note
HPM SDK gpio_disable_pin_interrupt() 只清当前 pin 的 GPIO IE 位; 共享 PLIC 路由只在同 port 最后一个已启用 pin disable 后关闭 / HPM SDK gpio_disable_pin_interrupt() only clears the current pin's GPIO IE bit; the shared PLIC route is closed only after the last enabled pin on the same port is disabled.

先关闭当前 pin 的 GPIO 事件; 仅当该 port 最后一个已使能 pin 被释放时,才关闭共享的 PLIC 路由。 FGPIO 没有 GPIO 中断能力,按完整 SDK GPIO 示例的约束返回 NOT_SUPPORT。 Disable the current pin's GPIO event first; the shared PLIC route is disabled only after the last enabled pin on the same port is released. FGPIO has no GPIO interrupt capability and returns NOT_SUPPORT according to the full SDK GPIO sample constraint.

Implements LibXR::GPIO.

Definition at line 178 of file hpm_gpio.cpp.

179{
180 if (irq_ == INVALID_IRQ || port_ >= PORT_COUNT || pin_ >= PIN_COUNT)
181 {
182 return ErrorCode::ARG_ERR;
183 }
184 if (HPM_GPIO_IsFastController(gpio_))
185 {
187 }
188
189 HPMGPIOIrqRouteGuard guard;
190 if (!interrupt_enabled_)
191 {
192 return ErrorCode::OK;
193 }
194
195 gpio_disable_pin_interrupt(gpio_, port_, pin_);
196
197 PortIrqRouteState& route = port_irq_route_map[port_];
198 if (route.enabled_pin_count == 0u)
199 {
200 route = {};
201 interrupt_enabled_ = false;
203 }
204
205 if (route.controller != gpio_ || route.irq != irq_)
206 {
207 interrupt_enabled_ = false;
209 }
210
211 --route.enabled_pin_count;
212 if (route.enabled_pin_count == 0u)
213 {
214 const uint32_t route_irq = route.irq;
215 route = {};
216 intc_m_disable_irq(route_irq);
217 }
218
219 interrupt_enabled_ = false;
220 return ErrorCode::OK;
221}
@ STATE_ERR
状态错误 / State error
@ NOT_SUPPORT
不支持 / Not supported
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error

◆ EnableInterrupt()

ErrorCode HPMGPIO::EnableInterrupt ( )
overridevirtual

使能当前引脚中断 / Enable GPIO interrupt for current pin.

使能当前引脚中断 / Enable interrupt for current pin.

Returns
成功返回 ErrorCode::OK;IRQ/端口参数无效返回 ErrorCode::ARG_ERR; HPM_FGPIO 返回 ErrorCode::NOT_SUPPORT;同 port 存在冲突 IRQ 路由返回 ErrorCode::STATE_ERR / Returns ErrorCode::OK on success, ErrorCode::ARG_ERR for invalid irq/port/pin, ErrorCode::NOT_SUPPORT for HPM_FGPIO, and ErrorCode::STATE_ERR when the same port is already routed to another IRQ.
Note
HPM SDK gpio_enable_pin_interrupt() 只设置 GPIO IE 位;PLIC 路由由 intc_m_enable_irq_with_priority() 打开,且同一 port 只在首个 pin enable 时调用 / HPM SDK gpio_enable_pin_interrupt() only sets the GPIO IE bit; PLIC routing is opened through intc_m_enable_irq_with_priority() only when the first pin on the same port is enabled.

对于共享同一 port IRQ 的多个 pin:

  • gpio_enable_pin_interrupt() 始终按 pin 开事件;
  • PLIC 路由只在该 port 首次进入“已使能”状态时打开一次。
  • FGPIO 没有 GPIO 中断能力,按完整 SDK GPIO 示例的约束返回 NOT_SUPPORT。 For multiple pins sharing one port IRQ:
  • gpio_enable_pin_interrupt() always operates per pin;
  • PLIC routing is enabled only once when the first pin on that port becomes active.
  • FGPIO has no GPIO interrupt capability and returns NOT_SUPPORT according to the full SDK GPIO sample constraint.

Implements LibXR::GPIO.

Definition at line 129 of file hpm_gpio.cpp.

130{
131 if (irq_ == INVALID_IRQ || port_ >= PORT_COUNT || pin_ >= PIN_COUNT)
132 {
133 return ErrorCode::ARG_ERR;
134 }
135 if (HPM_GPIO_IsFastController(gpio_))
136 {
138 }
139
140 HPMGPIOIrqRouteGuard guard;
141 if (interrupt_enabled_)
142 {
143 return ErrorCode::OK;
144 }
145
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_))
149 {
151 }
152
153 gpio_enable_pin_interrupt(gpio_, port_, pin_);
154
155 if (needs_port_irq_enable)
156 {
157 route.controller = gpio_;
158 route.irq = irq_;
159 intc_m_enable_irq_with_priority(irq_, 1);
160 }
161
162 ++route.enabled_pin_count;
163 interrupt_enabled_ = true;
164 return ErrorCode::OK;
165}

◆ Read()

bool LibXR::HPMGPIO::Read ( )
inlineoverridevirtual

读取引脚电平 / Read current pin level.

Returns
true 高电平,false 低电平 / true for high level, false for low level.

Implements LibXR::GPIO.

Definition at line 84 of file hpm_gpio.hpp.

85 {
86 const uint32_t level = gpio_read_pin(gpio_, port_, pin_);
87 return level == 1u;
88 }

◆ SetAnalogHighImpedance()

ErrorCode HPMGPIO::SetAnalogHighImpedance ( )

将当前 PAD 配置为模拟高阻 / Configure current pad to analog high-impedance.

将引脚切换为模拟高阻 / Put current pin into analog high-impedance mode.

Returns
成功返回 ErrorCode::OK;port/pin 无效返回 ErrorCode::ARG_ERR; PAD 不可解析返回 ErrorCode::NOT_SUPPORT / Returns ErrorCode::OK on success, ErrorCode::ARG_ERR for invalid port/pin, or ErrorCode::NOT_SUPPORT when PAD is unavailable.
Note
该接口直接写 IOC FUNC_CTL 的 ANALOG 位并清除上下拉和开漏位,未上板前 仍需用实际电气连接确认高阻效果 / This API writes the IOC FUNC_CTL ANALOG bit and clears pull/open-drain bits. The high-impedance effect still needs board-level electrical verification.
如果当前 pin 已经通过 EnableInterrupt() 进入共享 port IRQ 路由,本接口会先 走 DisableInterrupt() 维护引用计数;否则只清当前 pin 的 GPIO IE 位 / If the pin is already routed through EnableInterrupt(), this API first calls DisableInterrupt() to keep the shared port IRQ reference count consistent; otherwise it only clears the current pin's GPIO IE bit.

用途:

  • 该引脚仅作为外部网络连接点,不希望其数字输入/上下拉影响外部 PWM 信号;
  • 例如 PB10 外部跳线到 PA10 时,PA10 需保持高阻避免“分流”。 Usage:
  • Keep this pin from loading an externally driven signal (PWM/analog net);
  • Example: PB10 externally jumpered to PA10, PA10 should stay high-Z.

Definition at line 343 of file hpm_gpio.cpp.

344{
345 if (port_ >= PORT_COUNT || pin_ >= PIN_COUNT)
346 {
347 return ErrorCode::ARG_ERR;
348 }
349
350 if (pad_index_ == INVALID_PAD_INDEX)
351 {
353 }
354
355 if (interrupt_enabled_)
356 {
358 if (ans != ErrorCode::OK)
359 {
360 return ans;
361 }
362 }
363 else
364 {
365 gpio_disable_pin_interrupt(gpio_, port_, pin_);
366 }
367
368 gpio_set_pin_input(gpio_, port_, pin_);
369
370 HPM_IOC->PAD[pad_index_].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK;
371
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;
375
376 return ErrorCode::OK;
377}
ErrorCode DisableInterrupt() override
失能当前引脚中断 / Disable GPIO interrupt for current pin.
Definition hpm_gpio.cpp:178
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes

◆ SetConfig()

ErrorCode HPMGPIO::SetConfig ( Configuration config)
overridevirtual

配置当前引脚模式 / Configure GPIO mode for current pin.

配置 GPIO 方向、中断模式与上下拉 / Configure GPIO direction, interrupt mode, and pull.

Parameters
configGPIO 配置参数 / GPIO configuration.
Returns
成功返回 ErrorCode::OK;port/pin 或枚举值无效返回 ErrorCode::ARG_ERR; HPM_FGPIO 的中断方向或 SDK 未提供双沿枚举时返回 ErrorCode::NOT_SUPPORT / Returns ErrorCode::OK on success, ErrorCode::ARG_ERR for invalid port/pin or enum values, or ErrorCode::NOT_SUPPORT for interrupt directions on HPM_FGPIO or when the SDK does not provide the both-edge enum.
Note
该接口会将 PAD 复用强制切换为 GPIO,不负责外设复用配置 / This API forces pad mux to GPIO function (no peripheral alternate-function setup).
在可解析到 PAD 时会自动开启 IOC loopback,用于输出模式下直接通过 Read() 读取实际引脚电平 / When PAD can be resolved, IOC loopback is enabled so Read() can return the actual pad level even in output mode.

与 STM32 HAL 的常见用法对齐:

  • Direction 对应 GPIO 模式(输入/输出/中断边沿)
  • Pull 对应上拉/下拉配置 Aligned with common STM32 HAL usage:
  • Direction maps to GPIO mode (input/output/IRQ edge)
  • Pull maps to pull-up / pull-down configuration

Implements LibXR::GPIO.

Definition at line 234 of file hpm_gpio.cpp.

235{
236 if (port_ >= PORT_COUNT || pin_ >= PIN_COUNT)
237 {
238 return ErrorCode::ARG_ERR;
239 }
240
241 switch (config.pull)
242 {
243 case Pull::NONE:
244 case Pull::UP:
245 case Pull::DOWN:
246 break;
247 default:
248 return ErrorCode::ARG_ERR;
249 }
250
251 const bool is_interrupt_direction =
252 config.direction == Direction::FALL_INTERRUPT ||
253 config.direction == Direction::RISING_INTERRUPT ||
254 config.direction == Direction::FALL_RISING_INTERRUPT;
255 if (is_interrupt_direction && HPM_GPIO_IsFastController(gpio_))
256 {
258 }
259 if (config.direction == Direction::FALL_RISING_INTERRUPT)
260 {
261#if !defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) || (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT != 1)
263#endif
264 }
265
266 if (pad_index_ != INVALID_PAD_INDEX)
267 {
268 // 保持接口自洽:先确保 PAD 复用到 GPIO / Keep API self-contained: force GPIO mux
269 // first.
270 HPM_GPIO_ConfigMuxToGPIO(gpio_, port_, pad_index_);
271 }
272
273 switch (config.direction)
274 {
275 case Direction::INPUT:
276 gpio_set_pin_input(gpio_, port_, pin_);
277 break;
280 gpio_set_pin_output(gpio_, port_, pin_);
281 break;
283 gpio_set_pin_input(gpio_, port_, pin_);
284 gpio_config_pin_interrupt(gpio_, port_, pin_, gpio_interrupt_trigger_edge_falling);
285 break;
287 gpio_set_pin_input(gpio_, port_, pin_);
288 gpio_config_pin_interrupt(gpio_, port_, pin_, gpio_interrupt_trigger_edge_rising);
289 break;
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);
294 break;
295#else
297#endif
298 default:
299 return ErrorCode::ARG_ERR;
300 }
301
302 if (pad_index_ != INVALID_PAD_INDEX)
303 {
304 uint32_t pad_ctl = HPM_IOC->PAD[pad_index_].PAD_CTL;
305
306 // 仅更新上下拉与开漏位,保留其他电气属性 / Update pull + open-drain bits only.
307 pad_ctl &=
308 ~(IOC_PAD_PAD_CTL_PE_MASK | IOC_PAD_PAD_CTL_PS_MASK | IOC_PAD_PAD_CTL_OD_MASK);
309
310 switch (config.pull)
311 {
312 case Pull::NONE:
313 break;
314 case Pull::UP:
315 pad_ctl |= IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1);
316 break;
317 case Pull::DOWN:
318 pad_ctl |= IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(0);
319 break;
320 }
321
322 if (config.direction == Direction::OUTPUT_OPEN_DRAIN)
323 {
324 pad_ctl |= IOC_PAD_PAD_CTL_OD_SET(1);
325 }
326
327 HPM_IOC->PAD[pad_index_].PAD_CTL = pad_ctl;
328 }
329
330 return ErrorCode::OK;
331}
@ 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.
@ UP
上拉模式 / Pull-up mode.

◆ Write()

void LibXR::HPMGPIO::Write ( bool value)
inlineoverridevirtual

写引脚电平 / Write output pin level.

Parameters
valuetrue 高电平,false 低电平 / true for high level, false for low level.

Implements LibXR::GPIO.

Definition at line 95 of file hpm_gpio.hpp.

96 {
97 gpio_write_pin(gpio_, port_, pin_, value ? 1u : 0u);
98 }

The documentation for this class was generated from the following files: